gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Beginners > intro before game...

#19217 - darknet - Wed Apr 14, 2004 4:52 am

A long time ago I posted a question involving button taps versus presses, and since I have used the code given to me to effectively differentiate between the two.

However, I am having an odd problem that I cannot seem to fix. I have 3 mini-games, each equipped with its own set of introduction screens. To shift through each intro screen, the user presses the 'A' button. However, the last intro screen goes directly into the game without caring about a prompt from the user. In another words, when I press 'A' on the 2nd of three intro screens, the third is quickly shown on the screen and the game is started. Rather, I would like to the game only to begin on the user's input on the third screen. Here the code in question:

Code:

void showDefenderIntro() {

   int previousButton, button, down, up;

   setMode(MODE_3 | BG2_ENABLE);
   drawMode3Background(videoBuffer, defenderIntroOne_Bitmap);
   waitForVSync();

    while(defend_state !=IN_DEFENDER) {

      button = *BUTTONS ^ 0x03ff;
      down = button & ~previousButton;   //pressed since last loop
      up = previousButton & ~button;    //released since last loop

      if( (down & A_BUTTON) !=0) {

            switch(defend_state) {

               case SECOND_DEFENDER_INTRO:
                  drawMode3Background(videoBuffer, defenderIntroTwo_Bitmap);
                  defend_state = FINAL_DEFENDER_INTRO;
                  break;

               case FINAL_DEFENDER_INTRO:
                  drawMode3Background(videoBuffer, defenderIntroThree_Bitmap);
                  defend_state = IN_DEFENDER;
                  break;
            }
        }
         previousButton = button;
         waitForVSync();
   }
}

#19219 - sgeos - Wed Apr 14, 2004 5:35 am

First of all, the local variables (previousButton, button, down, up) are never initialized. Second, it looks like there is a global variable, defend_state. What is the value of defend_state at the onset of showDefenderIntro()? When and how is it set to SECOND_DEFENDER_INTRO?

It seems to me that the above posted code could be a little better organized. I'd make it look something like this:
Code:
void showDefenderIntro()
{
   // Declare variables here

   // Draw initial background
   // initialize variables

   while(defend_state !=IN_DEFENDER) {

      waitForVSync(); // Only called in one spot

      // Button updates here
      previousButton = button; // This is button update code

      // Demo change on A_BUTTON here

   }
}


If it is assumed that the function exits during a vblank, I would keep the waitForVSync() calls as they are.

I did not step through the button logic, but it seems like different operations would need to be done to test for a press and a release?

-Brendan

#19230 - TheMikaus - Wed Apr 14, 2004 7:22 pm

I'm currently at school, so I'm not entirely sure that the following will even compile but it looks right to me. Again. I just started so it might not work at all! So sorry if I waste your time. Oh and don't forget to insert the correct value for all ones as mine just has the text all ones.

Code:
void showDefenderIntro() {

   int previousButton, down, up;
   
   previousButton = *BUTTONS; //Get the value of the register (it's all 1's when up)

   down = 0;
   up = 1;

   /*if it's all one's then it's all up and a ! on all 1's will give zero
   which is false.   however a ! on not all ones will produce a value which is greater than zero (true).
*/
   if(!previousButton)
   {
    down = 1;
   up = 0;
   }


   setMode(MODE_3 | BG2_ENABLE);
   drawMode3Background(videoBuffer, defenderIntroOne_Bitmap);
   waitForVSync();

    while(defend_state !=IN_DEFENDER) {

      previousButton = *BUTTONS;

     //If they are pressing something and they have released the keys
      if(!previousButton && up)
   {
      down = 1;
   }           
      //if all keys are up, set no keys pressed and up to true
      else if(previousButton == (Whatever value all ones would be))
      {
         down = 0;
         up = 1;
      }

//if it was released and then pressed
      if( (down & up)) {

            switch(defend_state) {

               case SECOND_DEFENDER_INTRO:
                  drawMode3Background(videoBuffer, defenderIntroTwo_Bitmap);
                  defend_state = FINAL_DEFENDER_INTRO;
 
//The button hasn't been released so tell the loop that
        up = 0;
                  break;

               case FINAL_DEFENDER_INTRO:
                  drawMode3Background(videoBuffer, defenderIntroThree_Bitmap);
                  defend_state = IN_DEFENDER;
                  break;
            }
        }

         waitForVSync();
   }
}


Again if it doesn't work. Sorry. Looks kinda ok to me.

#19238 - MumblyJoe - Thu Apr 15, 2004 1:20 am

Ok, I am going to make a couple of assumptions and give you a class I wrote the other day to solve a similar problem. I am assuming you can use C++ or at least read it well enough to get what it does. Basically you pass the ctor a key (a u16 representing the bit that key uses, should be in everyones shitty gba.h) and two callback functions with the second one (for up) bieng optional. Then go into a loop or whatever which calls the Check() member of the class. I just wrote this to solve a very simple problem where interrupts etc was unneccessary, and have found it pretty reliable. Oh, one other assumption, you have a pressed function (or macro if you wish) to test keys.

Code:

class CallBack
{
    public:
    typedef void(*voidvoid)();
    CallBack(const u16 k,voidvoid down, voidvoid up=0)
    :keyer(k),downer(down),upper(up),current(false){}
    void Check()
    {
         if((Pressed(keyer)==true)&&(current==false))
            {
            if(downer)
                downer();
            current = true;
            }
         else
             if((Pressed(keyer)==false)&&  (current==true))
                 {
                 if(upper)
                     upper();
                 current = false;
                 }
    }
    private:
    u16 keyer;
    voidvoid upper;
    voidvoid downer;
    bool current;
};

_________________
www.hungrydeveloper.com
Version 2.0 now up - guaranteed at least 100% more pleasing!