Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: The Snake game. Movement problem with clocks  (Read 2388 times)

0 Members and 1 Guest are viewing this topic.

lowarago

  • Newbie
  • *
  • Posts: 10
    • View Profile
The Snake game. Movement problem with clocks
« on: March 08, 2017, 03:22:51 pm »
Hello, I am new to SFML, I've read about everything I need to know that would get me ready for making this game.

I have successfully managed to create a game. The problem is with the movement.
I used isKeyPressed with left,up,down,right keys and I used clock to slowdown the snake. I also put some if statements to check whether the snake is moving eg. right when I press LEFT so it prevents snake doing 180 deg.

If you press 1 key at time when you want to move snake, everything works perfectly, but as soon as I press multiple keys ( I also created an if statement to check if player is holding multiple keys, if he is, then don't do anything if not, change direction) and start going crazy with it a little bit snake does 180 deg turn and its "GAME OVER".

Why does this happen ? I think my code is alright, but something happens that I have no idea what it is.

This is my MAIN LOOP

        sf::Clock       clock;
        float           timer = 0;
        float           delay = 0.1;

        bool    left_pressed    = false;
        bool    right_pressed   = false;
        bool    down_pressed    = false;
        bool    up_pressed      = false;

        // MAIN GAME LOOP ////////////////////////////////////////////////
        while (win.isOpen()) {

                // Setting up the clock
                float   time    = clock.getElapsedTime().asSeconds();

                clock.restart();
                timer += time;


                //Checking for events : closing, escape, enter
                while (win.pollEvent(event)) {
                        switch (event.type) {
                        case sf::Event::Closed:
                                win.close();
                                break;
                        case sf::Event::KeyReleased:
                                switch (event.key.code) {
                                case sf::Keyboard::Escape:
                                        win.close();
                                        break;
                                case sf::Keyboard::Return:
                                        game_state = state_of_game::PLAYING;
                                        player.respawn();
                                        break;
                                default:
                                        break;
                                }
                               
                        default:
                                break;
                        }
                }
đ

                // CHECK IF YOU ATE YOURSELF //

                if (game_state == state_of_game::LOST) {

                        sf::Text        lost("GAME OVER", font, 100U);

                        lost.setFillColor(sf::Color::Red);

                        lost.setPosition(win_w / 2 - lost.getCharacterSize() * 3, win_h / 2 - lost.getCharacterSize());
                        win.draw(lost);

                }
                else {

                        left_pressed    = sf::Keyboard::isKeyPressed(sf::Keyboard::Left);
                        right_pressed   = sf::Keyboard::isKeyPressed(sf::Keyboard::Right);
                        down_pressed    = sf::Keyboard::isKeyPressed(sf::Keyboard::Down);
                        up_pressed      = sf::Keyboard::isKeyPressed(sf::Keyboard::Up);


                        keys_down = (short)left_pressed + (short)right_pressed + (short)down_pressed + (short)up_pressed;


                        // MOVEMENT
                        if(keys_down==1){
                                if (left_pressed) {
                                        if (dir != Right)       dir = Left;
                                }
                                else if (right_pressed){
                                        if (dir != Left)        dir = Right;
                                }
                                else if (up_pressed) {
                                        if (dir != Down)         dir = Up;
                                }
                                else if (down_pressed) {
                                        if (dir != Up)   dir = Down;
                                }
                        }

                        // UPDATING SNAKE WITH DELAY TO REDUCE ITS SPEED
                        if (timer >= delay) {          
                                timer = 0;             
                                player.update();
                        }

                        //Clear the window with color WHITE
                        win.clear(sf::Color::White);

                        /////// Draw everything here ///////////
                        //win.draw(...);
               
                        // Draw lines
                        //win.draw(d_bgr);
                       

                        //Draw the snake
                        for (int i = 0; i < player.get_size(); i++) {
                                win.draw(player[i]);
                        }
               
                        // Draw the goal
                        win.draw(v_goal.draw());


                        //Draw the wall
                        for (int i = 0; i < wall_vec.size(); i++) {
                                wall_sprite.setPosition(wall_vec[i][0], wall_vec[i][1]);
                                win.draw(wall_sprite);
                        }
                }

                //end of frame
                win.display();
        }


 

This is my update function in object player.

void update() {
                short   last_x = snake_tail[snake_tail.size() - 1].getPosition().x;
                short   last_y = snake_tail[snake_tail.size() - 1].getPosition().y;

                for (int i = snake_tail.size() - 1; i > 0; --i) {
                        snake_tail[i].setPosition(snake_tail[i - 1].getPosition().x, snake_tail[i - 1].getPosition().y);
                }
               
                 
                switch (dir)
                {
                        // Move snake

                case Left: //left
                        head_x -= N;
                        break;
                case Right: //right
                        head_x += N;
                        break;
                case Up: //up
                        head_y -= N;
                        break;
                case Down: //Down
                        head_y += N;
                        break;

                }

                snake_tail[0].setPosition(head_x, head_y);
                short i = 0;
               

                for (i = 1; i < snake_tail.size(); i++) {
                        get_x = snake_tail[i].getPosition().x;
                        get_y = snake_tail[i].getPosition().y;

                        if ( get_x == head_x && get_y == head_y) {
                                game_state = { LOST };
                        }
                }
                if (game_state != LOST){
                // CHECK IF SNAKE HIT THE WALL

                        if (head_x == 0)                                game_state = LOST;
                        else if (head_x == win_w - 16)  game_state = LOST;
                        else if (head_y == 0)                   game_state = LOST;
                        else if (head_y == win_h - 16)  game_state = LOST;
                }

                // Check if goal is at that position
                if(game_state!=LOST)
                if (v_goal.x == head_x && v_goal.y == head_y) {
                        // Increase size
                        for (i = 0; i < v_goal.increase; i++) {
                                snake_tail.push_back(snake_sprite);
                                snake_size++;
                                snake_tail[snake_tail.size() - 1].setPosition(last_x, last_y);
                        }                      

                        // RESPAWN THE GOAL
                        v_goal.respawn(snake_tail);
                }
               
        }
 


Sorry if I didn't explain it well (the problem). Game is working, but sometimes when I press 2 keys at once it does the 180 turn, but sometimes I go really crazy and start pressing 3 keys and try everything and it works normally and it comes back again.

What might cause this ? Any ideas ?

Arcade

  • Full Member
  • ***
  • Posts: 230
    • View Profile
Re: The Snake game. Movement problem with clocks
« Reply #1 on: March 08, 2017, 04:56:29 pm »
I only spent a very brief amount of time looking over your code, but I may have spotted the problem.

It looks like the issue could be when two keys are pressed, not necessarily at the same time, but immediately back-to-back. You only update the position of your snake once every 0.1 seconds, but you allow the direction to change every step of your game loop. Think about what will happen if the snake is moving to the right and you press the Up key and then Left key within 0.1 seconds.

You will probably need to be a little more clever with how you handle inputs. If more than 1 key is pressed between calls to player.update() then you will need to see if it is a valid direction based on the original snake direction, not necessarily the current direction if that makes sense.

lowarago

  • Newbie
  • *
  • Posts: 10
    • View Profile
Re: The Snake game. Movement problem with clocks
« Reply #2 on: March 08, 2017, 11:44:10 pm »
Yeah, that's the problem (test it with increasing the delay value). I knew it was clock all along. Now I have to come up with new way of moving the snake to prevent this from happening.

EDIT:

Solved it !!!

It was pretty damn simple. I just added new public member "my_dir" inside snake class that is going to return a direction of snake.

left_pressed    = sf::Keyboard::isKeyPressed(sf::Keyboard::Left);
                        right_pressed   = sf::Keyboard::isKeyPressed(sf::Keyboard::Right);
                        down_pressed    = sf::Keyboard::isKeyPressed(sf::Keyboard::Down);
                        up_pressed              = sf::Keyboard::isKeyPressed(sf::Keyboard::Up);


                        keys_down               = (short)left_pressed + (short)right_pressed + (short)down_pressed + (short)up_pressed;


                        // MOVEMENT
                        if(keys_down==1){
                                if (left_pressed) {
                                        if (player.my_dir != Right)     dir = Left;
                                }
                                else if (right_pressed){
                                        if (player.my_dir != Left)      dir = Right;
                                }
                                else if (up_pressed) {
                                        if (player.my_dir != Down)      dir = Up;
                                }
                                else if (down_pressed) {
                                        if (player.my_dir != Up)        dir = Down;
                                }
                        }

                        // UPDATING SNAKE WITH DELAY TO REDUCE ITS SPEED
                        if (timer >= delay) {          
                                timer = 0;             
                                player.update();
                                //timer.restart();
                        }
 


SNAKE CLASS UPDATE FUNCTION

void update() {
                short   last_x = snake_tail[snake_tail.size() - 1].getPosition().x;
                short   last_y = snake_tail[snake_tail.size() - 1].getPosition().y;

                for (int i = snake_tail.size() - 1; i > 0; --i) {
                        snake_tail[i].setPosition(snake_tail[i - 1].getPosition().x, snake_tail[i - 1].getPosition().y);
                }
               
                 
                switch (dir)
                {
                        // Move snake

                case Left: //left
                        head_x -= N;
                        break;
                case Right: //right
                        head_x += N;
                        break;
                case Up: //up
                        head_y -= N;
                        break;
                case Down: //Down
                        head_y += N;
                        break;

                }
                my_dir = dir; // Here
                snake_tail[0].setPosition(head_x, head_y);
                short i = 0;

                .
                .
                .
 

Thank you Arcade !
« Last Edit: March 08, 2017, 11:57:41 pm by lowarago »

 

anything