Taking 2 keyboard inputs with sfml - c++

How do I make my "game" take 2 key inputs, for example if the user clicks w and d he moves up right.
btw, the variable eventCheck is an Event object
here's my current code(obviously not the full code just the event code):
while (window.isOpen()) {
Event eventCheck;
while (window.pollEvent(eventCheck)) {
switch (eventCheck.type) {
case Event::Closed:
window.close();
break;
case Event::KeyPressed:
switch (eventCheck.key.code) {
case Keyboard::W:
if (Keyboard::isKeyPressed(Keyboard::A)) {
const Vector2f spritePos = sprite.getPosition();
sprite.setPosition(spritePos.x, spritePos.y - 5);}
break;
case Keyboard::A:
if (Keyboard::isKeyPressed(Keyboard::A)) {
const Vector2f spritePos = sprite.getPosition();
sprite.setPosition(spritePos.x - 5, spritePos.y);}
break;
case Keyboard::S:
if (Keyboard::isKeyPressed(Keyboard::S)) {
const Vector2f spritePos = sprite.getPosition();
sprite.setPosition(spritePos.x, spritePos.y + 5);}
break;
case Keyboard::D:
if (Keyboard::isKeyPressed(Keyboard::D)) {
const Vector2f spritePos = sprite.getPosition();
sprite.setPosition(spritePos.x + 5, spritePos.y);}
break;
}
}
break;
}
window.clear(Color(0,0,0,255));
window.draw(sprite);
window.display();
}
return 0;

1.) SFML has event polling through sf::Event and real time key state access provided through sf::Keyboard. If you only need to handle a single key press, your best bet is to poll them through window.pollEvent otherwise it's usually always better to get the state of a key and react based on the state. In this case you are mixing event polling with keyboard states. Choose one or the other.
2.) Not using sf:: removes a lot of clarity from the code
Now onto the code!
I wouldn't poll any user input inside events. I would get the state of the keys:
// Once per game loop
void ProcessInput()
{
int keyCount = 0;
if(sf::Keyboard::isKeyPressed(sf::Keyboard::W))
{
keyCount++;
//Move Character Up, The more keys are pressed, the more i would mess around with speed/velocity here
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::A))
{
keyCount++;
//Move Character Left, The more keys are pressed, the more i would mess around with speed/velocity here
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::S))
{
keyCount++;
//Move Character Down, The more keys are pressed, the more i would mess around with speed/velocity here
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::D))
{
keyCount++;
//Move Character Right, The more keys are pressed, the more i would mess around with speed/velocity here
}
}
Depending on the amount of keys the user pressed, you would want to move your character less since they could move more diagonally than vertically/horizontally, but mess around with speed and velocity as you see fit.

I ended up doing
bool moveL = false;
bool moveU = false;
bool moveD = false;
bool moveR = false;
while (window.isOpen()) {
Event eventCheck;
while (window.pollEvent(eventCheck)) {
switch (eventCheck.type) {
case Event::Closed:
window.close();
break;
case Event::KeyReleased:
switch (eventCheck.key.code) {
case Keyboard::A:
moveL = false;
break;
case Keyboard::W:
moveU = false;
break;
case Keyboard::S:
moveD = false;
break;
case Keyboard::D:
moveR = false;
break;
}
break;
case Event::KeyPressed:
switch (eventCheck.key.code) {
case Keyboard::A:
moveL = true;
break;
case Keyboard::W:
moveU = true;
break;
case Keyboard::S:
moveD = true;
break;
case Keyboard::D:
moveR = true;
break;
case Keyboard::Space:
jump(sprite, window);
break;
}
const Vector2f spritePos = sprite.getPosition();
if (moveD && moveR) {
sprite.setPosition(spritePos.x + 5, spritePos.y + 5);
}
else if (moveL && moveU) {
sprite.setPosition(spritePos.x - 5, spritePos.y - 5);
}
else if (moveU && moveD) {
sprite.setPosition(spritePos.x, spritePos.y);
}
else if (moveU && moveR) {
sprite.setPosition(spritePos.x + 5, spritePos.y - 5);
}
else if (moveD && moveL) {
sprite.setPosition(spritePos.x - 5, spritePos.y + 5);
}
else if (moveL) {
sprite.setPosition(spritePos.x - 5, spritePos.y);
}
else if (moveR) {
sprite.setPosition(spritePos.x + 5, spritePos.y);
}
else if (moveU) {
sprite.setPosition(spritePos.x, spritePos.y - 5);
}
else if (moveD) {
sprite.setPosition(spritePos.x, spritePos.y + 5);
}
break;
}
}
window.clear(Color(0,0,0,255));
window.draw(sprite);
window.display();
}
return 0;
}

