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.

C/C++ > input from multiple keys...

#1751 - Malefactor - Wed Jan 22, 2003 4:22 pm

My C is a little shakey so I'm asking for help.

I currently use this code to check if select is pressed
Code:
if(!(*KEYS & KEY_SELECT))
{
}

Would this check if Select and A are pressed at the same time?
Code:
if(!(*KEYS & KEY_SELECT))
{
    if(!(*KEYS & KEY_A))
    {
    }
}

Or is there a more efficient way of doing it?
_________________
[Images not permitted - Click here to view it]

#1753 - Vortex - Wed Jan 22, 2003 4:27 pm

This one seems to be a little bit more efficient IMHO:

Code:

if(!(*KEYS & (KEY_SELECT | KEY_A)))
{
// ...
}

#1777 - Malefactor - Wed Jan 22, 2003 11:29 pm

ty
_________________
[Images not permitted - Click here to view it]

#1789 - satanicfreak2 - Thu Jan 23, 2003 4:42 am

what if you wanted to have a combination of buttons pressed... like for example trowing a fire ball. down, then left, then b??

#1792 - Malefactor - Thu Jan 23, 2003 5:23 am

Code:
if(!(*KEYS & (KEY_DOWN | KEY_LEFT | KEY_B)))
{
// ...
}


I think...

SatanicFreak2:
On a whim I went to your website and downloaded blocks..
Thank you for showing me how to save and load from sram!
_________________
[Images not permitted - Click here to view it]

#1821 - peebrain - Thu Jan 23, 2003 6:14 pm

Just a little tip... Assuming your KEYS is #define'd to be the actual memory address of the keyboard input address, you'll want to store the value in another variable, then use that variable for checking against key states.

i.e.:
Code:

int theKeys = *KEYS;
if (theKeys & KEY_A && theKeys & KEY_SELECT)
{
//whatever
}


The reason for that being that there is a slight chance the key state could change while checking whether a button is being hit or not. Depending on how slow/fast your code is, that could lead to missed inputs, or contradicting inputs. Say, for example, if the user pushes A or B, a menu comes up. If the user pushes B though, you want to make a sound (stupid example, I know). If your code was like:

Code:

if (*KEYS & KEY_A || *KEYS & KEY_B)
{
// do menu
  if (*KEYS & KEY_B)
  {
  //do sound
  }
}


Then the KEYS could change while doing the menu, and you could miss the B input. If you saved it in a variable it wouldn't have that problem.

This post is much too long to explain what I'm trying to explain... :-P.

~Sean

#1826 - Vortex - Thu Jan 23, 2003 7:55 pm

Sean,

The probability for that to happend is close to zero, but you have a point. However I am afraid your IF statements will never work because the GBA keypad register reacts to pressing keys by turning bits to zero, so you still need the ! operator, i.e. in their currect form the IFs will trigger if the keys are NOT pressed.

Just my $0.02.

#1829 - Malefactor - Fri Jan 24, 2003 12:00 am

thanx for the tip peebrain, I will implement it and see if it improves the responsiveness of my proggie...

their may be almost no chance of such a thing happening, but it will only take me a few seconds to eliminate that change altogether.
_________________
[Images not permitted - Click here to view it]

#1832 - ampz - Fri Jan 24, 2003 12:40 am

No keypad code, no matter how ugly you write it, will affect the responsiveness of your game. (ok, unless you introduce delay loops)

#1834 - peebrain - Fri Jan 24, 2003 3:08 am

Oh yeah, forgot about that crazy ! stuff... thanks Vortex.

Nonetheless, it's good programming practice, in my opinion. Of course, I started writting games in Qbasic on a 386, so I instinctually write code that works better on slow machines :-P. I guess for the GBA it really isn't necessary unless theres some odd special case...

~Sean

#1836 - Malefactor - Fri Jan 24, 2003 3:16 am

BTW I also need to check for any key being pressed, so if | is 'and'...
what is 'or'?
_________________
[Images not permitted - Click here to view it]

