SFML community forums

Help => General => Topic started by: paupav on July 08, 2014, 12:02:33 pm

Title: automatically create new bodypart in snake game
Post by: paupav on July 08, 2014, 12:02:33 pm
So, I'm developing simple snakegame in SFML, and I've just wanted to ask you if there is way to automate creating bodyparts and drawing them. Curently I have code that looks like this:

// defining bodyparts
    sf::RectangleShape square (sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart1(sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart2(sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart3(sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart4(sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart5(sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart6(sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart7(sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart8(sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart9(sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart10(sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart11(sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart12(sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart13(sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart14(sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart15(sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart16(sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart17(sf::Vector2f(res.x/grid, res.x/grid));
    sf::RectangleShape bodyPart18(sf::Vector2f(res.x/grid, res.x/grid));
//etc

//pos of bodyyparts

    sf::Vector2i part1Pos(snakePos.x + grid, snakePos.y);
    sf::Vector2i part2Pos(part1Pos.x + grid, part1Pos.y);
    sf::Vector2i part3Pos(part2Pos.x + grid, part2Pos.y);
    sf::Vector2i part4Pos(part3Pos.x + grid, part3Pos.y);
    sf::Vector2i part5Pos(part4Pos.x + grid, part4Pos.y);
    sf::Vector2i part6Pos(part5Pos.x + grid, part5Pos.y);
//etc

//set position of body
    square.setPosition(snakePos.x, snakePos.y);
    bodyPart1.setPosition(part1Pos.x, part1Pos.y);
    bodyPart2.setPosition(part2Pos.x, part2Pos.y);
    bodyPart3.setPosition(part3Pos.x, part3Pos.y);
    bodyPart4.setPosition(part4Pos.x, part4Pos.y);
    bodyPart5.setPosition(part5Pos.x, part5Pos.y);
    bodyPart6.setPosition(part6Pos.x, part6Pos.y);
       
    bodyPart7.setPosition(part1Pos.x, part1Pos.y);
    bodyPart8.setPosition(part2Pos.x, part2Pos.y);
    bodyPart9.setPosition(part3Pos.x, part3Pos.y);
    bodyPart10.setPosition(part4Pos.x, part4Pos.y);
    bodyPart11.setPosition(part5Pos.x, part5Pos.y);
    bodyPart12.setPosition(part6Pos.x, part6Pos.y);
//etc
And then to draw it:
if(snakeSize >= 1)
    window.draw(bodyPart1);
    if(snakeSize >= 2)
    window.draw(bodyPart2);
    if(snakeSize >= 3)
    window.draw(bodyPart3);
    if(snakeSize >= 4)
    window.draw(bodyPart4);
    if(snakeSize >= 5)
    window.draw(bodyPart5);
    if(snakeSize >= 6)
    window.draw(bodyPart6);
//etc

It basically works, but it doesn't look nice.

(http://s27.postimg.org/axuewb2dd/snake_1.png)
(http://s27.postimg.org/ydcc1nm4h/snake_2.png)
Title: Re: automatically create new bodypart in snake game
Post by: eXpl0it3r on July 08, 2014, 12:11:53 pm
Just use an std::vector. If you don't know how to use C++ containers, you might want to learn basic C++ first, at best with a good C++ book (https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list).

Also you need to link the actual images, if you want them to appear on the forum:

(http://s27.postimg.org/ptsy3wds1/snake_1.png)

(http://s27.postimg.org/n0zqjvdfl/snake_2.png)
Title: Re: automatically create new bodypart in snake game
Post by: paupav on July 08, 2014, 01:56:52 pm
But how would I implement it into my code :( . I'm kinda bad at programing. I havent programmed for half of year.
Title: Re: automatically create new bodypart in snake game
Post by: Strelok on July 08, 2014, 02:19:57 pm
You lack basic programming notions, you might want to follow exploiter's suggestion and read a good c++ book.
Title: Re: automatically create new bodypart in snake game
Post by: paupav on July 08, 2014, 03:22:12 pm
ya, I've skipped few lessons, and forgot the ones that I'velearned.
Title: Re: automatically create new bodypart in snake game
Post by: Hapax on July 08, 2014, 04:09:48 pm
There are lots of examples and tutorials (http://bit.ly/1mbUWor) on the internet about using std::vector if you are unable to have access to a book.

Remember that internet tutorials often teach what is often considered as bad programming practices so you should spend also some time researching why.
Title: Re: automatically create new bodypart in snake game
Post by: Jesper Juhl on July 09, 2014, 01:55:40 am
The thing to remember about snakes is that only the head and tail actually move. All the body parts in between stay in position.

So, an easy way to implement a snake is to use a std::deque<sf::Vector2i> to store the positions (x, y) of the snakes body parts.
If you do that, then moving the snake is as simple as removing the old tail at the end and then adding a new head at the front - something like this:
...
std::deque<sf::Vector2i> segments;
...
void Snake::move()
{
// first remove old tail
segments.pop_back();
// figure out where new head needs to go ...
sf::vector2i new_head(x, y); // x, y being where ever you want the new head to be
// then add the new head
segments.emplace_front(new_head);
}
 

To grow the snake by one segment you can then simply skip removing the tail when you move it. So something like:

void Snake::move()
{
if (!growing) {
  // remove old tail
  segments.pop_back();
}
growing = false; // don't grow again next move (unless something sets growing again before next move)

// figure out where new head needs to go ...
sf::vector2i new_head(x, y); // x, y being where ever you want the new head to be
// then add the new head
segments.emplace_front(new_head);
}
 

and to draw it you can then simply do something like:

...
for (auto& segment : segments) {
  sf::Sprite sprite(...);
  sprite.setPosition(segment.x, segment.y);
  draw(sprite);
}
...
 

I hope that makes sense :)
Title: Re: automatically create new bodypart in snake game
Post by: Hapax on July 09, 2014, 02:31:32 am
use a std::deque
The perfect solution!
Title: Re: automatically create new bodypart in snake game
Post by: paupav on July 09, 2014, 03:48:41 pm
The thing to remember about snakes is that only the head and tail actually move. All the body parts in between stay in position.

So, an easy way to implement a snake is to use a std::deque<sf::Vector2i> to store the positions (x, y) of the snakes body parts.
If you do that, then moving the snake is as simple as removing the old tail at the end and then adding a new head at the front - something like this:
...
std::deque<sf::Vector2i> segments;
...
void Snake::move()
{
// first remove old tail
segments.pop_back();
// figure out where new head needs to go ...
sf::vector2i new_head(x, y); // x, y being where ever you want the new head to be
// then add the new head
segments.emplace_front(new_head);
}
 

To grow the snake by one segment you can then simply skip removing the tail when you move it. So something like:

void Snake::move()
{
if (!growing) {
  // remove old tail
  segments.pop_back();
}
growing = false; // don't grow again next move (unless something sets growing again before next move)

// figure out where new head needs to go ...
sf::vector2i new_head(x, y); // x, y being where ever you want the new head to be
// then add the new head
segments.emplace_front(new_head);
}
 

and to draw it you can then simply do something like:

...
for (auto& segment : segments) {
  sf::Sprite sprite(...);
  sprite.setPosition(segment.x, segment.y);
  draw(sprite);
}
...
 

I hope that makes sense :)
I've mase it completely different. Basically snakes tail is mase of a squares (bodyParts) that move as head of the snake moves. When head moves bodyPart1 takes position of a snakes head, then bodyPart2 takes position of the bodyPart1 and so on.
I'm happy with my whole code except that part. Whole game scales as I change resolution.