#8683 - immortalninjak - Thu Jul 17, 2003 11:41 pm
Hi,
just started out GBA programming and have been playing around with a program that counts how many times you push the buttons and displays it.
It works by incrementing a variable count by one for every button that is pressed during the getinput() method call.
However this means that count increases if you just hold on to the buttons.
My question is: is there a simple way disable a buton until it has been released and pressed again?
At the moment my solution has been to have an extra variable for each button and an extra method checkre() which is called after getinput()
for example for the up button:
Code: |
getinput(){
if( up==0){
if(!(*KEYS & KEY_UP)){
count++;
up = 1;
}
}
}
checkre(){
if(*KEYS & KEY_UP){
up = 0;
}
}
|
any help or opinions would be great thanks
#8689 - XeroxBoy - Fri Jul 18, 2003 3:45 am
You could just add an else to the if in getinput().
#8690 - night_ - Fri Jul 18, 2003 3:46 am
I had a quick look and I think the following (untested) code does the job. I didn't investigate deeper, maybe there are "better" solutions:
Code: |
get_input()
{
if(!(*KEYS & KEY_UP))
{
if(!up)
{
++count;
up = 1;
}
}
else
{
up=0;
}
} |
[/code]
#8691 - night_ - Fri Jul 18, 2003 3:47 am
XeroxBoy was one minute faster ;-)
#8692 - XeroxBoy - Fri Jul 18, 2003 3:53 am
p433r me :D
#8694 - sgeos - Fri Jul 18, 2003 4:06 am
It looks like you've figured it out, but here is the code I use:
Code: |
#define AGB_KEY_MAX 2
#define AGB_KEY_RESET 1
#define AGB_A 0
#define AGB_B 1
#define AGB_SELECT 2
#define AGB_START 3
#define AGB_RIGHT 4
#define AGB_LEFT 5
#define AGB_UP 6
#define AGB_DOWN 7
#define AGB_R 8
#define AGB_L 9
unsigned long press[10];
unsigned long release[10];
void key_refresh(void)
{
int ctr;
for (ctr = 0; ctr < 10; ctr++)
{
if ((*(volatile unsigned short *)0x04000130 >> ctr) & 0x1)
{
if (release[ctr])
{
press[ctr] = 0;
release[ctr] = 0;
}
if (press[ctr])
release[ctr] = 1;
}
else
{
press[ctr]++;
if (press[ctr] > AGB_KEY_MAX)
press[ctr] = AGB_KEY_RESET;
}
}
}
void key_zero(void)
{
int ctr;
for (ctr = 0; ctr < 10; ctr++)
{
press[ctr] = 0;
release[ctr] = 0;
}
} |
The button press code is initiatialized with key_zero(). key_refresh() needs to be called every frame. You can check to see if a button is pressed or released with:
Code: |
if (press[AGB_A])
// Do the A thing
if (release[AGB_START])
// Do the start thing |
You can see how long the button has been held down by looking at the value in press[AGB_pick_a_button]. There is a macro that can be changed that affect how big the press values go, AGB_KEY_MAX. There is also a macro that affects what happens to the value when it reaches max, AGB_KEY_RESET.
-Brendan
#8716 - col - Fri Jul 18, 2003 3:44 pm
this trick won't disable keys, or read key releases, but for counting keypresses and for other stuff you can do :
Code: |
//globals, or members of class Keypad
u16 newkeys = 0;
u16 keys = 0;
//call this per frame
void updateKeys(){
newKeys = KEYS ^ keys & KEYS;
keys = KEYS;
}
|
can't remember off-hand if KEYS is the inverse of the keypad reg contents:
the main thing is that KEYS has a 1 for a key being pressed, and a 0 for not being pressed.
keys == which buttons are being pressed
newKeys == which buttons have been pressed since the last frame
so to do a count of eg START key presses:
Code: |
if(newKeys & KEY_START){
++startKeyCount;
}
|
I hope this helps
cheers
Col
#8810 - col - Sun Jul 20, 2003 6:14 pm
its easy to adapt the above code to give you key releases:
Code: |
//globals, or members of class Keypad
u16 newkeys = 0;
u16 keys = 0;
u16 keysReleased = 0;
//call this per frame
void updateKeys(){
newKeys = KEYS ^ keys & KEYS;
keysReleased = KEYS ^ keys & keys;
keys = KEYS;
}
|
keys == which buttons are being pressed
newKeys == which buttons were just pressed
keysReleased == which buttons were just released
cheers
Col
#8869 - immortalninjak - Tue Jul 22, 2003 3:12 pm
thanks all.
Combined this with a count down and text prog to get a mini game of sorts
#10318 - whells - Tue Sep 02, 2003 12:13 pm
col wrote: |
Code: |
//globals, or members of class Keypad
u16 newkeys = 0;
u16 keys = 0;
u16 keysReleased = 0;
//call this per frame
void updateKeys(){
newKeys = KEYS ^ keys & KEYS;
keysReleased = KEYS ^ keys & keys;
keys = KEYS;
}
|
keys == which buttons are being pressed
newKeys == which buttons were just pressed
keysReleased == which buttons were just released
cheers
Col |
I have an Question . . .
if i use the code
whe i declare th KEYS in Keypad.h
u16* KEYS = (u16*)0x04000130;
(originally was → int* KEYS = (int*)0x4000130)
After Compiling
It still have error,as Follows
sprite.cpp: In function 'void updateKeys()':
sprite.cpp:61 invalid operands of types 'u16' and 'u16*' to binary ' operator&'
sprite.cpp:62 cannot convert 'u16*' to 'u16' in assignment
Boring... :?
_________________
~ GBA SP~
#10325 - col - Tue Sep 02, 2003 2:51 pm
whells wrote: |
I have an Question . . .
if i use the code
whe i declare th KEYS in Keypad.h
u16* KEYS = (u16*)0x04000130;
(originally was → int* KEYS = (int*)0x4000130)
After Compiling
It still have error,as Follows
sprite.cpp: In function 'void updateKeys()':
sprite.cpp:61 invalid operands of types 'u16' and 'u16*' to binary ' operator&'
sprite.cpp:62 cannot convert 'u16*' to 'u16' in assignment
Boring... :? |
Code: |
//defines for a header file
#define KEYS *(volatile u16*)0x04000130
#define readKeys() (~KEYS)
//globals, or members of class Keypad
u16 newkeys = 0;
u16 keys = 0;
u16 keysReleased = 0;
//call this per frame
void updateKeys(){
hwKeys = readKeys();
newKeys = hwKeys ^ keys & hwKeys;
keysReleased = hwKeys ^ keys & keys;
keys = hwKeys;
}
|
i hope this works for you :)
Col
#10327 - tepples - Tue Sep 02, 2003 2:56 pm
Try this
#define KEYS (*(volatile u16 *)0x04000130)
Then make sure to read KEYS only once per execution of the game loop; otherwise, button bounces will confuse your game logic.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.