Related

The better way to control player in 2d game ? (sdl2)

I'm doing this like this, in .hpp file:
class Player
{
public:
Player(){}
Player(){}
virtual ~Player(){}
void handler(SDL_Event event);
void update()
{
move(velocityForwardX, velocityForwardY);
move(-velocityBackwardX, -velocityBackwardY);
/* the player moves from it current position. */
}
protected:
int speed = 5;
int velocityForwardX = 0;
int velocityForwardY = 0;
int velocityBackwardX = 0;
int velocityBackwardY = 0;
};
in .cpp file:
#include "Player.h"
void Player::handler(SDL_Event event)
{
if(event.type == SDL_KEYDOWN){
switch(event.key.keysym.sym)
{
case SDLK_d:
velocityForwardX = speed;
break;
case SDLK_q:
velocityBackwardX = speed;
break;
case SDLK_z:
velocityBackwardY = speed;
break;
case SDLK_s:
velocityForwardY = speed;
break;
default:
break;
}
}
else if(event.type == SDL_KEYUP){
switch(event.key.keysym.sym)
{
case SDLK_d:
velocityForwardX = 0;
break;
case SDLK_q:
velocityBackwardX = 0;
break;
case SDLK_z:
velocityBackwardY = 0;
break;
case SDLK_s:
velocityForwardY = 0;
break;
default:
break;
}
}}
like this I can presse any key and release it and the player move well. It also works if two opposite keys are pressed then one is release so the player is going in the right direction. Can we make it easier ? (sorry for my english)
You could store only one variable per direction and add and subtract speed when pressing and releasing a button, e.g.
switch(event.key.keysym.sym)
{
case SDLK_d:
velocityX += speed;
break;
case SDLK_q:
velocityX -= speed;
break;
case SDLK_z:
velocityY -= speed;
break;
case SDLK_s:
velocityY += speed;
break;
default:
break;
}
// similar for key release
With this if you press opposite x direction keys simultaniously, velocityX will be 0, and the same for the y direction and velocityY.

How to press multiple keys at the same time using events in real-time? (Allegro 5)

