Author Topic: How do I use the Zero's buttons as input for my app?  (Read 1495 times)

SnakiestD (OP)

  • *
  • Posts: 7
How do I use the Zero's buttons as input for my app?
« on: September 29, 2014, 11:43:18 pm »
Hey so I only have a few hours worth of c++ coding experience, so be nice.  :P
I wanted to create a game for my GCW-Zero, so I installed the toolchain and I have been using code::blocks to make apps. When compiled to run on my computer, they run great and all is well about that. This is an example of what I've been messing around with:

Code: [Select]
    // A red seed with grow into a flower when planted in the sunlight.
    // Otherwise it will grow into a mushroom.
    // Assuming the conditions are correct for growing a flower
    // ..planting a blue seed in wet soil will produce a sunflower..
    // ..while planting a blue seed in dry soil will produce a dandelion.

    // A blue seed with grow into a flower when planted in the dark.
    // Otherwise it will grow into a mushroom.
    // Assuming the conditions are correct for growing a flower
    // ..planting a blue seed in wet soil will produce a dandelion..
    // ..while planting a blue seed in dry soil will produce a sunflower.

    // User inputs the seed colour, whether in sunlight or not, and if the soil is wet or dry.
    // Machine outputs what will grow.

    // Code:

    #include <iostream>
    #include <string>
    using namespace std;

    int main()
    {

        // Get seed colour.
        string seedColour = "";
        cout << "Enter the colour of your seed (red or blue): \n";
        cin >> seedColour;

        if(seedColour != "red" && seedColour != "blue")
        {
            cout << "I don't know much about " << seedColour << " seeds. Please pick red or blue.\n";
            return 0;
        }

        // Get sunlight conditions.
        string sunlightConditions = "";
        cout << "Enter the sunlight conditions of the seed (bright or dim): \n";
        cin >> sunlightConditions;

        if(sunlightConditions != "bright" && sunlightConditions != "dim")
        {
            cout << "I'm only a computer. I don't know how bright " << sunlightConditions << " is. Please pick bright or dim\n";
            return 0;
        }

        // Get moisture of soil.
        string soilMoisture = "";
        cout << "Enter the soil moisture (wet or dry): \n";
        cin >> soilMoisture;

        if(soilMoisture != "wet" && soilMoisture != "dry")
        {
            cout << "I have never heard of " << soilMoisture << " soil before. Please pick wet or dry\n";
            return 0;
        }
        // If red seed
        if(seedColour == "red")
        {
            // If sunlight = true
            if(sunlightConditions == "bright")
            {
                // If soil is wet
                if(soilMoisture == "wet")
                {

                    // Output sunflower
                    cout << "A sunflower will grow.\n";
                }
                // If soil is dry
                else
                {
                    // Output dandelion
                    cout << "A dandelion will grow.\n";
                }
            }
            // Otherwise
            else
            {
                // Output mushroom
                cout << "A mushroom will grow.\n";
            }
        }

        // If blue seed
        else
        {
            // If sunlight = false
            if(sunlightConditions == "dim")
            {

                // If soil is wet
                if(soilMoisture == "wet")
                {

                    // Produce dandelion
                    cout << "A dandelion will grow.\n";
                }
                // If soil is dry
                else
                {
                    // Produce sunflower
                    cout << "A sunflower will grow.\n";
                }
            }

            // Otherwise
            else
            {
                // Output mushroom
                cout << "A mushroom will grow.\n";
            }
        }
    }

I have also worked out how to create OPK files and getting the apps to run on my GCW-Zero.
The apps run great, but my only problem is:
I don't know how to assign the buttons as inputs.

My goal right now is to create a text-based adventure game, where the program outputs something like: "Press A to do action 1, B to do action 2, etc", and then the user presses one of the buttons, and the previous text outputted from the machine is cleared, and the input from the user is never visible. The program would then of course repeat "Press A to do a new action 1, B to do a new action 2"

When I run the apps I've made on my Zero, pressing left on the dpad will input "^[[D", and right will input "^[[C", pressing y inputs a space and pressing R deletes the previous character. I think pressing start is the same as enter on my computer.

Should I just do something like this?

