Jump to content
  • Advertisement
Sign in to follow this  
Canvas

SDL player.update doesnt update?

This topic is 2316 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey guys im have a little bit of trouble with checking keys for input, im pretty sure they are being checked correctly but it doesnt seem to change the location of my player image.

Here is my main code
#include "SDL.h"
#include <string>
#include "player.h"
SDL_Surface *screen = NULL;
SDL_Event event;
player gamePlayer;
bool init(){
if (SDL_Init (SDL_INIT_EVERYTHING) == -1)
{
return false;
}
screen = SDL_SetVideoMode(640,480,32,SDL_SWSURFACE);
if (screen == NULL)
{
return false;
}
SDL_WM_SetCaption("Event Handling", NULL);
return true;
}
int main(int argc, char* args[] ){
bool quit = false;
gamePlayer.loadImage("hello2.png");
//initialize SDL
if (init() == false)
{
return 1;
}
while (quit == false)
{
while (SDL_PollEvent( &event))
{
if (event.type == SDL_QUIT)
{
quit = true;
}
gamePlayer.update();
}
SDL_BlitSurface(gamePlayer.draw(),NULL,screen,&gamePlayer.rtnPos());
if (SDL_Flip(screen) == -1)
{
return 1;
}
}
return 0;
}


Here is my player.h and player.cpp
//Player header
#ifndef PLAYER_H
#define PLAYER_H
//includes
#include <string>
#include "SDL.h"
#include "SDL_image.h"
//Using namespace
//body
class player{
private:
SDL_Surface* image;
SDL_Event iEvent;
SDL_Rect pos;
public:
player();
void update();
void loadImage(std::string filename);
SDL_Rect rtnPos(){return pos;}
SDL_Surface* draw();
};
//end body
#endif
////player.cpp
#include "player.h"
player::player()
{
image = IMG_Load("dot.bmp");
pos.x = 100;
pos.y = 100;
pos.h = 320;
pos.w = 240;
}
void player::loadImage(std::string fileName)
{
image = IMG_Load(fileName.c_str());
}
SDL_Surface* player::draw()
{
return image;
}
void player::update()
{
if(SDL_PollEvent(&iEvent))
{
if (iEvent.type == SDL_KEYDOWN)
{
switch(iEvent.key.keysym.sym)
{
case SDLK_UP: pos.y -= 10; break;
case SDLK_RIGHT: pos.x += 10; break;
case SDLK_LEFT: pos.x -= 10; break;
case SDLK_DOWN: pos.y += 10; break;
}
}
}
}


Can anyone see why it isnt moving?

Cheers Canvas

Share this post


Link to post
Share on other sites
Advertisement
You have two poll event loops, but SDL only has a single event queue. The event loop in main will pick up the first even that occurs in a given frame, and the player::update() will pick up the second. They will then alternate while events are still in the queue (for non-mouse games, there are generally few events in the queue).

I recommend having a single even loop, and passing interesting events to the player object:

// In player.h
class player {
public:
// ...
void update(SDL_Event event);
// ...
};

// Inside main()


while (SDL_PollEvent( &event))
{
if (event.type == SDL_QUIT)
{
quit = true;
}
else
{
gamePlayer.update(event);
}
}

Now, in this case your player object will correctly receive the events of interest.

There may remain another issue however, depending on the style of your game. If your game expects the player to continue moving while the key is held down, then you need a way to "remember" the direction of movement and a way to update the position even when events do occur.

A simple solution is to add some variables to the player to indicate the current direction and speed of movement, and to separate the event code from the update code, like so:

class Player
{
public:
Player();

void update();
void onEvent(const SDL_Event &event);

// ...

private:

int x;
int y;
int vx;
int vy;
};

// Player.cpp

Player::Player()
{
x = 100;
y = 100;
vx = 0;
vy = 0;
}


void Player::onEvent(const SDL_Event &event)
{

const int SPEED = 10;
if (event.type == SDL_KEYDOWN)
{
switch(event.key.keysym.sym)
{
case SDLK_UP: vy -= SPEED; break;
case SDLK_DOWN: vy += SPEED; break;
case SDLK_LEFT: vx -= SPEED; break;
case SDLK_RIGHT: vx += SPEED; break;
}
}
else if(event.type == SDL_KEYUP)
{
switch(event.key.keysym.sym)
{
case SDLK_UP: vy += SPEED; break;
case SDLK_DOWN: vy -= SPEED; break;
case SDLK_LEFT: vx += SPEED; break;
case SDLK_RIGHT: vx -= SPEED; break;
}
}
}

void Player::update()
{
x += vx;
y += vy;

// Maybe some code to keep the player inside the screen/world/map bounds?
SDL_Surface *screen = SDL_GetVideoSurface();

if(x < 0)
{
x = 0;
}
else if(x > screen->w)
{
x = screen->w;
}

if(y < 0)
{
y = 0;
}
else if(x > screen->h)
{
y = screen->h;
}
}

An interesting "trick" here is starting the velocity at 0, and adding or subtracting the speed to it, rather than simply setting the speed. You may wonder at this idea - surely any key can only be pressed down once, and thus the difference would appear irrelevant.

For reference, here is the type of implementation I'll be discussing:


