-1

I'm writing board game using SFML and I want my player's figures to move around this board, but I want this to be smooth animated move, from field X to field Y. Unfortunatelly, it isnt happening, my player's figures just changes location, it jumps from lets say field 4 into field 8, while I want to move from 4 to 5, then to 6, then to 7 and finnaly to 8. Hopefully its clear enough. Now let's see some code.

Firstly Field class.

class Field {
    int m_position_id;
    int m_position_x;
    int m_position_y;
    std::string m_name;
public:
    Field() {}
    Field(int, int, int);
    virtual ~Field() = default;

    int getPosID() { return m_position_id; }
    int getPosX() { return m_position_x; }
    int getPosY() { return m_position_y; }
};

Then we got Board which is basicly just an array of Fields

constexpr int BOARD_SIZE = 40;

    class Board {
        std::array<Field, BOARD_SIZE> m_board;
    public:
        Board();
        Field& getBoard(int index) { return m_board[index]; }
};

Player class

class Player {  
    int m_position_id = 0;  //starting position
    float m_position_x = 600; 
    float m_position_y = 600;   
    sf::CircleShape m_shape;    
public:
    Player(std::string, sf::Color, float);          
    sf::CircleShape& getShape() { return m_shape; }
    int getPositionID() { return m_position_id; }   
    float getPositionX() { return m_position_x; }
    float getPositionY() { return m_position_y; }
    void setPositionID(int p_position_id) { m_position_id = p_position_id; }
    void setPositionX(int p_position_x) { m_position_x = p_position_x; }
    void setPositionY(int p_position_y) { m_position_y = p_position_y; }
};

And finnaly, method that isnt working as I expect it oo

void GameEngine::movePlayer(Player &p_player, int p_distance) {     
    int l_current_pos_id = p_player.getPositionID();    

    p_player.setPositionID(p_player.getPositionID() + p_distance);
    p_player.setPositionX(m_game_board.getBoard(p_player.getPositionID()).getPosX());
    p_player.setPositionY(m_game_board.getBoard(p_player.getPositionID()).getPosY());
    if (p_player.getPositionID() > 39) {
        p_player.setPositionID(p_player.getPositionID() - 40);
        p_player.setPositionX(m_game_board.getBoard(p_player.getPositionID()).getPosX());
        p_player.setPositionY(m_game_board.getBoard(p_player.getPositionID()).getPosY());
    }       
    //going out of array range here probably
    for (int i = l_current_pos_id; i < p_player.getPositionID(); i++) {
        int x = m_game_board.getBoard(i + 1).getPosX() - m_game_board.getBoard(i).getPosX();
        int y = m_game_board.getBoard(i + 1).getPosY() - m_game_board.getBoard(i).getPosY();
        p_player.getShape().move(x, y); 
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
}

And finnaly, class that handles the view

bool m_draw = false;
while (window.isOpen()) {
    if (m_evnt.type == sf::Event::KeyReleased && m_evnt.key.code == sf::Keyboard::R) {
                //Roll dice
                m_game_engine.rollDice(m_game_status); //this just updates some text, result of rollDice is passed as p_distance to movePlayer
                m_draw = true;              
            }
}

window.clear(); 
for (int i = 0; i < m_game_engine.getNumberOfPlayers(); i++) {
    window.draw(m_game_engine.getPlayer(i).getShape());
}       

if (m_draw) {
    for (int i = 0; i < m_game_engine.getNumberOfPlayers(); i++) {
        window.draw(m_game_engine.getPlayer(i).getShape());
}

            window.display();
}

Ah and from GameEngine class

class GameEngine {
    std::vector<Player> m_players;
    Player& getPlayer(int index) { return m_players[index]; }
};

So as you can see, it stores in local variable current player position, then assigns new one, then by Field position ID it gets X and Y coordinate of this position. Next step is checking if this position is inside array (have to do the same for moving my figure around board, because it crashes after first circuit around the board. Still, thats not the point here. For loop at the end, should move from field i to (i+1), then it should wait for 0,5 sec, move again to next field, etc. Althought, after I run my program, it sleeps at beggining and then not moves, but changes position of my shape and its over, no animation at all.

JohnDoe
  • 179
  • 1
  • 4
  • 17
  • you're moving the player how you want but aren't allowing the game to draw since you're doing it all in one function. You'll need to spread out the movement over many update calls before each draw. So you'll probably need to store some `isMoving` field and a target `x` and `y` and move the player a little on each update call until the player is at the target. – kmdreko Dec 18 '17 at 00:02

1 Answers1

0

You have a loop and you have waits. That's not how a game works. You can read up on the basics here.

Your game loop has to run. That's the place where the drawing takes place. If you move your token and don't draw it until it arrived, it will look like a teleport. You need to draw between your mini-moves.

Your token needs a target position and a current position and a speed. And every loop you need to add the appropriate numbers to the current position, until it finally arrives at the target position. But you cannot do that in a closed loop, this needs to happen inside your game loop, as a part of it. You probably also want a variable that indicates that a token is indeed moving, so nothing else can happen while it's not complete.

nvoigt
  • 75,013
  • 26
  • 93
  • 142