I cant get last position



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
  #include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <iostream>
#include <vector>

sf::Vector2f SNAKE_SIZE{15.f, 15.f};
struct snake_body
{   
    int last_x = 0;
    int last_y = 0;
    sf::RectangleShape body{SNAKE_SIZE};

};

class Snake{

    public:    
    
    int x = 0;
    int y = 0;
    int last_x = 0;
    int last_y = 0;

    sf::RectangleShape snek_head{SNAKE_SIZE};
    std::vector<snake_body> snake_bod;
    


    void update_pos(){
        for (int i = 0; i < snake_bod.size(); i++)
        {
            std::cout<<i<<"::"<<snake_bod[i].last_x<<"."<<snake_bod[i].last_y<<std::endl;
            std::cout<<i<<"::"<<snake_bod[i].body.getPosition().x<<"."<<snake_bod[i].body.getPosition().y<<std::endl;
            if ((&snake_bod[i] == &snake_bod[0]) == 1 ){
                snake_bod[0].last_x = last_x;
                snake_bod[0].last_y = last_y;
                snake_bod[0].body.setPosition(snake_bod[0].last_x,snake_bod[0].last_y);
                
            }
            else{
                snake_bod[i].last_y = snake_bod[i-1].last_y;
                snake_bod[i].last_x = snake_bod[i-1].last_x;
                snake_bod[i].body.setPosition(snake_bod[i].last_x,snake_bod[i].last_y);
            }
        }

    }
    void draw(sf::RenderWindow& win){
        win.draw(snek_head);
        for (int i = 0; i < snake_bod.size(); i++)
        {
        win.draw(snake_bod[i].body);
        }
        
        
    }
    void move(int _x,int _y){
    last_x = snek_head.getPosition().x;
    last_y = snek_head.getPosition().y;
    update_pos();
    snek_head.move(_x,_y);
    }
    
    void add_body(){
    snake_bod.push_back(snake_body());
    }
};
 ||||||||| Main.cppp |||||

#define SNAKE_STEP 12

    

int main(){

sf::RenderWindow window(sf::VideoMode(400, 400), "SFML works!");
//window.setFramerateLimit(60); 
sf::View view(sf::FloatRect(0, 0, window.getSize().y, window.getSize().x));

Snake snake;
snake.add_body();
snake.add_body();
snake.add_body();
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
            else if (event.type == sf::Event::Resized) view.setSize(window.getSize().x , window.getSize().y);

            else if (1 == sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) snake.move(SNAKE_STEP,0);
            else if (1 == sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) snake.move(-SNAKE_STEP,0);         
            else if (1 == sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) snake.move(0,-SNAKE_STEP);
            else if (1 == sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) snake.move(0,SNAKE_STEP);
            else if (1 == sf::Keyboard::isKeyPressed(sf::Keyboard::H)) snake.add_body();
            }
        // snake.update_pos();
        window.clear();
        window.setView(view);
        snake.draw(window);
        window.display();

         }

    return 0;
    }


Im doing a snake game and this code isnt working because i dont what to do to get last position in update_pos() (its working with only 2 squares)
Could you help me?
Last edited on
You don't need last_x/last_y:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
struct snake_body
{   
    int x = 0;
    int y = 0;
    sf::RectangleShape body{SNAKE_SIZE};

};

class Snake{

    public:    
    
    int x = 0;
    int y = 0;

    sf::RectangleShape snek_head{SNAKE_SIZE};
    std::vector<snake_body> snake_bod;
    


    void update_pos(int head_x,int head_y){
        int cur_x = head_x;
        int cur_y = head_y;
        for (int i = 0; i < snake_bod.size(); i++)
        {
                int body_x = snake_bod[i].x;
                int body_y = snake_bod[i].y;

                snake_bod[i].y = cur_y;
                snake_bod[i].x = cur_x;
                ...
                cur_x = body_x;
                cur_y = body_y;
        }

    }
    void draw(sf::RenderWindow& win){
        win.draw(snek_head);
        for (int i = 0; i < snake_bod.size(); i++)
        {
        win.draw(snake_bod[i].body);
        }
        
        
    }
    void move(int _x,int _y){
    head_x = snek_head.getPosition().x;
    head_y = snek_head.getPosition().y;
    update_pos(head_x, head_y);
    snek_head.move(_x,_y);
    }
    