void Player::onEvent(const SDL_Event &event)
{
const int SPEED = 10;
if (event.type == SDL_KEYDOWN)
{
switch(event.key.keysym.sym)
{
case SDLK_UP: vy = -SPEED; break;
case SDLK_DOWN: vy = SPEED; break;
case SDLK_LEFT: vx = -SPEED; break;
case SDLK_RIGHT: vx = SPEED; break;
}
}
else if(event.type == SDL_KEYUP)
{
switch(event.key.keysym.sym)
{
case SDLK_UP: vy = 0; break;
case SDLK_DOWN: vy = 0; break;
case SDLK_LEFT: vx = 0; break;
case SDLK_RIGHT: vx = 0; break;
}
}
}

Imagine that the player starts by holding down the UP key. So their y velocity is incremented to -10. Now, imagine that without releasing the UP key they press the down key. If you set the velocities, rather than added to them, then their velocity would become +10. With the addition method, it becomes 0 - which I think is reasonable if the user holds the up and down keys at the same time.

However, even that, while nice, is not the real "win". Think what happens now if the user releases the either key under the "set" implementation - the velocity becomes zero. But the player is still holding down a key!

This isn't perfect. If you are running the game in a window, and the game loses focus, the state of the player can get out of sync with the keys. Another option is simply to ask for the current key "state":


class Player
{
public:
Player();

void update();
// ...

private:
int x;
int y;
// ...
};

Player::Player()
{
x = 100;
y = 100;
}

void Player::update()
{
const int SPEED = 10;
Uint8 *keys = SDL_GetKeyState(NULL);

if(keys[SDLK_UP])
{
y -= SPEED;
}
if(keys[SDLK_DOWN])
{
y += SPEED;
}

if(keys[SDLK_LEFT])
{
x -= SPEED;
}
if(keys[SDLK_RIGHT])
{
x += SPEED;
}

// Bounds code is similar
}

In this case, you would have no player related code in your event loop, instead you must call Player::update() every frame.

Finally, note that I'm using regular integers to hold the player's position, rather than a SDL_Rect. SDL_BlitSurface() modifies the "destination" rectangle passed to it to contain the "clipped" co-ordinates. You are passing a copy, so this doesn't affect you... yet.

Share this post


Link to post
Share on other sites
Awesome, im going to try the code soon, just abit busy at the moment, Also i know about the focus stuff and velocity im going to try and code it later and i will let you know if i need help with them also :D but cheers for the reminder :), I will reply if i found some errors :), also when it draws the rectangle it seems to draw it in all of its previous positions? can you see why in my code?

Share this post


Link to post
Share on other sites
Well you don't clear the screen, so anything you have previously drawn will still be underneath your new stuff. A simple way to clear the screen is use the SDL_FillRect() function, and pass a NULL SDL_Rect pointer:

SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));

Share this post


Link to post
Share on other sites
K i have just moved my player.update and other stuff and works correctly, but sometimes when i release a button the player sprite keeps moving, like its stuck on speed 10, why so?

player handleInput code here
void player::handleInput(SDL_Event iEvent)
{
const int SPEED = 10;
if (iEvent.type == SDL_KEYDOWN)
{
switch(iEvent.key.keysym.sym)
{
case SDLK_UP: yVel = -SPEED; break;
case SDLK_DOWN: yVel = SPEED; break;
case SDLK_LEFT: xVel = -SPEED; break;
case SDLK_RIGHT: xVel = SPEED; break;
}
}
else if(iEvent.type == SDL_KEYUP)
{
switch(iEvent.key.keysym.sym)
{
case SDLK_UP: yVel = 0; break;
case SDLK_DOWN: yVel = 0; break;
case SDLK_LEFT: xVel = 0; break;
case SDLK_RIGHT: xVel = 0; break;
}
}
}


if i press right arrow and up arrow at the same time and then let go at the same time, the player sprite just goes "wwweeeeeeeee" upwards

i feel like its because the players.udpate is the only one that can change the xVel and yVel, now if i was to let go of a key and the pollEvent missed it, it wont stop moving until i press the key again, but why is this so? is my code wrong?

Share this post


Link to post
Share on other sites
gamePlayer.update() needs to be called even when there are no events (That's what's causing your jerky movement).
gamePlayer.handleInput() needs to be called only when there are events.

So it should look like this:

while(quit == false)
{
//Handle events first.
SDL_Event event;
while(SDL_PollEvent(&event))
{
//Handle events like quiting.
gamePlayer.handleInput(event);
otherStuff.handleInput(event);
moreThings.handleInput(event);
}

//Handle updating next.
gamePlayer.update();
otherStuff.update();
moreThings.update();

//Handle drawing after that.
SDL_FillRect(...);

//Whatever you draw last is above whatever you drew before it.
gameWorld.draw(screen);
gamePlayer.draw(screen);
otherStuff.draw(screen);
moreThings.draw(screen);

SDL_Flip(screen);
}

Share this post


Link to post
Share on other sites
Awesome my code for my main loop is now
while (quit == false)
{
fps.start();
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
quit = true;
}
//Handle Inputs
gamePlayer.handleInput(event);
}
//Update
gamePlayer.update();
//Clear screen
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
//Draw
SDL_BlitSurface(gamePlayer.draw(),NULL,screen,&gamePlayer.rtnPos());
if (SDL_Flip(screen) == -1)
{
return 1;
}
if( fps.rtnTicks() < 1000 / 30 )
{
SDL_Delay( ( 1000 / 30 ) - fps.rtnTicks() );
}
}


Cheers for the help, i should i seen this myself :D

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!