-4

I'm trying to make a snake game in C++ with SFML. Here is my code below. The problem is that I don't know how I could possibly make the snake bite himself : each snake block takes the position of the last one, resulting in a perfectly straight snake. So it's more of an algorithm problem. Thanks for your advices :) BTW Didn't put hashtages and < in the include because the editor takes them away :/ BTW2: Looked for similar responses but none of them were with my approach or were in another language. Here you go:

#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <SFML/Audio.hpp>
#include <deque>

void selfIncrement();

sf::Event event;
sf::Clock clockSnake;
sf::Time elapse;

enum Direction { Up, Down, Left, Right};

int dir = Up;

int n = 1;

class SnakeBlock
{
public:

SnakeBlock * next;
sf::Texture texture;
sf::Sprite snakeblock;
int lastX, lastY;
};

std::deque<SnakeBlock> Snake;

int main()
{
elapse = clockSnake.getElapsedTime();

sf::Music epicMusic;
epicMusic.openFromFile("epicmusic.wav");
epicMusic.play();

SnakeBlock snakeHead;
snakeHead.texture.loadFromFile("spritesheetsnake.png", sf::IntRect(0,0,20,22));
snakeHead.snakeblock.setTexture(snakeHead.texture);
SnakeBlock snakeBody1;
snakeBody1.snakeblock.setTexture(*(snakeHead.snakeblock.getTexture()));
SnakeBlock snakeBody2;
snakeBody2.snakeblock.setTexture(*(snakeHead.snakeblock.getTexture()));

Snake.push_front(snakeHead);
Snake.push_front(snakeBody1);
Snake.push_front(snakeBody2);
Snake[2].snakeblock.setPosition(500,350);
Snake[1].snakeblock.setPosition(475, 338);
Snake[0].snakeblock.setPosition(450, 316);

sf::RenderWindow window(sf::VideoMode(1028,768), "SFML Snake");
window.setFramerateLimit(60);
while(window.isOpen())
{
    while(window.pollEvent(event))
    {
        switch(event.type)
        {
            case sf::Event::Closed:
            epicMusic.stop();
            window.close();
            break;

            default:
            break;
        }

    }

    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
    {
            dir = Left;
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
    {
            dir = Right;
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
    {
            dir = Down;
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
    {
            dir = Up;
    }
    if(dir == Up)
    {

        Snake[0].snakeblock.move(0,-2);
        Snake[n].snakeblock.setPosition(Snake[n-1].snakeblock.getPosition().x, Snake[n-1].snakeblock.getPosition().y+20);
    }
    if(dir == Down)
    {
        Snake[0].snakeblock.move(0,2);
        Snake[n].snakeblock.setPosition(Snake[n-1].snakeblock.getPosition().x, Snake[n-1].snakeblock.getPosition().y-20);
    }
    if(dir == Left)
    {
        Snake[0].snakeblock.move(-2,0);
        Snake[n].snakeblock.setPosition(Snake[n-1].snakeblock.getPosition().x+20, Snake[n-1].snakeblock.getPosition().y);
    }
    if(dir == Right)
    {
        Snake[0].snakeblock.move(2,0);
        Snake[n].snakeblock.setPosition(Snake[n-1].snakeblock.getPosition().x-20, Snake[n-1].snakeblock.getPosition().y);
    }
    window.clear(sf::Color::Red);
    n++;
    if( n > 2)
    {
        n = 1;
    }
    //selfIncrement();
    for(unsigned int m = 0; m < Snake.size(); m++)
    {
        window.draw(Snake[m].snakeblock);
    }

    window.display();
}
return 0;

}

/*void selfIncrement()
{
elapse = clockSnake.getElapsedTime();
if(elapse.asSeconds() > 0.10)
{
    n++;
    clockSnake.restart();
}
if(n > Snake.size())
{
    n = 1;
}
}
*/

NEW CODE using new principle::

#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <SFML/Audio.hpp>
#include <deque>

void advanceStep();

sf::Event event;
sf::Clock clockSnake;
sf::Time elapse;

enum Direction { Up, Down, Left, Right};

sf::Vector2i direction;
int dir = Up;

int n = 1;

class SnakeBlock
{
public:

sf::Texture texture;
sf::Sprite snakeblock;
int dir = 0;
int lastX, lastY;
};

SnakeBlock element;
std::deque<SnakeBlock> Snake;

int main()
{
elapse = clockSnake.getElapsedTime();

sf::Music epicMusic;
epicMusic.openFromFile("epicmusic.wav");
epicMusic.play();

SnakeBlock snakeHead;
snakeHead.texture.loadFromFile("spritesheetsnake.png", sf::IntRect(0,0,20,22));
snakeHead.snakeblock.setTexture(snakeHead.texture);
SnakeBlock snakeBody1;
snakeBody1.snakeblock.setTexture(*(snakeHead.snakeblock.getTexture()));
SnakeBlock snakeBody2;
snakeBody2.snakeblock.setTexture(*(snakeHead.snakeblock.getTexture()));

Snake.push_front(snakeHead);
Snake.push_front(snakeBody1);
Snake.push_front(snakeBody2);
Snake[2].snakeblock.setPosition(500,350);
Snake[1].snakeblock.setPosition(475, 338);
Snake[0].snakeblock.setPosition(450, 316);

sf::RenderWindow window(sf::VideoMode(1028,768), "SFML Snake");
window.setFramerateLimit(10);
while(window.isOpen())
{
    while(window.pollEvent(event))
    {
        switch(event.type)
        {
            case sf::Event::Closed:
            epicMusic.stop();
            window.close();
            break;

            default:
            break;
        }

    }

    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
    {
            dir = Left;
            direction.x = -1;
            direction.y = 0;
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
    {
            dir = Right;
            direction.x = 1;
            direction.y = 0;
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
    {
            dir = Down;
            direction.x = 0;
            direction.y = -1;
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
    {
            dir = Up;
            direction.x = 0;
            direction.y = 1;
    }
    if(dir == Up)
    {

        Snake[0].snakeblock.move(0,-2);
        Snake[1].snakeblock.setPosition(Snake[0].snakeblock.getPosition().x, Snake[0].snakeblock.getPosition().y+20);
        Snake[2].snakeblock.setPosition(Snake[1].snakeblock.getPosition().x, Snake[1].snakeblock.getPosition().y+20);
    }
    if(dir == Down)
    {
        Snake[0].snakeblock.move(0,2);
        Snake[1].snakeblock.setPosition(Snake[0].snakeblock.getPosition().x, Snake[0].snakeblock.getPosition().y-20);
        Snake[2].snakeblock.setPosition(Snake[1].snakeblock.getPosition().x, Snake[1].snakeblock.getPosition().y-20);
    }
    if(dir == Left)
    {
        Snake[0].snakeblock.move(-2,0);
        Snake[1].snakeblock.setPosition(Snake[0].snakeblock.getPosition().x+20, Snake[0].snakeblock.getPosition().y);
        Snake[2].snakeblock.setPosition(Snake[1].snakeblock.getPosition().x+20, Snake[1].snakeblock.getPosition().y);
    }
    if(dir == Right)
    {
        Snake[0].snakeblock.move(2,0);
        Snake[1].snakeblock.setPosition(Snake[0].snakeblock.getPosition().x-20, Snake[0].snakeblock.getPosition().y);
        Snake[2].snakeblock.setPosition(Snake[1].snakeblock.getPosition().x-20, Snake[1].snakeblock.getPosition().y);
    }
    window.clear(sf::Color::Red);
    advanceStep();
    for(unsigned int m = 0; m < Snake.size(); m++)
    {
        window.draw(Snake[m].snakeblock);
    }
    window.display();
}
return 0;

}

void advanceStep()
{
sf::Vector2f headpos(Snake[0].snakeblock.getPosition());

headpos.x += 22 * direction.x;
headpos.y += 22 * direction.y;

Snake[0].snakeblock.setPosition(headpos);

Snake.pop_back();
Snake.push_front(Snake[0]);
}

NEW CODE TAKING IN ACCOUNT EVERYTHING YOU ALL SAID, but now the snake just disappear, probably because of the pop_back..

#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <SFML/Audio.hpp>
#include <deque>

void advanceStep();

sf::Event event;
sf::Clock clockSnake;
sf::Time elapse;

enum Direction { Up, Down, Left, Right};

sf::Vector2i direction(0, 0);
int dir = Up;


class SnakeBlock
{
public:

sf::Texture texture;
sf::Sprite snakeblock;
int dir;
};

std::deque<SnakeBlock> Snake;

int main()
{
elapse = clockSnake.getElapsedTime();

sf::Music epicMusic;
epicMusic.openFromFile("epicmusic.wav");
epicMusic.play();

SnakeBlock snakeHead;
snakeHead.texture.loadFromFile("spritesheetsnake.png", sf::IntRect(0,0,20,22));
snakeHead.snakeblock.setTexture(snakeHead.texture);
SnakeBlock snakeBody1;
snakeBody1.snakeblock.setTexture(*(snakeHead.snakeblock.getTexture()));
SnakeBlock snakeBody2;
snakeBody2.snakeblock.setTexture(*(snakeHead.snakeblock.getTexture()));

Snake.push_back(snakeHead);
Snake.push_back(snakeBody1);
Snake.push_back(snakeBody2);

Snake[2].snakeblock.setPosition(500,350);
Snake[1].snakeblock.setPosition(475, 338);
Snake[0].snakeblock.setPosition(450, 316);

sf::RenderWindow window(sf::VideoMode(1028,768), "SFML Snake");
window.setFramerateLimit(1);
while(window.isOpen())
{
    while(window.pollEvent(event))
    {
        switch(event.type)
        {
            case sf::Event::Closed:
            epicMusic.stop();
            window.close();
            break;

            default:
            break;
        }

    }

    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
    {
            direction.x = -1;
            for(int i = 1; i < Snake.size(); i++)
            {
                Snake[i].snakeblock.setPosition(Snake[i+1].snakeblock.getPosition().x-20, Snake[i+1].snakeblock.getPosition().y);
            }
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
    {
            direction.x = 1;
            for(int j = 1; j < Snake.size(); j++)
            {
                Snake[j].snakeblock.setPosition(Snake[j+1].snakeblock.getPosition().x+20, Snake[j+1].snakeblock.getPosition().y);
            }
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
    {
            direction.y = -1;
            for(int l = 1; l < Snake.size(); l++)
            {
                Snake[l].snakeblock.setPosition(Snake[l+1].snakeblock.getPosition().x, Snake[l+1].snakeblock.getPosition().y-22);
            }
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
    {
            direction.y = 1;
            for(int o = 1; o < Snake.size(); o++)
            {
                Snake[o].snakeblock.setPosition(Snake[o+1].snakeblock.getPosition().x, Snake[o+1].snakeblock.getPosition().y+22);
            }
    }
    window.clear(sf::Color::Red);
    advanceStep();
    for(unsigned int m = 1; m < Snake.size(); m++)
    {
        window.draw(Snake[m].snakeblock);
    }
    window.display();
}
return 0;

}

void advanceStep()
{
sf::Vector2f headpos;
headpos.x = Snake[0].snakeblock.getPosition().x;
headpos.y = Snake[0].snakeblock.getPosition().y;

headpos.x += 22 * direction.x;
headpos.y += 22 * direction.y;

SnakeBlock element;
element.snakeblock.setPosition(headpos);

Snake.pop_back();
Snake.push_front(element);
}
user2687718
  • 31
  • 1
  • 6
  • 2
    Each snake block knows its position, right? A simple solution is, each update, check whether each non-head block is overlapping the head block. – Neil Kirk Aug 15 '13 at 23:49
  • Please read my post completely : "THE SNAKE IS PERFECTLY STRAIGHT, THEREFORE IT CANNOT BITE ITSELF !". – user2687718 Aug 15 '13 at 23:54
  • 7
    +1 for awesomest question title ever – pm100 Aug 16 '13 at 00:45
  • 2
    @pm100 My vote on that one actually goes to "Interfaces to allow unit's ability to attack ground, air, or both in Java using Design Patterns" (http://stackoverflow.com/questions/18200459/interfaces-to-allow-units-ability-to-attack-ground-air-or-both-in-java-using/18200571#18200571) – Jason C Aug 16 '13 at 01:33
  • 5
    @user2687718 You have everything you need to solve this problem, given to you by people using their free time to help you with homework that you should be able to do on your own. There's no need for an attitude (see comments on my answer below). – Jason C Aug 16 '13 at 01:39
  • Ok sorry I didn't read the question properly. Asking how to make the snake change direction in the title would be clearer. – Neil Kirk Aug 16 '13 at 01:55

4 Answers4

3

Your implementation has a lot of problems. Rather than pointing out each and every issue, here's a rough outline. Let's say your snake is a list of Segments, with a maximum length:

  • On each update step:
    1. Next position = head position + current direction.
    2. Add segment at head of queue, in next position.
    3. While the queue length is greater than maximum length, remove a segment at tail of queue.
  • On keyboard input, just change the current direction.
  • If you ever need to change the length of the snake, just change the maximum length -- the update step will then adjust the length of the snake.

A collision, semantically, is when the snakes head runs into any other part of its body.

To detect collisions, implement this on each update step. Check the head against the rest of the body segments. If there's an intersection, a collision occurred.

BTW if you want a smoother "shrinking" effect when the maximum snake length decreases, you could e.g. just remove two segments max per update (while queue length > max length and while segments removed < shrink rate).

Edit: Addressing your comment below wondering how to change direction based on an integer (or an enum, which I see you use now -- same concept); here's some more pseudocode:

Vec2 direction(0, 0);

if (currentDirection == Up)
    direction.y = -1;
else if (currentDirection == Down)
    direction.y = 1;
else if (currentDirection == Left)
    direction.x = -1;
else if (currentDirection == Right)
    direction.x = 1;

// direction is now a vector containing an x and y offset, which you can
// apply to the current position of the snake head to find the next
// position.
Jason C
  • 38,729
  • 14
  • 126
  • 182
  • Firstly, you didn't look the past comments or read my post completely, otherwise you would have understood that this is NOT a collision problem. Secondly, current direction is an INTEGER that can equals to 0, 1, 2 and 3 and, I really do not see how I could use that to make the movement look like it could potentially bite himself, or you need to develop MORE. – user2687718 Aug 16 '13 at 00:02
  • The algorithm I outlined above shows you *exactly* how to give the snake the ability to change directions. To move your snake in a given direction based on an integer value, you would use a `switch`, or an `if`, or choose a different representation for direction. Up to you. You may wish to check out a tutorial on control flow statements -- while your code indicates you understand how to use an `if`, your comment indicates your inability to understand how to modify the direction based on an integer constant, so I am confused. You have everything you need to solve this problem here. – Jason C Aug 16 '13 at 01:46
  • it's because you had not precised that I had to change the direction with a condition on the direction integer value. I hope you will be more precise in what you say in the future to other people, and not blame them for not understanding. But I still appreciate your help. – user2687718 Aug 16 '13 at 11:14
  • Did you actually write the code in your post? That code makes heavy use of `switch` and `if` blocks. I believe my assumption that you knew how to use them was reasonable. If you have copied this code from somewhere else, you are going to have a lot of trouble with this project. – Jason C Aug 16 '13 at 11:31
2

The basic principle is that you need to detect if the head reaches any of the blocks of itself - if so, it's "bitten itself".

So, when you have just moved the snake (including "growin" it, if applicable), check if the head matches the position of any of the other "blocks" that make up the snake.

Edit: To make the snake "wiggle", you need to use a "remember" which direction the head is moving in, and each move should "shuffle" the direction of that block to the one behind it.

In other words, add a dir entry to SnakeBlock, and use that to move each block.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • No you didn't understand... I want the snake to be possible to have a movement such it is POSSIBLE to bite itself. I do not talk about the collision here ! Right as it is now, its only a PERFECTLY straight snake, which cannot bite itself. You get me ? – user2687718 Aug 15 '13 at 23:54
  • Thanks for your answer that is now relevant but I do not get the term shuffle, could you explain with other words that part ? – user2687718 Aug 16 '13 at 00:04
2

That's what you get for overcomplicating things.

Because you use std::deque you don't need "next" field. or "move" method. Blocks also don't need separate textures (that implies all textures are unique, which is incorrect).

Rough outline of complete game (constructors are omitted):

struct Vector2{
   int x, y;
};

typedef std::deque<Vector2> Vec2Deque;

struct Snake{
    Vec2 direction; //(+-1, +-1)
    int blockSize;
    Vec2Deque blocks;//for blocks you only need their coordinates.

    void render(){
        for(size_T i = 0; i < blocks.size(); i++)
             renderSpriteAt(blocks[i]);
    }

    void advanceStep(){
         Vector2 headPos = blocks[0];//take current head pos             
         headPos.x += blockSize * direction.x; //calculate next position based on direction
         headPos.y += blockSize * direction.y; //and block size. Direction is 2component vector.
         blocks.pop_back();//remove last element
         blocks.push_front(headPos);//insert new element with new position as a head. 
              //That'll automatically create illusion of movement.
    }
};

That'll simulate classical grid-based snake.

If you want better snake (that moves smoothly, and can turn at small angles (like 1 degree to the left), things will become more complicated.

Think simple. Also see KISS principle.


NEW CODE TAKING IN ACCOUNT EVERYTHING YOU ALL SAID, but now the snake just disappear, probably because of the pop_back

Replace this:

if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
    {
            direction.x = -1;
            for(int i = 1; i < Snake.size(); i++)
            {
                Snake[i].snakeblock.setPosition(Snake[i+1].snakeblock.getPosition().x-20, Snake[i+1].snakeblock.getPosition().y);
            }
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
    {
            direction.x = 1;
            for(int j = 1; j < Snake.size(); j++)
            {
                Snake[j].snakeblock.setPosition(Snake[j+1].snakeblock.getPosition().x+20, Snake[j+1].snakeblock.getPosition().y);
            }
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
    {
            direction.y = -1;
            for(int l = 1; l < Snake.size(); l++)
            {
                Snake[l].snakeblock.setPosition(Snake[l+1].snakeblock.getPosition().x, Snake[l+1].snakeblock.getPosition().y-22);
            }
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
    {
            direction.y = 1;
            for(int o = 1; o < Snake.size(); o++)
            {
                Snake[o].snakeblock.setPosition(Snake[o+1].snakeblock.getPosition().x, Snake[o+1].snakeblock.getPosition().y+22);
            }
    }

with this:

if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
    {
            direction.x = -1;
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
    {
            direction.x = 1;
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
    {
            direction.y = -1;
            for(int l = 1; l < Snake.size(); l++)
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
    {
            direction.y = 1;
    }

You shouldn't update snake anywhere outside of advanceStep. You should use either push/pop or that loop that shifts elements, not both of them. You don know, that you can use "i" in all your loops, and don't need to pick different variable name every time, right?

If you're still having problem with the snake, try writing a scroll shooter instead. For example:

  1. Arcanoid.
  2. Scroll shooter.

Unless you want to add particle systems to those games, they should be easier than the snake, because in those games one object has only one sprite.

SigTerm
  • 26,089
  • 6
  • 66
  • 115
  • Thanks now I get what you mean, so I should make 4 vectors called Up/Down/Left/right and use them in my setPos ! – user2687718 Aug 16 '13 at 00:11
  • @user2687718: No, I think you simply forgot to shift snake blocks. Remove last, and add new block as a head, at every step. If you keep trying to move only first and last block (which is what you did), nothing's gonna happen.There's not a single "pop"(pop_front/pop_back) in your code, you know... – SigTerm Aug 16 '13 at 00:14
  • its because i'm trying to test it for a snake made of 2/3 segment, later I'll do pop/more push_front – user2687718 Aug 16 '13 at 00:16
  • Also I can't really do what you just wrote because in SFML, everything is in a big loop window.isOpen(), so I can't really see how I can use your idea.. – user2687718 Aug 16 '13 at 00:20
  • @user2687718: I don't see the problem and it doesn't make any difference. Perhaps you should try something simpler first? or switch to gamemaker? or read more tutorials? First learn how to deal with traditional snake, that had non-fractional number of segments, then you can start complicating things. – SigTerm Aug 16 '13 at 00:23
  • You can't just ask somebody to switch to gamemaker after I read two books on C and C++. I'm just new to game programming and I'm determined to finish this snake. I just do not get concepts easily, thats 'all. Also I don't see what you meant by non fractional number of segments, unless you mean a perfectly straight snake, which is what I get for the moment. You do not explain how to set up the direction vector, do I have to change its coordinates after each key press ? Also is the advancestep method only made for the head ? Thanks a lot. – user2687718 Aug 16 '13 at 00:32
  • (BTW for the texture you can see I always re use the texture of the first head). – user2687718 Aug 16 '13 at 00:33
  • I will update my post so you can see what I'm doing, and even if I don't clearly understand what you are saying I appreciate your help. – user2687718 Aug 16 '13 at 00:41
  • figured a little more what you meant: replaced last function by void advanceStep() { sf::Vector2f headpos(Snake[0].snakeblock.getPosition()); headpos.x += 22 * direction.x; headpos.y += 22 * direction.y; SnakeBlock element; element.snakeblock.setPosition(headpos); Snake.push_front(element); } – user2687718 Aug 16 '13 at 00:51
  • (if you help me I give you the link of the epicMusic used in my snake, fair enough ?) – user2687718 Aug 16 '13 at 00:57
  • Just check me if I'm correct : you want me to use the deque of Vector as the deque of SnakeBlock I got, or you want me to make two deque (one made of SnakeBlock, one made of Vector) where the deque of Snake will use the coordinates of the one made of Vector to set the position of each block ? Its not clear :( – user2687718 Aug 16 '13 at 01:13
  • @user2687718 A good approach for these kinds of things is to sit down and work out what you need to happen on each update step to get the behavior that you want. I like to work these kinds of things out on paper. Don't think in terms of what SigTerm "wants" you to do. Think in terms of what *you* want the *program* to do, and how you can express that logic in C++ (or whatever language you are using). Start with a goal for your behaviors, then work out a high level algorithm to make that happen, then the implementation details will become clearer. – Jason C Aug 16 '13 at 01:37
  • Your comment on my answer regarding your confusion about using an integer for a direction suggests that you should perhaps start with a simpler game. That's not a bad thing at all, but you need to get a solid grasp of the basics before moving on. – Jason C Aug 16 '13 at 01:39
  • @user2687718: I don't "want" you to do anything. I just presented you approach that will work on any graphical system (sdl, sfml, whatever). Every step you append snake's new "head" (with new coordinates) to the **front** of the queue/deque, and you kill the tail element at the end of queue/deque. That creates illusion of movement. And that is the part your code is missing. It doesn't matter how you store direction of movement (enum, int, vector, whatever), approach is missing. – SigTerm Aug 16 '13 at 05:37
  • @user2687718: No offense, but at the moment your code is kinda messy and gives a strong impression that you're trying too many new things at once. You're storing snake blocks in deque, BUT you don't use deque's "pop" mechanism (which is the main part of the snake), plus it has "next" element within it (which suggests that it actually wants to be a linked list) plus you store sfml sprite for every block, and because deque can use copy constructor that might not actually play nice with sfml data types. Given the impression of your code, I'd advise to slow down a bit. (continued) – SigTerm Aug 16 '13 at 05:41
  • @user2687718: (continued) IMO you either want to start making games or you want to learn C++. If you want to **make games**, then you don't have to learn programming. Grab gamemaker and use it instead. However, **if you want to learn C++ programming**, then at the moment you need to grab some kind of good beginner's book, and slowly walk through exercises. Because I started learning programming-related stuff roughly 18 years ago, I can't recommend anything myself. However, you might want to check [this list](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) out. – SigTerm Aug 16 '13 at 05:46
  • I read Thinking in C++ and did almost all exercices of it, and same for a C book. The problem is not programming here, but GAME programming ! Check my updated code, I take in account what you all said. Thanks in advance. – user2687718 Aug 16 '13 at 11:16
  • @user2687718: Try writing arcanoid instead. Arcanoid should be simpler than snake because one object have only one sprite to display. – SigTerm Aug 16 '13 at 13:08
  • yeah true ! but I wish to finish this one first (at least have a snake that can be fractioned and wiggle) went so far, check my last thread – user2687718 Aug 16 '13 at 15:27
  • @user2687718: I think it **might** be better for you to write simpler game at the moment, instead of struggling with this one. Once you get hang of basic things (game loop, input, etc), try it again. Still, it is your decision. If you keep trying to fix the snake, you'll probably overcome problems eventually. Your choice. However fractional snake is more complicated, and if it also should be able to turn at small angles (+- 1 degree, instead of +- 90 degrees, for example), things will get complicated and you'll need more complicated math (catmull-rom splines, probably). – SigTerm Aug 16 '13 at 16:28
  • yeah I don't want that yet, heres the new code, I completely rebuilt it and didnt use sprites as you said because they can drive me crazy to set up textures : http://pastebin.com/E4Cm2x5x – user2687718 Aug 16 '13 at 20:36
  • what do you think ? only problem is that it disappear but I do not understand how – user2687718 Aug 16 '13 at 20:36
  • @user2687718: Look, no offense, but I'm not a free tutor or something. I think your code is unnecessarily complicated. `Move` method should be 5 times shorter. Compare to my snippet and think about it. Your snake disappears probably because `_direction` (identifier names shouldn't start with underscores, by the way- those are reserved), is an uninitialized int. You didn't assign any value to it within Snake's constructor, and by default it'll be `0xcccccccc` which your `Move` can't handle. – SigTerm Aug 16 '13 at 21:10
  • @user2687718: Learn how to use debugger, investigate values of variables, and walk through your code when something's wrong. You do know how to do that, right? – SigTerm Aug 16 '13 at 21:11
  • not really :/ what do you mean by investigate value of variables? and yes I know you are not free tutor, you helped me a lot already and you are not forced to help (even if i'd like :) ). Thanks. by the way _direction is directly initialized if you press a key so... and I get a wiggling snake if I remove the shrink() in my move method of snake, and I will not make a perfectly clean and simple game as my first one :( – user2687718 Aug 16 '13 at 22:12
  • its because I tried with your snippet and it didn't work because I had to use setposition :( this approach looks completely fine to me and is way less complicated than the first one I had already – user2687718 Aug 16 '13 at 22:56
  • also I changed what you said and replaced the underscore and it still disappear :( but before I had a snake that could wiggle but I changed the code sadly – user2687718 Aug 16 '13 at 22:57
  • http://pastebin.com/SDJKE4FD if you put the move in each if, IT MAKE THE SNAKE WIGGLE !!!!!! – user2687718 Aug 16 '13 at 23:02
  • I think my problem has nothing to do with the variables but more because I'm new to the loop programming system (aka everything in is a loop in a game), I just need to find how I could possibly move in the same direction while you do not press any key... – user2687718 Aug 16 '13 at 23:18
  • @user2687718: good. Now accept one of the answers. If you're new to "loop programming", you should try qt tutorials. Event loop is a fairly common thing on modern platoforms. – SigTerm Aug 17 '13 at 16:03
1

As I understand it, Currently your snake remain as a straight line and you want it to be able to turn like in other games.

What I did in my game, I have two data structure, One for snake parts (position and direction) and other for turns ( direction and position).

In game loop, Snake part is moving in its direction but if its position matches to direction of turn then snake part changes its direction to turn's direction and update its position accordingly.

Turn is removed when you apply it to tail part of snake. and added when you detect key press, capture its direction and position is snake's head position.

My implementation is here, you can check it out what I am saying.

Kunal
  • 3,475
  • 21
  • 14
  • Thanks tried to do with your implementation check out this pastebin http://pastebin.com/SDJKE4FD I do not see the problem – user2687718 Aug 16 '13 at 22:59
  • you need two queue, one for snake and other for all turns. In your code I see only one queue for snake and one global direction ( that will cause your snake to move in straight line). When you press key you need to store direction and pos in that another queue and before moving snake compare each snake part pos to that turn's pos and change snake part's direction accordingly. – Kunal Aug 17 '13 at 03:02