|
Post by smiling123 on Oct 7, 2014 20:25:25 GMT -8
Hi, I would like to ask on the screen navigation for Gameduino 2. I have looked through the "widgets" demo and I might have misunderstood the get_input script. What I meant was I needed to get the buttons to work in such way that e.g user presses button 1, it will change into another view, showing something. If user presses button 2, its another view etc. So how may I implement this simple navigation?
|
|
|
Post by dgustavus on Oct 14, 2014 6:12:03 GMT -8
Hi, One option which I have used is to put a group of buttons with tags for the various screen draw functions you want to invoke. You can think of this group of buttons as menu buttons, and they need to be present on all the screens. Out of the loop() I call a function named displayscreen() which is little more than a case statement that invokes different screen draw functions based on a global variable I named scrNumber. In every screen draw function, the same group of menu buttons appears along with a case statement based on the button tag which changes the global scrNumber. The next time loop() calls displayscreen(), the different screen draw function invoked will be based on the last button pressed.
A simple solution, but hope it helps. Duane
|
|
|
Post by BenYam on Dec 14, 2014 6:33:28 GMT -8
Hi,
yes, using tags is a great idea. My method is that I assume a programe to be a state machine. First, I define states like:
#define STATE_WAITING_LOGIN 0 #define STATE_GAME_RUNNING 1 #define STATE_WAITING_CONFIG 2 ... static byte State;
In the Setup() routine, I set an initial state and show the first screen, which may be a keyboard for login theuser:
State = STATE_WAITING_LOGIN; Keyboard1.SetData(Config.Player, "Enter player's name"); Keyboard1.Show();
In the main loop, I service necessary inputs, call redrawing of all the screens and make another things as needed, and - the most important - set the State to an appropriate value according the inputs and context:
GD.ClearColorRGB(0xDDDDFF); GD.Clear();
// getting tag from touch: GetInputs(&X, &Y, &Z, &Tag); switch (Tag) { case TAG_MAIN_MENU: { State = STATE_WAITING_CONFIG; ConfigDlg1.SetCaption("Settings"); ConfigDlg1.Show(); } break; default: break; }
DrawStatusBar (Config.Player, 3, 2, true, Tag);
DrawMenu (MAXX-90-2, MAXY-BARH, 90, BARH-1, "Options");
DrawBalls();
//DrawIcons();
//servicing keyboard: Keyboard1.Draw(); switch (Keyboard1.ModalResult) { case MR_OK: { switch (State) { case STATE_WAITING_LOGIN:{ Keyboard1.GetData(Config.Player, 16); State = STATE_GAME_RUNNING; } break; } } break; case MR_CANCEL: State = STATE_GAME_RUNNING; break; }
// servicing ConfigDlg: ConfigDlg1.Draw(); switch (ConfigDlg1.ModalResult) { case MR_OK: { switch (State) { case STATE_WAITING_CONFIG: { ConfigDlg1.GetData(&Config.ShowNames, &Config.ShowAlert); State = STATE_GAME_RUNNING; } break; } } break; case MR_CANCEL: State = STATE_GAME_RUNNING; break; }
// redraw whole screen: GD.swap();
// change the state: switch (State) { case STATE_WAITING_LOGIN: break; case STATE_GAME_RUNNING: DoMovements(); break; default: break; }
while ConfigDlg1, Keyboard1, etc. are my classes. They have their own methods Draw(), Show(), Hide(), SetData(), GetData() etc., e.g.
class TKeyboard { public: TKeyboard(); void Draw(); void Show(); void Hide(); void SetData(char* aData, char* aCaption); void GetData(char* aData, int aMaxLen); int ModalResult; char InputText[MAXINPUT+1]; char Caption[MAXCAPTION+1]; private: boolean Visible; byte prevkey; byte CursorPos; };
static TKeyboard Keyboard1;
At the beginning of all Draw() methods, there is a test for visibility of the object, so that if the object should not be visible at the specific moment, it just skips out and doesn't draw:
void TKeyboard::Draw() { if (!Visible) return; // main frame Rectangle (90, 50, 300, 168, 8, LIGHT_GREEN, 255); Rectangle (93, 56, 294, 162, 8, BLACK, 255); // caption Rectangle (100, 37, 280, 12, 8, LIGHT_GREEN, 255); Rectangle (101, 38, 278, 9, 8, BLACK, 255); DrawText (105, 37, 21, LIGHT_GRAY, 255, Caption);
// input line byte key = GD.inputs.tag; if (prevkey==0x00) { switch (key) { //case TAG_MAIN_MENU: Visible = true; break; case TAG_ENTER: ModalResult=MR_OK; Hide(); break; case TAG_ESCAPE: ModalResult=MR_CANCEL; Hide(); break; case TAG_BACK: { // backspace if (CursorPos>0) { InputText[CursorPos-1]=0; CursorPos--; } } break; default: { if ((key>=' ') && (key < 0x7f)) { if (CursorPos < MAXINPUT) { InputText[CursorPos] = key; CursorPos++; InputText[CursorPos] = 0; } } break; } } } prevkey = key; Rectangle (105, 62, 245, 15, 4, LIGHT_GRAY, 255); DrawText (105, 61, 21, BLACK, 255, InputText); GD.Tag(255); // keyboard GD.ColorRGB(LIGHT_GRAY); GD.cmd_keys(80, 88, 300, 24, 28, OPT_FLAT | OPT_CENTER | key, "1234567890"); GD.cmd_keys(80, 88 + 26, 300, 24, 28, OPT_FLAT | OPT_CENTER | key, "QWERTYUIOP"); GD.cmd_keys(80, 88 + 52, 300, 24, 28, OPT_FLAT | OPT_CENTER | key, "ASDFGHJKL"); GD.cmd_keys(80, 88 + 78, 300, 24, 28, OPT_FLAT | OPT_CENTER | key, "ZXCVBNM,."); GD.Tag(' '); GD.cmd_button(160, 88+107, 133, 24, 28, OPT_FLAT, ""); GD.Tag(TAG_BACK); GD.cmd_button(356, 58, 30, 24, 28, OPT_FLAT, "<"); GD.Tag(TAG_ENTER); GD.cmd_button(352, 88+70, 40, 24, 28, OPT_FLAT, "OK"); GD.Tag(TAG_ESCAPE); GD.cmd_button(352, 85+105, 40, 24, 28, OPT_FLAT, "X"); }
sorry for formatting, too many indents 
Milan
|
|