SDL how to move an object by holding a button rather then pressing the button over and over

Started by
8 comments, last by BeerNutts 11 years, 4 months ago
I've already tried looking this up but I can't find anything to help.
I just learned how to move an object which was successful. You press a button once to move it, but you can't hold it down to keep the object moving, you have to keep tapping the button to make move more.

Is there a certain way or certain code to make it so that you can just hold the button to keep moving and let go whenever you want to stop?
Advertisement
Sure, there are two common ways:

A) On button press, set bool "move" to true. On button release, set bool "move" to false. (You have to create such a bool yourself). Every frame, if "move" is true, move the player. Realistically, you'll want several bools, because you can move in several directions, or alternatively, two ints (x,y) holding the amount to move each frame, positively or negatively.

B) Let SDL handle the "move" boolean for you, and instead call SDL_GetKeyState() which returns a bool array of most of the keyboard keys and whether they are currently being held or not (see documentation link). Every frame you can then check if the key is held down, and move the player.
(sigh) Now I'm hitting some more problems, things may be a little mixxed up. Now it won't move at all! It shows but doesn't respond in movement. Heres the code I wrote if you or anyone can see what I'm doing wrong

[sharedmedia=core:attachments:12623]
#include "SDL.h"
int main(int argc, char *argv[])
{
bool bRun = true;
SDL_Surface *screen , *ship;
SDL_Rect shipRect;
shipRect.x = 100 ;
shipRect.y = 100 ;

SDL_WM_SetCaption("Fryday", NULL);
screen = SDL_SetVideoMode( 256 , 224 , 32 , SDL_DOUBLEBUF|SDL_HWSURFACE|SDL_ANYFORMAT);

SDL_FillRect(screen , NULL , 0x221122);
ship = SDL_LoadBMP("./ship.bmp");
SDL_SetColorKey( ship, SDL_SRCCOLORKEY, SDL_MapRGB(ship->format, 255, 0, 255) );
SDL_BlitSurface( ship , NULL , screen , &shipRect );
SDL_Flip(screen);
SDL_Event event;
while(bRun) {
bool keysHeld[323] = {false}; // everything will be initialized to false

if (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
bRun = false;
}
if (event.type == SDL_KEYDOWN)
{
keysHeld[event.key.keysym.sym] = true;
}
if (event.type == SDL_KEYUP)
{
keysHeld[event.key.keysym.sym] = false;
}

if ( keysHeld[SDLK_ESCAPE] )
{
bRun = false;
}
if ( keysHeld[SDLK_LEFT] )
{
shipRect.x -= 1;
}
if ( keysHeld[SDLK_RIGHT] )
{
shipRect.x += 1;
}
if ( keysHeld[SDLK_UP] )
{
shipRect.y -= 1;
}
if (keysHeld[SDLK_DOWN])
{
shipRect.y += 1;
}
}
}; // while(bRun) { END
return 0;
}
I am a pygame person, but typically it's done as this:

if event.key == event.keydown:
if event.ket == event.K_UP:
ship.location.x -= 10 // Pygame takes (0,0) top left screen MAX_width,MAX_height) to be bottom right screen


Your code handles keydown alone versus handling with some specific key being pressed AND held. Hope this helps.
Also, you only draw the ship once. You need to clear and redraw the ship every time it moves (also you need to include code that prevents the ship from being moved too quickly, as you are probably going to get 100+ FPS when you are only drawing one picture)
As RulerOfNothing says, your game loop needs to be setup like this:

  • Load resources
  • Initialize game settings
  • While (still playing)

    1. Get all the player input ([color=#ff0000][s]if[/s] while(SDL_PollEvent(&event)) )
    2. Update the game objects (by deltaTime*)
    3. Do any game thinking ([size=2]optionally part of the updating code instead)
    4. Render:

      1. Clear the entire screen
      2. Draw every object from back to front
      3. Draw the GUI
      4. Flip the screen buffers

  • Uninitialize the game, if neccesary.
  • Free game resources

*[size=2]A simple deltaTime is 'currentTime - previousTime'. This is the amount of time passed since the last frame. See SDL_GetTicks(). Others prefer a fixed timestep, but for beginner projects, 'currentTime - previousTime' might be simpler, and works just fine.

Your game should follow that basic pattern. 99% of games follow that basic pattern (with minor tweaks and variations here or there).

You should go through Lazy Foo's SDL tutorials.
Particularly:
But the tutorials build off each other, so you really really should go through them from the start.
You also should read Lazy Foo's article on Game Loops, and if you have any questions, ask here and we'll be glad to help.
BigBadBear - I am no expert in the lanquage you are using, but ( IF ) I am reading your code correctly ( THEN ) in your IF Keysheld statement, Romove The Equal Sign ( = ) after your Plus/Minus ( + / - ) signs and your ship should move.

The language I use has KeyDown(Upkey) vs. KeyHit(Upkey) to test whether a key is held or simply pressed.

Your Brain contains the Best Program Ever Written : Manage Your Data Wisely !!

@OP: The problem with your code is that:
A) You do your event looping in an if() instead of a while()
B) You don't ever actually initialize keyHeld[], leaving it set as false, thus never triggering the movement.
C) You have your keyHeld[] code inside your event loop when it should be outside. (Polling input states should usually be outside the event loop, handling input events should be inside the event loop)


BigBadBear - I am no expert in the language you are using, but ( IF ) I am reading your code correctly ( THEN ) in your IF Keysheld statement, Romove The Equal Sign ( = ) after your Plus/Minus ( + / - ) signs and your ship should move.

Not in C++. smile.png

var1 + var2 doesn't change the result of 'var1', you'd have to do var1 = var1 + var2. Using += is shorthand for that. var1 += var2 does change var1 properly.
Thank you SOTL. That ia why I Come here to learn and expand my knowlege. After reading your reply to my quote, I Checked it out. I think what I was thinking that since BigBadBear was only increasing or decreasing by 1, My trend of thought was the Increment / decrement operators in C++ of ++ or -- Example Ship.x ++ or Ship.x -- in order to increase / decrease the Ship.x by a value of 1.

Your Brain contains the Best Program Ever Written : Manage Your Data Wisely !!

Something else to consider would be to check the Input every frame; if a key is down, mark it in an Input Object, if it's not leave blank (false); then, you can pass the Input object to anyone who wants to know about Input. Like this (pseudo-code):


struct TInput {
bool IsLeftPressed;
bool IsRightPressed;
bool IsUpPressed;
bool IsFirePressed;
bool IsJumpPressed;
};

// create this funciton to get the current keys being pressed
void GetInput(TInput& input)
{
while(PollKeyEvent(&keyEvent) {
if (keyEvent.IsPressed) {
if (keyEvent.keycode == LEFT_KEY) {
input.IsLeftPressed;
}
if (keyEvent.keycode == UP_KEY) {
input.IsUpPressed;
}
// Continue checking them all
}
}
}

// in Main loop
while(IsRunning) {
TInput input;
GetInput(input);

// now pass the input into your Update functions, which would check input.IsFirePressed to see if the user is pressing fire, etc.
Player.Update(input);

// Call other update functions for enemies, objects, background, etc as well as rendering for them.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

This topic is closed to new replies.

Advertisement