Button held down by code - c++

I am writing a game and am trying to make a person move with the arrow keys.
I have this code
if (Key_Down(DIK_DOWN))
{movedown(player)}
This works but as I want the player to take four steps every time the key is pressed I created and animation loop. so the player cannot input any more move commands until the animation is over and they have taken four steps I made the code this.
if(player.move == false)
{
if (Key_Down(DIK_DOWN))
{movedown(player)}
}
The problem is that now once a button is pressed the program acts like the button is held down and the player keeps moving until another direction is pressed.
Can anyone explain what the outer loop has done to the code and fix the problem ?
it is programmed in visual c++ 2005 and direct x 9.c
Edit:
If I remove the outer loop then the button press is only registered once so I don't think it is the movedown function.

Simply keep track of the keystate in a variable. So you can reset a move counter. Something like this, combining both:
int MovingDown = 0;
...
if (!Key_Down(DIK_DOWN)) MovingDown = 0;
else if (MovingDown < 4) {
MovingDown++;
movedown(player);
}

Hard to tell without seeing more of your codebase but I would guess that you're not re-setting player.move after you've moved the player. Have you tried sticking some break poins in there to see what is being called and why?
If you remove the if(player.move == false) line does it have the same issue? ..or have you changed something elsewhere? If you could post more of your codebase like the whole movedown function and anythnig else which interacts (e.g. the animation code) it would help us help you...
[Edit] Is movedown a macro? Maybe you've got some peculiar side effect eminating from that? If not, it ought to have a semi colon after the function call.
What does KEY_DOWN return? Is that an API call? Try testing against the exact value you expect it to return?

Related

C++ parallel loops

