Discussion about software development for the old-school Gameboys, ranging from the "Gray brick" to Gameboy Color
(Launched in 2008)
You are not logged in.
hello gbdev. another newbie question here. the jump button is J_A. i want to set it up in gbdk so when i hold the J_A button, the jump method excutes only once. not unless i let go of the J_A button and press it again would the jump method executes. what is the best way to approach this?
here is my current code
while(1)
{
if((joypad() & J_A) || jumping == 1)
{
jump();
gameBallStaticStretched();
if(jumping == 0)
{
gameBallAnimSquashed(500);
wait_vbl_done();
}
}
if(joypad() & J_LEFT)
{
ballSprite01.x -= 3;
moveGameCharacter(&ballSprite01, ballSprite01.x, ballSprite01.y);
gameBallAnimRollLoop();
if(joypad() & J_A)
{
gameBallStaticStretched();
if(jumping == 0)
{
gameBallAnimSquashed(500);
}
}
}
if(joypad() & J_RIGHT)
{
ballSprite01.x += 3;
moveGameCharacter(&ballSprite01, ballSprite01.x, ballSprite01.y);
gameBallAnimRollLoop();
if(joypad() & J_A)
{
gameBallStaticStretched();
if(jumping == 0)
{
gameBallAnimSquashed(500);
}
}
}
performantDelay(2);
}
}Offline
The only way I know to detect a button being released would end up pausing your game until all buttons were released, but I do have a simple trick of making a Boolean tracker of if you can jump. Something of a "canJump" that gets set to FALSE when you initiate a jump and set it to be TRUE again when your character completes their jump. And make it so when you press J_A, check if canJump is TRUE or FALSE.
My solution is so primitive that this post was made on a stone tablet.
Offline
To piggy back off of Ardis's comment you can add in joypad() != J_A to see if A is not pressed so it could look like:
int canJump = 1;
if(joypad() == J_A && canJump == 1) {
canJump = 0;
}
if(joypad() != J_A){
canJump = 1;
}Offline
thanks ardis and gbjosh! it works now! now im having trouble controlling it with the directional button. when i press the right button and then the jump button(A) it works properly. the only problem now is when i hold the A button and press on the right button. the ball jumps and moves to the right. what i would like to do is when i hold the A button and then press right, the ball just slides. Ive been trying to figure out how to do this. im still learning programming so i dont have have any tricks up my sleeve to do this. Any tips in programming would be nice.
another question about compiling. im using debian linux and compiling using gbdk-n and gbdk2.6 using virtualbox and windows xp works fine when compiling my c code. i recently installed gbdk2.6 for linux and it compiles without errors. its just that when i try to make the ball jump, it doesnt jump. it jitters and i have to press it a couple of times to make it jump. is this a compiler bug?
#include <stdio.h>
#include <gb/gb.h>
#include "ballSprite.c"//16x16 sprite with animation
//global variables
BYTE keyPressed_A;
BYTE keyPressed_RIGHT;
BYTE jumping;
INT8 gravity = -2;
UINT8 currentSpeedY;
UINT8 floorYPosition = 136;
UINT8 possibleYSurface;
UINT8 timer = 0;
//performance delay to free up CPU
void performantDelay(UINT8 numloops)
{
UINT8 i;
for(i=0;i < numloops;i++)
{
wait_vbl_done();
}
}
//gameCharacter struct
struct gameCharacter
{
UBYTE spriteId[4];//change this according to sprite size (16x16, 24x24..)
UINT8 x;
UINT8 y;
UINT8 width;
UINT8 height;
};
//inializes gameCharacter to ballSprite01
struct gameCharacter ballSprite01;
//cycle through tiles for animation
void gameBallAnimRollLoop()//looping ball moving animation.(highlight jitters)
{
set_sprite_tile(1, 5);
set_sprite_tile(2, 6);
set_sprite_tile(3, 7);
set_sprite_tile(4, 8);
}
void gameBallStaticStretched()//static ball stretch
{
set_sprite_tile(1, 9);
set_sprite_tile(2, 10);
set_sprite_tile(3, 11);
set_sprite_tile(4, 12);
}
void gameBallStaticRest()//static ball rest
{
set_sprite_tile(1, 1);
set_sprite_tile(2, 2);
set_sprite_tile(3, 3);
set_sprite_tile(4, 4);
}
void gameBallAnimSquashed(UINT8 numloops)//static ball squashed
{
UINT8 i;
for(i=0;i < numloops;i++)
{
set_sprite_tile(1, 0);
set_sprite_tile(2, 0);
set_sprite_tile(3, 13);
set_sprite_tile(4, 14);
}
gameBallStaticRest();
}
//moving a 16x16 metaSprite in unison
void moveGameCharacter(struct gameCharacter *character, UINT8 x, UINT8 y)
{
move_sprite(character->spriteId[0],x, y);
move_sprite(character->spriteId[1],x + 8, y);
move_sprite(character->spriteId[2],x, y + 8);
move_sprite(character->spriteId[3],x + 8, y + 8);
}
//setup the ballSprite01 sprite struct
void setupBallSprite01()
{
set_sprite_data(0, 15, ballSprite);
ballSprite01.x=16;
ballSprite01.y = floorYPosition;
ballSprite01.width=16;
ballSprite01.height=16;
set_sprite_tile(1,1);
ballSprite01.spriteId[0]=1;
set_sprite_tile(2,2);
ballSprite01.spriteId[1]=2;
set_sprite_tile(3,3);
ballSprite01.spriteId[2]=3;
set_sprite_tile(4,4);
ballSprite01.spriteId[3]=4;
moveGameCharacter(&ballSprite01,ballSprite01.x,ballSprite01.y);
}
INT8 wouldHitSurf(UINT8 projectedYPosition)
{
if(projectedYPosition >= floorYPosition){
return floorYPosition;
}
return -1;
}
//jump algorithm
void jump()
{
if(jumping == 0)
{
jumping = 1;
currentSpeedY = 10;
}
currentSpeedY = currentSpeedY + gravity;
ballSprite01.y -= currentSpeedY;
possibleYSurface = wouldHitSurf(ballSprite01.y);
if(possibleYSurface == floorYPosition)
{
jumping = 0;
moveGameCharacter(&ballSprite01,ballSprite01.x, possibleYSurface);
}
else
{
moveGameCharacter(&ballSprite01,ballSprite01.x,ballSprite01.y);
}
}
void main()
{
//loads ballSprite
setupBallSprite01();
//initialize jumping variable
jumping = 0;
keyPressed_A = 1;
DISPLAY_ON;
SHOW_SPRITES;
while(1)
{
// printf("%d", joypad());
if((joypad() & J_A || jumping == 1) && keyPressed_A == 1)
{
jump();
gameBallStaticStretched();
if(jumping == 0)
{
gameBallAnimSquashed(500);
keyPressed_A = 0;
}
}
else if(joypad() != J_A)
{
keyPressed_A = 1;
}
if((joypad() & J_RIGHT) && keyPressed_RIGHT == 1)
{
ballSprite01.x += 3;
moveGameCharacter(&ballSprite01, ballSprite01.x, ballSprite01.y);
gameBallAnimRollLoop();
if(jumping == 0)
{
keyPressed_A = 1;
}
}
else if(joypad() != J_RIGHT)
{
keyPressed_RIGHT = 1;
}
performantDelay(2);
}
}Offline
so i checked out the the source for the game Pluto's Corner so i can learn how the controls were set but i couldn't find the "Keys.h" for the code. Theres this function i think called KEY_TICKED and i wanted to learn how it was done. Does anybody know? im just trying to learn. thanks
Offline
I can answer that
instead of just having the current state of the keys (obtained from the function joypad()) I also keep a copy of the previous state
So checking if a key has been ticked is just checking if it is currently pressed but it wasn't on the previous state
You can see how all this work here https://github.com/Zal0/ZGB/blob/master … ude/Keys.h
I call UPDATE_KEYS on every frame https://github.com/Zal0/ZGB/blob/2b6302 … ain.c#L120
Hope it helps
Offline
Yes!!! Thank you so much Zalo. Im just learning to make games with gameboy using GBDK-n. Its a small game or demo/test so I just incorporate the function in the main.c file.
#include <gb/gb.h>
//performance delay to free up CPU
void performantDelay(UINT8 numloops)
{
UINT8 i;
for(i=0;i < numloops;i++)
{
wait_vbl_done();
}
}
//joypad functions
void updateKeys()
{
previousKeys = keys;
keys = joypad();
}
INT8 keyPressed(INT8 K)
{
return keys & (K);
}
INT8 keyTicked(INT8 K)
{
return (keys & (K) && !(previousKeys & (K)));
}
INT8 keyReleased(INT8 K)
{
return previousKeys & (K) && !(keys & (K));
}
void anyKey()
{
keys;
}
void main()
{
while(1)
{
updateKeys();
if(keyPressed(J_RIGHT))
{
player.x += 1;
movePlayerR(&player, player.x, player.y);
}
}
}when i use keyTicked, it works now! Being new to c programming, im still having trouble wraping my head around how this works. Can anyone care to help me explain? Also, what if i wanted to use a double tick on a button? Say, when i press and hold right the character walks but when i ticked the right button and press it again, the character runs. basically a double click and hold the button. How would i go about doing that? is it a timer thing?
Offline
Most likely you'll want a limit on the amount of time between button presses for the double tap. There are probably a couple ways do to it, so here is one simplified example.
* A variable to track the state of whether the first tap occurred (this might be shared with general character moving state).
* Another variable to track how long (perhaps in frames) since the first button tap was released.
So then, when a subsequent tap occurs you can test whether the previous state is a matching one to start the double tap sequence, and whether it is within the required amount of time.
Offline