    void add_body(){ // Note: Doesn't work
    snake_bod.push_back(snake_body());
    }
};
Not tested!

The next problem is add_body(). You need to determine where to add the body:
1
2
3
4
5
6
7
8
    void add_body(){
    assert(not snake_bod.empty());
    end_x = snake_bod.back().x;
    end_y = snake_bod.back().y;
    snake_bod.push_back(snake_body());
    snake_bod.back().x = end_x + SNAKE_SIZE;
    snake_bod.back().y = end_y;
    }
This will add a body at the end in x direction.

Note that it is not tested. It is solely intended to give you the idea how to change things.
@coder777
i used your code in update_pos() and it works
could you explain your code please?
i dont know why or how this works
Last edited on
It works because any part of the snake always gets the position of its predecessor (0->1->2...). Hence no last_. is necessary. Only the head (at index 0) gets a new position.
@coder777
when I change the step the squares get on top of each other, could you give an idea on how to change that?
What do you mean by 'change the step'?

My guess is that you don't clear the screen before you move the snake? You should do so otherwise you have remains from the previous position.
@coder777 i mean SNAKE_STEP, if it is lower than the snake_size the body gets smaller (the squares get closer together), and i dont want that, i just want it to have smaller steps
Last edited on
In order to achieve you need to get rid of the coordinates/rectangles of the body. You don't need that:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
enum class position { left, right, top, bottom };

struct snake_body
{   
    position pos = position::right; // Note: a body part starts right of the previous / You may change that
};

class Snake{

    public:    
    
    int x = 0;
    int y = 0;

    std::vector<snake_body> snake_bod;
    


    void update_pos(position pos){
        position cur_pos = pos;
        for (int i = 0; i < snake_bod.size(); i++)
        {
                int body_pos = snake_bod[i].pos;

                snake_bod[i].pos = cur_pos;

                cur_pos = body_pos;
        }

    }
    void draw(sf::RenderWindow& win){

        sf::RectangleShape rect{SNAKE_SIZE};
        rect.setPosition(x, y);

        int cur_x = x;
        int cur_y = y;

        win.draw(rect);
        for (int i = 0; i < snake_bod.size(); i++)
        {
        switch(snake_bod[i].pos)
        {
          case position::right:
            cur_x += SNAKE_SIZE;
            break;
          case position::left:
            cur_x -= SNAKE_SIZE;
            break;
          case position::top:
            cur_y -= SNAKE_SIZE;
            break;
          case position::bottom:
            cur_y += SNAKE_SIZE;
            break;
        }
        rect.setPosition(cur_x, cur_y);
        win.draw(rect);
        }
        
        
    }
    void move(int _x,int _y){
    if(_x < 0)
      update_pos(position::right);
    else if(_x > 0)
      update_pos(position::left);
    else if(_y > 0)
      update_pos(position::top);
    else if(_y < 0)
      update_pos(position::bottom);
    x = _x
    y = _y;
    }
    
    void add_body(){
    snake_bod.push_back(snake_body{});
    }
};
Note: Not tested. Especially the switch(...)/update_pos(...) might need some adjustment.
im sorry i didnt post my current code, i want STEP to be different from the SNAKE_SIZE without it shrinking. wont your code be the same as mine?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
int SNAKE_size = 1;

sf::Vector2f SNAKE_SIZE{15.f, 15.f};
struct snake_body
{   
    int x;
    int y;
    sf::RectangleShape body{SNAKE_SIZE};
    //body.setFillColor(sf::Color::Green);

};

class Snake{

    public:    
    
