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

Author Topic: automatically create new bodypart in snake game  (Read 4797 times)

0 Members and 1 Guest are viewing this topic.

paupav

  • Full Member
  • ***
  • Posts: 156
    • View Profile
    • Email
automatically create new bodypart in snake game
« 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.



eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10825
    • View Profile
    • development blog
    • Email
Re: automatically create new bodypart in snake game
« Reply #1 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.

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



Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

paupav

  • Full Member
  • ***
  • Posts: 156
    • View Profile
    • Email
Re: automatically create new bodypart in snake game
« Reply #2 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.

Strelok

  • Full Member
  • ***
  • Posts: 139
    • View Profile
    • GitHub
Re: automatically create new bodypart in snake game
« Reply #3 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.

paupav

  • Full Member
  • ***
  • Posts: 156
    • View Profile
    • Email
Re: automatically create new bodypart in snake game
« Reply #4 on: July 08, 2014, 03:22:12 pm »
ya, I've skipped few lessons, and forgot the ones that I'velearned.

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: automatically create new bodypart in snake game
« Reply #5 on: July 08, 2014, 04:09:48 pm »
There are lots of examples and tutorials 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.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: automatically create new bodypart in snake game
« Reply #6 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 :)
« Last Edit: July 09, 2014, 01:58:44 am by Jesper Juhl »

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: automatically create new bodypart in snake game
« Reply #7 on: July 09, 2014, 02:31:32 am »
use a std::deque
The perfect solution!
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

paupav

  • Full Member
  • ***
  • Posts: 156
    • View Profile
    • Email
Re: automatically create new bodypart in snake game
« Reply #8 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.

 

anything