I'm making a console game called alien spaceships as a homework. It should look something like this http://img74.imageshack.us/img74/8362/alieninvadersfdcl192720mu1.jpg .
So far so good I ain't allowed to use classes nor objects => only functions and arrays.
I have one while loop that checks the buttons I press on the keyboard and according to the button applies some functions.
The problem comes when I try to shoot a missle because it's done with a "for" loop and when I shoot I can't move. Can someone give me an idea how the model is supposed to look like and how can I make something like this work. I don't think it's needed to post my code, but if you want I'll post it.
I assume that you're not willing to play with multiple threads. It is not mandatory for a simple game like this and would add a bit of complexity.
So generic loop for monothreaded game is:
state new_state = createInitialState();
do
{
input = readInput(); // non blocking !
new_state = modifyState(input, new_state);
updateScreen(new_state);
}
while (!exitCondition(input));
None of these functions should loop for long.
In your case, the missile position should be updated in modifyState taking into account the time since the last modifyState.
I assume you use a matrix to store all the data, and periodically you print the content of the matrix (that's how you create a console game).
So, your code should look something like this:
render()
{
update_position(x,y);
if(missile_fired)
update_missile_position();
}
main()
{
for(;;)
{
read_input(&x,&y);
render();
draw_image();
}
}

Jump function on a character

I'm creating this 2D game and I'm having problems with the Jump function. It works, the character jumps up and down, but I would like to be able to jump and then move the character while its in the air,e.g. so it can jump onto a platform. I'm using SDLK...
case SDL_KEYDOWN:
switch (event.key.keysym.sym){
RArrow = (event.button.button = SDLK_RIGHT);
Jump = (event.button.button = SDLK_SPACE);
if((RArrow) && (Jump))
{
if(g->getPlayer()->worldY = GROUND_LEVEL)
{
g->getPlayer()->jump();
g->getPlayer()->move(10);
}
}
break;
This is one of the ways I've tried. I've also tried to make a switch function inside the jump case to navigate left or right but I either didn't code it right or just didn't work.
I'm unfamiliar with SDLK and how this actually is done in real game development.
However one way I've implemented this is to see if both keys are pressed on each game tick. So if w+d is pressed the character would go up and right at the same time. But it's a hackish solution in my opinion.
With the implementation listed, looks like the character will only move right when they are on the ground level. You need to change your code so that every tick, the game checks if the character is jumping and if so, moves the character in the direction it is facing/jumping. This code may need to live outside of your event handler.
Ideally, your keyboard event handler would just set a flag on the character indicating that they are jumping and which direction, then in your game loop you call an update() method which actually handles the jumping (and stops jumping when the character collides with the world geometry, like a floor or wall).
Hope this helps!
EDIT:
Without seeing the rest of your code, I can't say much more. I'm also not great with C++, which I'm assuming this uses. One way you could implement this is:
Replace "g->getPlayer()->jump()" with "g->getPlayer()->setJumping()".
Implement "setJumping()" on the Character to set a jumping flag.
In the game loop, call "g->getPlayer()->updatePos()"
Implement "updatePos()" on the Character to update the character's position. In this, check the jumping flag, and if it's true update the position based on your jumping algorithm.

SDLK Perplexity

How does SDLK_'anykey' work? In my game, a bullet has to be shot when the Ctrl button is pressed, but through breakpoints and test print statements I have realised that even though I press 'ctrl' once, the function is getting called many times. Why is that? And how do I avoid this?
There's nothing much - this is the switch case in the main loop :
case SDLK_p :
s.origin(cat);
break;
where s is an object that calls the origin function of the Shoot class, and passes a frame to it. Using a count variable in the origin function, I now know that the function is called for the number of times equal to the seconds I hold down the 'p' key! How to prevent this?
SDL_PollEvent(&event);
You need to check the return value from SDL_PollEvent. If it's 0 there are no pending events and you shouldn't try to handle it.
According to documentation, you should add this line to the SDL initialization:
SDL_EnableKeyRepeat(0,0);

First mouse movement unexpected using SDL (C++)

I'm working on a c++ project for school, and my implementation at this moment requires mouse input for controlling a ship (It's supposed to be a remake of Tyrian). Everything is working fine, except for the first time I move the mouse, it has an offset depending on where the mouse was when I started the game. I guess this is because I'm using SDL_GetRelativeMouse but how can I prevent it?
You may wish to initialize the mouse to a good known position when the application begins, possibly right before events callbacks are initialized.
Making sure the mouse is within the bounds of the window may also be appropriate. It isn't really relevant to the application outside of its boundaries anyway.
This is what I do to toggle mousegrab in a FPS-type application:
if(event.key.keysym.sym == SDLK_z)
{
if( mouse_grabbed )
{
SDL_WM_GrabInput(SDL_GRAB_OFF);
SDL_WarpMouse( display->w/2, display->h/2 );
SDL_ShowCursor(1);
}
else
{
SDL_ShowCursor(0);
SDL_WM_GrabInput(SDL_GRAB_ON);
int tx,ty;
SDL_GetRelativeMouseState(&tx, &ty);
}
mouse_grabbed = !mouse_grabbed;
}
Consuming a mouse update via the dummy SDL_GetRelativeMouseState() call was the important part.
For the moment I'll just suppress the first time mouse movement is detected. This seems to work, but it seems a rather unprofessional approach.
I use this:
Sdl.SDL_ShowCursor(Sdl.SDL_DISABLE);
Sdl.SDL_WM_GrabInput(Sdl.SDL_GRAB_ON);
e=new Sdl.SDL_Event();
pollOne();
.
.
.
private void pollOne(){
while(Sdl.SDL_PollEvent(out e)==1){
switch(e.type){
case Sdl.SDL_MOUSEMOTION:
float throwAway=((float)e.motion.xrel*headSens);
break;
}
}
}
Basically, when initializing the mouse (grabbing it and making it invisible) call pollOne to throw the first event away. Every event captured hereafter in the main event processing function called by the main loop is with mouse at center screen.

2D Jumping error

Basically, here is my code:
bool Player::onCollision(BaseOBJ* obj)
{
if(obj->name == "phys_static")
{
jumping = true;
}
return true;
}
void Player::jump()
{
if(jumping == true)
{
ApplyForce(Vec2(0.f, -13000.f), Vec2(0.f, 0.f));
jumping = false;
}
}
onCollision is called first, when there is a collision. It is not called if there has not been any new collisions (ex. only jumps would register, not moving from side to side)
It normally works fine, however if I hold the jump key all the way through the jump (from when it is launched to when it touches the ground) I cannot jump again. Any solutions?
An often overlooked issue with holding down a key is that your operating system will convert this into fast, repeated presses.
Example:
In your text editor, hold the A key. One 'a' will appear, and then, after a slight delay:
aaaaaaaaaaaaa (Many repeated 'A' key presses are sent to the active application.)
Is your jump function being called repeatedly and somehow messing up how you intended your jump checking to work?
If not, please answer some of the questions that earlier commenters have presented.
P.S. Suggestion on the side: it appears to me that 'jumping' should be named 'canJump' or 'allowJumping'. This avoids a lot of confusion. Right now it sounds like it indicates whether you are jumping, whereas you actually use it to indicate whether you can jump.