    int x = 0;
    int y = 0;
    int end_x;
    int end_y;
    sf::RectangleShape snek_head{SNAKE_SIZE};
    std::vector<snake_body> snake_bod;
    


    void update_pos(){
        int cur_x = snek_head.getPosition().x;
        int cur_y = snek_head.getPosition().y;
        int body_x;
        int body_y;
        for (int i = 0; i < snake_bod.size(); i++)
        {
            body_x = snake_bod[i].x;
            body_y = snake_bod[i].y;
            snake_bod[i].y = cur_y;
            snake_bod[i].x = cur_x;
            snake_bod[i].body.setPosition(cur_x,cur_y);
            cur_x = body_x;
            cur_y = body_y;
        }

    }
    void draw(sf::RenderWindow& win){
        for (int i = 0; i < snake_bod.size(); i++)
        {
        win.draw(snake_bod[i].body);
        }
        win.draw(snek_head);
        
        
    }
    void move(sf::Vector2f dir){
    update_pos();
    snek_head.move(dir.x,dir.y);
    
    }
    
    void add_body(){
    SNAKE_size = snake_bod.size();
    end_x = snake_bod.back().x;
    end_y = snake_bod.back().y;
    snake_bod.push_back(snake_body());
    snake_bod.back().x = snek_head.getPosition().x;
    snake_bod.back().y = snek_head.getPosition().y;
    for (int i = 0; i < snake_bod.size(); i++){
        snake_bod[i].body.setFillColor(sf::Color::Green);
    }
    snek_head.setFillColor(sf::Color::Yellow);
    update_pos();
    }
    
};
||||||||||||||||||||||main.cpp|||||||||||||||||||||||

#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include "snake.cpp"
#include <iostream>
#include <vector>
sf::Vector2f direction;// (0,1):Up (0,-1):Down (-1,0):Left (1,0):Right
float STEP = 15.f;

int main(){

sf::RenderWindow window(sf::VideoMode(400, 400), "SFML works!");
//window.setFramerateLimit(60); 
sf::View view(sf::FloatRect(0, 0, window.getSize().y, window.getSize().x));
float dt = 0;
float dtMult;
float Time;
float Time1;
float move_t = 0.1;
bool move_b = true;
sf::Clock clock;
Snake snake;
snake.snake_bod.push_back(snake_body());
snake.add_body();
snake.add_body();
snake.add_body();
int i = 0;
    while (window.isOpen())
    {
        float currentTime = clock.restart().asSeconds();
        float fps = 1.f / currentTime;
        Time += currentTime;
        Time1 += currentTime;
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
            else if (event.type == sf::Event::Resized) view.setSize(window.getSize().x , window.getSize().y);

            else if (1 == sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) direction = sf::Vector2f{STEP,0};
            else if (1 == sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) direction = sf::Vector2f{-STEP,0};         
            else if (1 == sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) direction = sf::Vector2f{0,-STEP};
            else if (1 == sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) direction = sf::Vector2f{0,STEP};
            else if (1 == sf::Keyboard::isKeyPressed(sf::Keyboard::H)) STEP = 6;
            }

        if ((Time1 <= move_t and move_b == true )){
        snake.move(direction);
        std::cout << "here"<<std::endl;
        move_b = false;
        }
        else if ((Time1 >= move_t)) {
            move_b = true;
            Time1 = 0;
            }
        window.clear();
        window.setView(view);
        snake.draw(window);
        window.display();
         }

    return 0;
    }

Last edited on
wont your code be the same as mine?
No. I removed the rectangle from the snake. It is know calculated within the draw(...) function. Also I removed the coordinates from the snake body. Instead it contains the relative position. This enables that STEP could be different from SNAKE_SIZE.
when i try your code the snake rotates faster than it moves (it is acting like a whip i dont know how to explain) and when i change the SNAKE_SIZE to STEP in the the switch case the snake gets smaller like it happens in my code
Topic archived. No new replies allowed.