ZNelson1989
ZNelson1989

Reputation: 3

SFML Shape Not Drawn after Move

Following an SFML tutorial. This code should allow for me to move a cyan circle around the screen. Drawing the circle without using mPlayer.move(movement) works fine but when this line is ran in game.update the shape vanishes from screen never to be redrawn. What am I missing?

Game.cpp 

   Game::Game()
    :mWindow(sf::VideoMode(1440, 900, 32),"yeeboi1!!!!!") , mPlayer()
    {
    mPlayer.setRadius(20.f);
    mPlayer.setPosition(100.f, 110.f);
    mPlayer.setFillColor(sf::Color::Cyan);
    }


    Game::~Game()
{
}

    void Game::run() {
    while (mWindow.isOpen()) {
        processEvents();
        update();
        render();
    }
}

    void Game::processEvents()
    {
        sf::Event event;
        while (mWindow.pollEvent(event))
    {
            switch (event.type)
        {
        case sf::Event::KeyPressed:
            HandleInput(event.key.code, true);
            break;
        case sf::Event::KeyReleased:
            HandleInput(event.key.code, false);
            break;
        case sf::Event::Closed:
            mWindow.close();
            break;
        }

    }
}

    void Game::update() {
    sf::Vector2f movement(0.f, 0.f);
    if (mMoveUp)
        movement.y -= 1.f;
    if (mMoveDown)
        movement.y += 1.f;
    if (mMoveLeft)
        movement.x-= 1.f;
    if (mMoveRight)
        movement.x += 1.f;

    mPlayer.move(movement);




}

    void Game::render() {
    mWindow.clear();
    mWindow.draw(mPlayer);
    mWindow.display();
}

    void Game::HandleInput(sf::Keyboard::Key key, bool isPressed) {
    if (key == sf::Keyboard::W)
        mMoveUp = isPressed;
    if (key == sf::Keyboard::S)
        mMoveDown = isPressed;
    if (key == sf::Keyboard::A)
        mMoveLeft = isPressed;
    if (key == sf::Keyboard::D)
        mMoveRight = isPressed;
}



Game.h 

    #pragma once
    #include <SFML/Graphics.hpp>
    class Game
    {
    public:
    Game();
    ~Game();


    void run();

    private:
    void processEvents();
    void update();
    void render();
    void HandleInput(sf::Keyboard::Key key, bool isPressed);
    bool mMoveUp, mMoveDown, mMoveLeft, mMoveRight = false;

    private:
    sf::RenderWindow mWindow;
    sf::CircleShape mPlayer;
};




Main.cpp

#include "Game.h"


    int main()
    {
    Game game;
    game.run();

    return 0;
    }

Upvotes: 0

Views: 347

Answers (2)

Martin Sand
Martin Sand

Reputation: 518

Why not moving to a time based processing? Make sure you read http://gameprogrammingpatterns.com/game-loop.html as well.

I am currently sitting in the train so please apologize this short answer, but I guess you get the idea. See changes in Game::run and update(dtAsSeconds)

Game.cpp
#include "Game.h"

Game::Game()
 :mWindow(sf::VideoMode(1440, 900, 32),"yeeboi1!!!!!") , mPlayer()
 {
 mPlayer.setRadius(20.f);
 mPlayer.setPosition(100.f, 110.f);
 mPlayer.setFillColor(sf::Color::Cyan);
 }


 Game::~Game()
{
}

 void Game::run() {
   sf::Clock m_Clock = sf::Clock();

 while (mWindow.isOpen()) {
    sf::Time dt = m_Clock.restart();

    // Count seconds since last process
    float dtAsSeconds = dt.asSeconds();

     processEvents();
     update(dtAsSeconds);
     render();
 }
}

 void Game::processEvents()
 {
     sf::Event event;
     while (mWindow.pollEvent(event))
 {
         switch (event.type)
     {
     case sf::Event::KeyPressed:
         HandleInput(event.key.code, true);
         break;
     case sf::Event::KeyReleased:
         HandleInput(event.key.code, false);
         break;
     case sf::Event::Closed:
         mWindow.close();
         break;
     }

 }
}

 void Game::update(float dtAsSeconds) {
 sf::Vector2f movement(0.f, 0.f);
 if (mMoveUp)
     movement.y -= 1.f * dtAsSeconds * 100;
 if (mMoveDown)
     movement.y += 1.f * dtAsSeconds * 100;
 if (mMoveLeft)
     movement.x-= 1.f * dtAsSeconds * 100;
 if (mMoveRight)
     movement.x += 1.f * dtAsSeconds * 100;

 mPlayer.move(movement);




}

 void Game::render() {
 mWindow.clear();
 mWindow.draw(mPlayer);
 mWindow.display();
}

 void Game::HandleInput(sf::Keyboard::Key key, bool isPressed) {
 if (key == sf::Keyboard::W)
     mMoveUp = isPressed;
 if (key == sf::Keyboard::S)
     mMoveDown = isPressed;
 if (key == sf::Keyboard::A)
     mMoveLeft = isPressed;
 if (key == sf::Keyboard::D)
     mMoveRight = isPressed;
}

Game.h

#pragma once
#include <SFML/Graphics.hpp>
class Game
{
public:
Game();
~Game();


void run();

private:
void processEvents();
void update(float dtAsSeconds);
void render();
void HandleInput(sf::Keyboard::Key key, bool isPressed);
bool mMoveUp, mMoveDown, mMoveLeft, mMoveRight = false;

private:
sf::RenderWindow mWindow;
sf::CircleShape mPlayer;
};

main.cpp

#include "Game.h"

int main()
{
Game game;
game.run();

return 0;
}

Upvotes: 3

D. Christopher
D. Christopher

Reputation: 119

Your game is running as fast as it can, (which means that your circle is flying off the screen at the slightest input). Try limiting the framerate:

mWindow.setFramerateLimit(60);

Then every call to mWindow.display() will wait a bit.

EDIT: Make sure that your objects are not dependent on framerate. You can do this using sf::Clock.

class Game {
...
sf::Clock mClock;
}

Then in your update function, multiply the output by deltaTime:

void Game::update(sf::Time dt) {
    sf::Vector2f movement(0.f, 0.f);
    if (mMoveUp)
        movement.y -= 1.f * dt.asSeconds();
    ...
    mPlayer.move(movement);
}

//Now you can call the function
update(mClock.restart());

Upvotes: 0

Related Questions