This is a problem that haunts me for years.
Here's my game.h and game.cpp files:
game.h
#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED
#include "init.h"
ALLEGRO_BITMAP *load_bmp(path *s);
struct Actor {
const char *path;
ALLEGRO_BITMAP *bmp;
int x;
int y;
int speed;
};
void init_game_bitmaps();
void draw_game_bitmaps();
extern map<string, bool> key_states;
void init_key_states();
void check_states();
void control_actor(Actor *target, int speed);
extern Actor player;
#endif // GAME_H_INCLUDED
game.cpp
#include "game.h"
ALLEGRO_BITMAP *load_bmp(path *s) {
ALLEGRO_BITMAP *bmp = nullptr;
bmp = al_load_bitmap(s);
if (!bmp) {
al_show_native_message_box(display,
"Fatal Error!",
"Failed to load: " ,
s,
NULL,
ALLEGRO_MESSAGEBOX_ERROR);
al_destroy_display(display);
return nullptr;
}
return bmp;
}
map<string, bool> key_states;
void init_key_states() {
key_states["UP"] = false;
key_states["DOWN"] = false;
key_states["LEFT"] = false;
key_states["RIGHT"] = false;
}
void check_states() {
auto key = e.keyboard.keycode;
for (auto it = key_states.begin(); it != key_states.end(); ++it) {
if (e.type == ALLEGRO_EVENT_KEY_DOWN) {
if (key == ALLEGRO_KEY_UP) {
if (it->first == "UP") {
it->second = true;
}
}
if (key == ALLEGRO_KEY_DOWN) {
if (it->first == "DOWN") {
it->second = true;
}
}
if (key == ALLEGRO_KEY_LEFT) {
if (it->first == "LEFT") {
it->second = true;
}
}
if (key == ALLEGRO_KEY_RIGHT) {
if (it->first == "RIGHT") {
it->second = true;
}
}
} else if (e.type == ALLEGRO_EVENT_KEY_UP) {
if (key == ALLEGRO_KEY_UP) {
if (it->first == "UP") {
it->second = false;
}
}
if (key == ALLEGRO_KEY_DOWN) {
if (it->first == "DOWN") {
it->second = false;
}
}
if (key == ALLEGRO_KEY_LEFT) {
if (it->first == "LEFT") {
it->second = false;
}
}
if (key == ALLEGRO_KEY_RIGHT) {
if (it->first == "RIGHT") {
it->second = false;
}
}
}
cout << it->first << " : " << it->second << endl;
}
}
void control_actor(Actor *target, int speed) {
if (key_states["UP"]) {
target->y -= speed;
}
if (key_states["DOWN"]) {
target->y += speed;
}
if (key_states["LEFT"]) {
target->x -= speed;
}
if (key_states["RIGHT"]) {
target->x += speed;
}
}
Actor player = {
"GFX\\player_up.png",
nullptr,
(SCREEN_WIDTH / 2) - (ACTOR_SIZE / 2),
(SCREEN_HEIGHT / 2) - (ACTOR_SIZE / 2),
8};
void init_game_bitmaps() {
player.bmp = load_bmp(player.path);
}
void draw_game_bitmaps() {
al_draw_bitmap(player.bmp, player.x, player.y, 0);
al_flip_display();
}
Now here's my main file:
main.cpp
#include "init.h"
#include "game.h"
int main(int argc, char **argv){
init_all();
register_all();
init_game_bitmaps();
init_key_states();
while (running) {
draw_game_bitmaps();
al_wait_for_event(event_queue, &e);
if (e.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
running = false;
}
check_states();
control_actor(&player, player.speed);
if (e.type == ALLEGRO_EVENT_KEY_DOWN) {
if (e.keyboard.keycode == ALLEGRO_KEY_ESCAPE) {
running = false;
}
if (e.keyboard.keycode == ALLEGRO_KEY_ENTER) {
cout << "It works!";
}
}
}
destroy_all();
return 0;
}
As you can see, I have a std::map that stores key states (One for each arrow of the keyboard), and then I have a procedure called check_states(), that iterate over all the states at each main loop, and set them to true if their respective arrows are pressed (down), and to false when they are released.
The problem:
If I press UP and keep it holding, and then I press LEFT (Without releasing the UP key), the player will move diagonally. Nevertheless, if I release the LEFT, while still holding the UP key, the player will stop, and the state for UP will be true (And I see this because I'm couting it).
Theory
The al_wait_for_event() waits until the event queue specified is non-empty (Which means that when I press the UP key, it copies the event to e, and then when I press the LEFT, it must cancel UP and assign a new event to e, thus creating the unpleasant LAG when I press more than one key at once). Having that in mind, I've concluded: Well, I could have at least FIVE separate event_queues, and FIVE different "event objects". I've managed to create a vector of event_queues and of events and to iterate over both of them at each main loop while passing each event to its respective event_queue AND THE PROBLEM PERSISTED.
SO, how can I press more than one key in real-time? By real-time I mean real real-time, without lags, without any key canceling each other. The answer is key states? Why? How can I do it using events? Is it possible at all?.
EDIT:
I've changed my control_actor() procedure in order to use al_key_down() instead of checking for events, here's its code:
void control_actor(ALLEGRO_KEYBOARD_STATE *key, Actor *target, int speed) {
if (al_key_down(key, ALLEGRO_KEY_UP)) {
target->y -= speed;
cout << "UP" << endl;
}
if (al_key_down(key, ALLEGRO_KEY_DOWN)) {
target->y += speed;
cout << "DOWN" << endl;
}
if (al_key_down(key, ALLEGRO_KEY_LEFT)) {
target->x -= speed;
cout << "LEFT" << endl;
}
if (al_key_down(key, ALLEGRO_KEY_RIGHT)) {
target->x += speed;
cout << "RIGHT" << endl;
}
}
And the new main.cpp:
#include "init.h"
#include "game.h"
int main(int argc, char **argv){
init_all();
register_all();
init_game_bitmaps();
ALLEGRO_KEYBOARD_STATE key;
while (running) {
draw_game_bitmaps();
al_wait_for_event(event_queue, &e);
al_get_keyboard_state(&key);
control_actor(&key, &player, player.speed);
if (e.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
running = false;
}
if (e.type == ALLEGRO_EVENT_KEY_DOWN) {
if (e.keyboard.keycode == ALLEGRO_KEY_ESCAPE) {
running = false;
}
if (e.keyboard.keycode == ALLEGRO_KEY_ENTER) {
cout << "It works!";
}
}
}
destroy_all();
return 0;
}
The post on the allegro forums linked in the comment is from 2002, and that code does not work anymore on Allegro 5. So I've checked the docs, and I'll tell you: THE PROBLEM PERSISTED. The EXACT same thing happens. One arrow cancels the other and the player stops moving for a while, as soon as I press another arrow at the same time.
The Basic Keyboard Example on the allegro wiki may be of more help than that old post.
There is no need to manage multiple event queues here. Every key press and release should get pushed into the queue -- you just need to make sure you process every event in the queue.
Basically, you want a main loop that:
Processes every event currently in the queue
Updates the game state
Redraws the screen
Here is an example I drafted up:
#include <stdio.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_primitives.h>
const int SPEED = 5;
const float FPS = 60;
int main(int argc, char **argv) {
ALLEGRO_DISPLAY *display = NULL;
ALLEGRO_EVENT_QUEUE *event_queue = NULL;
ALLEGRO_TIMER *timer = NULL;
int x = 0, y = 0; // position
int vx = 0, vy = 0; // velocity
// initialize everything we need -- error checking omitted for brevity
al_init();
al_install_keyboard();
al_init_primitives_addon();
display = al_create_display(640, 480);
event_queue = al_create_event_queue();
timer = al_create_timer(1.0 / FPS);
al_register_event_source(event_queue, al_get_keyboard_event_source());
al_register_event_source(event_queue, al_get_timer_event_source(timer));
al_start_timer(timer);
bool done = false;
while(!done) {
bool redraw = false;
// process events until queue is empty
while(!al_is_event_queue_empty(event_queue)) {
ALLEGRO_EVENT ev;
al_wait_for_event(event_queue, &ev);
switch(ev.type) {
case ALLEGRO_EVENT_KEY_DOWN:
switch(ev.keyboard.keycode) {
case ALLEGRO_KEY_W:
vy -= SPEED; // add upward velocity
break;
case ALLEGRO_KEY_S:
vy += SPEED; // add downward velocity
break;
case ALLEGRO_KEY_A:
vx -= SPEED; // add leftward velocity
break;
case ALLEGRO_KEY_D:
vx += SPEED; // add leftward velocity
break;
case ALLEGRO_KEY_ESCAPE:
done = true;
break;
}
break;
case ALLEGRO_EVENT_KEY_UP:
switch(ev.keyboard.keycode) {
case ALLEGRO_KEY_W:
vy += SPEED; // remove upward velocity
break;
case ALLEGRO_KEY_S:
vy -= SPEED; // remove downward velocity
break;
case ALLEGRO_KEY_A:
vx += SPEED; // remove leftward velocity
break;
case ALLEGRO_KEY_D:
vx -= SPEED; // remove leftward velocity
break;
}
break;
case ALLEGRO_EVENT_TIMER:
redraw = true; // time for next frame
break;
}
}
// got through all the events this loop -- redraw if necessary
if (redraw) {
// move circle
x += vx;
y += vy;
// draw circle
al_clear_to_color(al_map_rgb(0, 0, 0));
al_draw_filled_circle(x, y, 20, al_map_rgb(0, 0, 255));
al_flip_display();
}
}
al_destroy_display(display);
return 0;
}
Note the while(!al_is_event_queue_empty(event_queue)). This ensures that we don't miss any event before moving on to the update loop.
If you try running the example, the circle should respond appropriately to any combination of the WASD keys.
If you hold S+D, it will move diagonally right and down.
Release S, and it will continue moving right, but not down.
Hope this helps!

Focus sprite by leftclick and then remove focus by leftclick again. (C++ and SFML 2.2)

In the following code a sprite can by clicked with left mouse button and then moved around freely. Then you have to hit the right button to "free" it again.
Now what is, if I want to use left button for removing the focus, instead of right button. Is this possible and how? I can't imagine, how to do it. Many thanks in advance.
#include <SFML/Graphics.hpp>
#include <iostream>
#include <vector>
int main()
{
sf::RenderWindow mMainWindow(sf::VideoMode(600,600), "Map", sf::Style::Close);
mMainWindow.setFramerateLimit(60);
mMainWindow.setKeyRepeatEnabled(false);
sf::Image image;
image.create(50, 50, sf::Color::Red);
sf::Texture texture;
texture.loadFromImage(image);
std::vector<sf::Sprite> EnemyVector;
sf::Sprite* focus = nullptr;
bool move = false;
while (mMainWindow.isOpen())
{
sf::Event event;
bool creating = false;
bool leftclicked = false;
bool rightclicked = false;
sf::Vector2i mousePos;
while (mMainWindow.pollEvent(event))
{
switch (event.type)
{
case sf::Event::Closed:
mMainWindow.close();
break;
case sf::Event::KeyPressed:
creating = (event.key.code == sf::Keyboard::A);
break;
case sf::Event::MouseButtonPressed:
if (event.mouseButton.button == sf::Mouse::Left)
{
leftclicked = true;
mousePos = sf::Vector2i(event.mouseButton.x, event.mouseButton.y);
break;
}
if (event.mouseButton.button == sf::Mouse::Right)
{
rightclicked = true;
mousePos = sf::Vector2i(event.mouseButton.x, event.mouseButton.y);
break;
}
}
}
if (creating)
{
sf::Sprite sprite;
mousePos = (mousePos == sf::Vector2i(0, 0) ? sf::Mouse::getPosition(mMainWindow) : mousePos);
sprite.setTexture(texture);
sprite.setColor(sf::Color::Red);
sprite.setOrigin(static_cast<float>(sprite.getTextureRect().width) / 2, static_cast<float>(sprite.getTextureRect().height) / 2);
sprite.setPosition(static_cast<float>(mousePos.x), static_cast<float>(mousePos.y));
focus=nullptr;
EnemyVector.push_back(sprite);
}
if (leftclicked)
{
for (auto& enemy = EnemyVector.rbegin(); enemy != EnemyVector.rend(); ++enemy)
{
if (enemy->getGlobalBounds().contains(static_cast<float>(mousePos.x), static_cast<float>(mousePos.y)))
{
focus = &(*enemy);
move = true;
break;
}
}
}
if(rightclicked)
{
focus = nullptr;
}
if(move)
{
if(focus!=nullptr)
{
focus->move((sf::Mouse::getPosition(mMainWindow).x - focus->getPosition().x),(sf::Mouse::getPosition(mMainWindow).y - focus->getPosition().y));
}
}
mMainWindow.clear();
for (auto& enemy = EnemyVector.rbegin(); enemy != EnemyVector.rend(); ++enemy)
{
mMainWindow.draw(*enemy);
}
mMainWindow.display();
}
return 0;
}
try this
if (leftclicked)
{
for (auto& enemy = EnemyVector.rbegin(); enemy != EnemyVector.rend(); ++enemy)
{
if (enemy->getGlobalBounds().contains(static_cast<float>(mousePos.x), static_cast<float>(mousePos.y)))
{
focus = &(*enemy);
move = !move;
break;
}
}
}

Handling multiple keypressess at the same time in SDL

I'm making a simple top down 2D shooter, where you move with WASD and shoot in the direction you're looking at with space. I can move and shoot just fine, but I can't do them both at the same time. For example if I'm shooting and start moving, my character will stop shooting until I release and press space again, and if I then start moving in another direction I have to release and press space again.
Here's my main method:
int main(int argc, char* args[])
{
if (!init())
{
log("Failed to initialize!\n");
}
else
{
log("Initialized SDL and SDL subsystems. \nLoading assets:\n");
if (!loadAssets())
{
printf("Failed to load assets!\n");
}
else
{
log("All assets loaded successfully.\n");
bool running = true;
SDL_Event e;
std::vector<Shot> shots;
LTimer shotTimer;
float cooldown = 250.0f;
float previousCooldown = 0.0f;
Player player;
log("Game running.\n");
shotTimer.start();
while (running)
{
while (SDL_PollEvent(&e) != 0)
{
if (e.type == SDL_QUIT)
{
log("SDL_QUIT event triggered.\n");
running = false;
}
else if (e.type == SDL_KEYDOWN)
{
switch (e.key.keysym.sym)
{
case SDLK_ESCAPE:
{
running = false;
break;
}
}
}
player.handleEvent(e);
if (SDL_GetTicks() - previousCooldown > cooldown)
{
previousCooldown = SDL_GetTicks();
shots = shoot(e, player, shots);
}
}
player.move();
for (int i = 0; i < shots.size(); i++)
{
shots[i].move();
}
/*if (shotTimer.getTicks() >= cooldown)
shotTimer.restart();*/
SDL_SetRenderDrawColor(renderer, 0xff, 0xff, 0xff, 0xff);
SDL_RenderClear(renderer);
background.render(0, 0);
for (int i = 0; i < shots.size(); i++)
{
shots[i].render();
}
player.render();
SDL_RenderPresent(renderer);
}
}
}
close();
return 0;
}
Here's my shoot() function, which is probably what's causing this:
std::vector<Shot> shoot(SDL_Event& e, Player player, std::vector<Shot> shots)
{
bool shoot = false;
if (e.type = SDL_KEYDOWN && e.key.repeat == 1)
{
switch (e.key.keysym.sym)
{
case SDLK_SPACE:
{
shoot = true;
break;
}
}
}
else if (e.type = SDL_KEYUP && e.key.repeat == 1)
{
switch (e.key.keysym.sym)
{
case SDLK_SPACE:
{
shoot = false;
break;
}
}
}
if (shoot)
{
Shot newShot(player.getDir(), player);
shots.push_back(newShot);
}
return shots;
}
And this is how I move the player
void Player::handleEvent(SDL_Event& e)
{
if (e.type == SDL_KEYDOWN && e.key.repeat == 0)
{
switch (e.key.keysym.sym)
{
case SDLK_w: mVelY -= PLAYER_VEL; mDir = 0; break;
case SDLK_s: mVelY += PLAYER_VEL; mDir = 1; break;
case SDLK_d: mVelX += PLAYER_VEL; mDir = 2; break;
case SDLK_a: mVelX -= PLAYER_VEL; mDir = 3; break;
}
}
else if (e.type == SDL_KEYUP && e.key.repeat == 0)
{
switch (e.key.keysym.sym)
{
case SDLK_w: mVelY += PLAYER_VEL; break;
case SDLK_s: mVelY -= PLAYER_VEL; break;
case SDLK_d: mVelX -= PLAYER_VEL; break;
case SDLK_a: mVelX += PLAYER_VEL; break;
}
}
}
Separate your event polling from the rest of the game logic.
Poll all events once per frame in a separate function and store the state of the keystates into an array. Then, when you need the state, simply check the array.
You can also use SDL_GetKeyboardState to sample the surrent state of the keys, without having to handle the key events yourself.

C++ SDL program terminates immediately

I've been following LazyFoo's tutorial for a while. But I haven't been able to get this to initialize a week a go. I went back to it recently, after error checking, I found it that the window initializes properly, but the images won't load. What is the reason for it?
#include "SDL/SDL.h"
#include <string>
//setting screen info
const int SCH=640;
const int SCW=480;
const int BBP=32;
const char* name = "TEHGAEM";
// sprite height and width
const int SPH=45;
const int SPW=45;
//initilize event
SDL_Event event;
//loading surfaces for screen, sprite, and temp sprite
SDL_Surface *screen=NULL;
SDL_Surface *sprite=NULL;
SDL_Surface *temp = NULL;
//making class for movable objects
class Player
{
private:
int x,y;
int xVel,yVel;
public:
Player();
void show();
void move();
void handle_input();
};
//initializing variables
Player::Player()
{
x=0;
y=0;
xVel=0;
yVel=0;
}
//intended to show player picture
void Player::show()
{
SDL_Rect pos;
pos.x=x;
pos.y=y;
SDL_BlitSurface(sprite, NULL, screen, &pos);
SDL_UpdateRects(screen, 1, &pos);
}
//setting input
void Player::handle_input()
{
if (event.type ==SDL_KEYDOWN)
{
switch (event.key.keysym.sym)
{
case SDLK_UP: yVel -= SPH /2; break;
case SDLK_DOWN: yVel += SPH /2; break;
case SDLK_LEFT: xVel -=SPW /2; break;
case SDLK_RIGHT: xVel +=SPW /2; break;
}
}
if (event.type == SDL_KEYUP)
{
switch(event.key.keysym.sym)
{
case SDLK_UP: yVel += SPH /2; break;
case SDLK_DOWN: yVel -= SPH /2; break;
case SDLK_LEFT: xVel +=SPW /2; break;
case SDLK_RIGHT: xVel -=SPW /2; break;
}
}
}
void Player::move()
{
x=+xVel;
y=+yVel;
if (x >= SCW)
{
x-10;
}
if (y >= SCH)
{
y-10;
}
}
//initializing program
bool init()
{
if (SDL_Init(SDL_INIT_EVERYTHING)==-1)
{
return false;
}
screen = SDL_SetVideoMode(SCH,SCW,BBP, SDL_SWSURFACE);
if (screen == NULL)
{
return false;
}
SDL_WM_SetCaption(name, NULL);
return true;
}
//loading images
bool somethings()
{
temp = SDL_LoadBMP("sprite.bmp");
if (temp == NULL)
{
return false;
}
sprite = SDL_DisplayFormat (temp);
if (sprite ==NULL)
{
return false;
}
SDL_FreeSurface(temp);
return true;
}
//clean up function
void clean()
{
SDL_FreeSurface(sprite);
SDL_Quit();
}
int main(int argc, char* args[])
{
Player P1;
bool quit;
if (init() == false)
{
return 1;
}
if (somethings() ==false)
{
return 1;
}
while (quit ==false)
{
while (SDL_PollEvent(&event))
{
P1.handle_input();
if (event.type == SDL_QUIT)
{
quit == true;
}
}
if (SDL_Flip(screen) ==-1)
{
return 1;
}
P1.move();
P1.show();
}
clean();
return 0;
}
This isn't completely related to your problem but the varible bool quit; isn't defined as true or false before the main while( quit == false ) { ... }loop. This could produce undefined while loop behavior.
int main(int argc, char* args[])
{
Player P1;
bool quit = false; // CHANGE THIS AND SEE WHAT HAPPENS
if (init() == false)
{
return 1;
}
if (somethings() ==false)
{
return 1;
}
while (quit ==false)
{
while (SDL_PollEvent(&event))
{
P1.handle_input();
if (event.type == SDL_QUIT)
{
quit == true;
}
}
if (SDL_Flip(screen) ==-1)
{
return 1;
}
P1.move();
P1.show();
}
clean();
return 0;
}
About the images not loading, step through your program with a debugger and watch your somethings()function and follow the variables temp and sprite.
Make sure your "sprite.bmp" file is located in the running directory of this program. I tested it and it works for me.
Also this has no effect:
if (x >= SCW)
{
x-10;
}
if (y >= SCH)
{
y-10;
}
You probably wanted to say x -= 10; and y -= 10;.
This makes your 'player' jump back to the original position immediately:
if (event.type == SDL_KEYUP)
{
switch(event.key.keysym.sym)
{
case SDLK_UP: yVel += SPH /2; break;
case SDLK_DOWN: yVel -= SPH /2; break;
case SDLK_LEFT: xVel +=SPW /2; break;
case SDLK_RIGHT: xVel -=SPW /2; break;
}
}
You probably only need to handle SDL_KEYDOWN event.
Hope that helps.
There are big chances that you aren't loading the bitmap. But anything that you are trying to print on the screen and wasn't loaded can terminate the app.