Code: [Select]
int main()
{
    string keyPressed = ""
    cout << "Press left to do action 1 and right to do action two\n"
    cin >> keyPressed
   if(keyPressed == "^[[D"
    {
        //do action 1
    }
    if(keyPressed == "^[[C"
    {
        //do action 2
    }
}

If that is the correct way of doing it, what about the face buttons that aren't showing any input (A, X, B)

Thank you.

Senor Quack

  • *
  • Posts: 215
Re: How do I use the Zero's buttons as input for my app?
« Reply #1 on: September 30, 2014, 01:55:56 am »
The buttons are indeed mapped to keypresses, but not in a way that is fully usable from a console terminal program.  You will be limited in the buttons you can actually read (because many of the buttons are mapped to key-modifiers like CONTROL, SHIFT, etc, for reasons of backward compatibility with the Dingoo device our OS evolved from.) 

You should instead be using SDL for input, and, ideally, output:   http://wiki.surkow.com/Tutorials:SDL

Scroll halfway down and you will find the implementation details of reading the device's buttons.   Note: that example uses SDL's event-driven input.  You can instead use a polled reading of input, which is what I often prefer..  Here is an untested example of code that uses this method I quickly whipped up just now:
Code: [Select]
#define GCW_DPAD_UP 0
#define GCW_DPAD_DOWN 1
#define GCW_DPAD_LEFT 2
#define GCW_DPAD_RIGHT 3
#define GCW_A 4
#define GCW_B 5
#define GCW_X 6
#define GCW_Y 7
#define GCW_L 8
#define GCW_R 9
#define GCW_SELECT 10
#define GCW_START 9
#define GCW_POWER 12
#define GCW_HOLD 13
#define GCW_BUTTON_COUNT 14

unsigned int gcw_buttons[GCW_BUTTON_COUNT];

const unsigned int buttons_to_keymap[GCW_BUTTON_COUNT] = {
SDLK_UP,
SDLK_DOWN,
SDLK_LEFT,
SDLK_RIGHT,
SDLK_LCTRL,
SDLK_LALT,
SDLK_LSHIFT,
SDLK_SPACE,
SDLK_TAB,
SDLK_BACKSPACE,
SDLK_ESCAPE,
SDLK_RETURN,
SDLK_HOME,
SDLK_PAUSE
};

/* Only needs to be executed once after SDL and its input subsystem has been initialized: */
void init_keyboard_input(void)
{
SDL_EnableKeyRepeat(0, 0); // No key repeat
SDL_EventState(SDL_KEYDOWN, SDL_IGNORE); //Disable events for keyboard
SDL_EventState(SDL_KEYUP, SDL_IGNORE); // Disable events for keyboard
}

/* Executed once each time input is needing to be read: */
void control_update(void)
{
SDL_PumpEvents();
Uint8 *keystate = SDL_GetKeyState(NULL);
if (keystate) {
int i;
for (i=0; i < GCW_BUTTON_COUNT; i++)
gcw_buttons[i] = keystate[buttons_to_keymap[i]];
} else {
printf("Error: Unable to retreive SDL keyboard state!\n");
}
}

Since you are using Code::Blocks to cross-compile with SDL, it will take a good bit of configuration.   Here is the official Wiki Tutorial: http://wiki.surkow.com/Tutorials:CodeBlocks     Here is a forum thread to help you further if-need-be:  http://boards.dingoonity.org/gcw-development/programing-in-windows-with-codeblocks/

If you choose to use a Makefile to compile with, instead of Code::Blocks' built in compilation wizards, here is an example Makefile:    http://wiki.surkow.com/Makefile   
« Last Edit: September 30, 2014, 08:05:46 am by Senor Quack »

SnakiestD (OP)

  • *
  • Posts: 7
Re: How do I use the Zero's buttons as input for my app?
« Reply #2 on: September 30, 2014, 02:32:48 am »
The buttons are indeed mapped to keypresses, but not in a way that is fully usable from a console terminal program.  You will be limited in the buttons you can actually read (because many of the buttons are mapped to key-modifiers like CONTROL, SHIFT, etc, for reasons of backward compatibility with the Dingoo device our OS evolved from.) 

You should instead be using SDL for input, and, ideally, output:   http://wiki.surkow.com/Tutorials:SDL

Scroll halfway down and you will find the implementation details of reading the device's buttons.   Note: that example uses SDL's event-driven input.  You can instead use a polled reading of input, which is what I often prefer..  Here is an untested example of code that uses this method I quickly whipped up just now:
Code: [Select]

#define GCW_DPAD_UP 0
#define GCW_DPAD_DOWN 1
#define GCW_DPAD_LEFT 2
#define GCW_DPAD_RIGHT 3
#define GCW_Y 4
#define GCW_B 5
#define GCW_X 6
#define GCW_A 7
#define GCW_SELECT 8
#define GCW_START 9
#define GCW_L 10
#define GCW_R 11
#define GCW_POWER 12
#define GCW_HOLD 13
#define GCW_BUTTON_COUNT 14

unsigned int gcw_buttons[GCW_BUTTON_COUNT];

const unsigned int buttons_to_keymap[GCW_BUTTON_COUNT] = {
SDLK_LEFT,
SDLK_RIGHT,
SDLK_UP,
SDLK_DOWN,
SDLK_LCTRL,
SDLK_LALT,
SDLK_LSHIFT,
SDLK_SPACE,
SDLK_TAB,
SDLK_BACKSPACE,
SDLK_ESCAPE,
SDLK_RETURN,
SDLK_HOME,
SDLK_PAUSE
};

/* Only needs to be executed once after SDL and its input subsystem has been initialized: */
void init_keyboard_input(void)
{
SDL_EnableKeyRepeat(0, 0); // No key repeat
SDL_EventState(SDL_KEYDOWN, SDL_IGNORE); //Disable events for keyboard
SDL_EventState(SDL_KEYUP, SDL_IGNORE); // Disable events for keyboard
}


/* Executed once each time input is needing to be read: */
void control_update(void)
{
SDL_PumpEvents();
Uint8 *keystate = SDL_GetKeyState(NULL);
if (keystate) {
int i;
for (i=0; i < GCW_BUTTON_COUNT; i++)
gcw_buttons[i] = keystate[buttons_to_keymap[i]];
} else {
printf("Error: Unable to retreive SDL keyboard state!\n");
}
}

Since you are using Code::Blocks to cross-compile with SDL, it will take a good bit of configuration.  Here is a forum thread to help you with that:    http://boards.dingoonity.org/gcw-development/programing-in-windows-with-codeblocks/

If you choose to use a Makefile to compile with, instead of Code::Blocks' built in compilation wizards, here is an example Makefile:    http://wiki.surkow.com/Makefile   

Thank you! I don't understand much of what you said but hopefully I'll be able to figure it out with a little bit of Google.

Senor Quack

  • *
  • Posts: 215
Re: How do I use the Zero's buttons as input for my app?
« Reply #3 on: September 30, 2014, 04:36:02 am »
Hi, I found mistakes in my key mapping in the code I posted, please use the updated code in my original post!

 

Post a new topic