#1837 - nolanjurgens - Fri Jan 24, 2003 5:34 am

| is the bitwise OR operator, & is the bitwise AND operator.

#1839 - satanicfreak2 - Fri Jan 24, 2003 6:01 am

Malefactor, you are welcome.

#1852 - Malefactor - Fri Jan 24, 2003 2:11 pm

ok, that's what I thought... But I guess I forgot about the ! and was thinking that | was and because of it...

so would
(!(*KEYS & (KEY_DOWN & KEY_LEFT & KEY_B)))
be true if any of those keys were being pressed?
_________________
[Images not permitted - Click here to view it]

#1854 - Splam - Fri Jan 24, 2003 3:59 pm

You probably want to | together the keys and then & the result with the key register.

eg (if the following bits were correct) ;)

KEY_DOWN=0001
KEY_LEFT= 0010
KEY_B = 0100

your method would produce
0001 & 0010 & 0100 = 0000
and then you'd check 0000 against the button register

#1893 - satanicfreak2 - Sat Jan 25, 2003 3:37 am

the best way to do it is to check if both are being pressed at the same time.
Code:
 if ( (! ((*KEYS) & KEY_UP) )&&(! ((*KEYS) & KEY_LEFT) ))
  {

// code goes in here

  }


at least thats how i do it.

#1928 - Malefactor - Sun Jan 26, 2003 2:01 am

ty ppl
_________________
[Images not permitted - Click here to view it]

#1932 - imikeyi - Sun Jan 26, 2003 6:40 am

What about if you want a series of commands, such as a fireball in SF2, ie down, down-forward, forward, punch. Would you nest if statements such as:

Code:

if down then
    if down-forward then
          if forward
              do fireball


Personally I think this would be too fast to work.

Or would you test for the sequence per frame, eg in your control handling code
Code:

if down then
    do down action
    fireball = 1
if down-forward then
    do down-forward action
    if fireball=1 then fireball++;
if forward then
    do forward action
    if fireball=2 then fireball++;
if fireball = 3 then do fireball


(Sorry for the pseudocode!)
_________________
microkernel advance

#1936 - tepples - Sun Jan 26, 2003 9:54 am

If I were writing a side-view 2D fighting game in the style of Capcom's Street Fighter II, I would detect key-down events, queue them up, and use string matching on the queue.

Pseudocode follows:
Code:

/* find which buttons were just pressed */
cur_joy = (JOY & 0x3ff) ^ 0x3ff;  /* read controller and convert result to active-high */
just_pressed = cur_joy & ~last_joy;  /* find new presses */

/* add relevant events to queue */
for(i = 0; i < 10; i++)
  if(just_pressed & (1 << i))  /* check each bit */
    add_to_queue(i);

/* prime next iteration */
last_joy = cur_joy;


Then you can detect a fireball by looking at the end of the queue for for 7 4 1 (Down Right B) if facing right or 7 5 1 (Down Left B) if facing left. A dragon punch would be Right Down Right B (4 7 4 1) if facing right or Left Down Left B (5 7 5 1) if facing left. A Zangief-style circle throw would be Right Down Left Up B (4 7 5 6 1) if facing right, etc. My method also lets beginners use mortal kombat style flange moves (down, release, left, release, B) before they learn the smooth SF2 motions.

But if you're writing a fighting game, you have to take into account that experienced players will be able to make controller motions faster than 60fps, and so 60fps polling won't feel as accurate as 180fps polling. You can get 180fps by polling the controller three times a frame: at approximately lines 0, 80, and 160. A 180fps poll rate should be fast enough to capture the fastest controller motions but slow enough not to get confused by contact bounce.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#1986 - Malefactor - Mon Jan 27, 2003 6:12 am

I was going to say sequence because nested if statements will mean they'd either have to press them all at once or ungodly fast...

Queuing seems like the better way..
_________________
[Images not permitted - Click here to view it]