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

Author Topic: Where is the value for the Snake size? Snake Game  (Read 2993 times)

0 Members and 1 Guest are viewing this topic.

Programmy

  • Newbie
  • *
  • Posts: 19
    • View Profile
Where is the value for the Snake size? Snake Game
« on: August 02, 2018, 12:37:15 pm »
I'm studying the book SFML Game Development by example and I'm having trouble understanding where the snake class is getting the size value for the Snake, I suspect that it's in the world.cpp and is initialized by m_blockSize=16, not really sure, I take a look at the snake class at the snake.h and there's no value at int m_size, so
what's going on? is it being initialized by the constructor member initialization list at Game.cpp? could anyone explain how the snake is gettting it's size? where is the snake getting the value?

Game.h

#pragma once
#include "Window.h"
#include "World.h"
#include "Snake.h"


class Game {
public:
        Game();
        ~Game();

        void HandleInput();
        void Update();
        void Render();

        sf::Time GetElapsed();
        void RestartClock();

        Window* GetWindow();
private:
        Window m_window;
        sf::Clock m_clock;
        float m_elapsed;

        World m_world;
        Snake m_snake;
       
       
};
 


Game.cpp

#include "Game.h"

Game::Game() :  m_window("Snake", sf::Vector2u(800, 600)), m_snake(m_world.GetBlockSize()), m_world(sf::Vector2u(800, 600))
{
        m_clock.restart();

       
       
        m_elapsed = 0.0f;

       
}

Game::~Game() {}

sf::Time Game::GetElapsed() { return m_clock.getElapsedTime(); }


void Game::RestartClock() { m_elapsed += m_clock.restart().asSeconds(); }


Window* Game::GetWindow(){      return &m_window; }

void Game::HandleInput() {
        // Input handling.
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) && m_snake.GetPhysicalDirection() != Direction::Down)
       
        {m_snake.SetDirection(Direction::Up);}


        else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)
        && m_snake.GetPhysicalDirection() != Direction::Up) {
                m_snake.SetDirection(Direction::Down);
        }
        else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)
                && m_snake.GetPhysicalDirection() != Direction::Right) {
                m_snake.SetDirection(Direction::Left);
        }
        else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)
                && m_snake.GetPhysicalDirection() != Direction::Left) {
                m_snake.SetDirection(Direction::Right);
        }
}

void Game::Update() {
        m_window.Update();
        float timestep = 1.0f / m_snake.GetSpeed();
        if (m_elapsed >= timestep) {
                m_snake.Tick();
                m_world.Update(m_snake);
                m_elapsed -= timestep;
                if (m_snake.HasLost()) {
                       
                        m_snake.Reset();
                }
        }
}

void Game::Render() {
        m_window.BeginDraw();
        // Render here.
        m_world.Render(*m_window.GetRenderWindow());
        m_snake.Render(*m_window.GetRenderWindow());
       

        m_window.EndDraw();
}

 


World.h

#pragma once
#include <SFML/Graphics.hpp>
#include "Snake.h"

class World {
public:
        World(sf::Vector2u l_windSize);
        ~World();

        int GetBlockSize();

        void RespawnApple();

        void Update(Snake& l_player);
        void Render(sf::RenderWindow& l_window);
private:
        sf::Vector2u m_windowSize;
        sf::Vector2i m_item;
        int m_blockSize;

        sf::CircleShape m_appleShape;
        sf::RectangleShape m_bounds[4];
};

 

World.cpp

#include "World.h"

World::World(sf::Vector2u l_windSize) {
        m_blockSize = 16;

        m_windowSize = l_windSize;
        RespawnApple();
        m_appleShape.setFillColor(sf::Color::Red);
        m_appleShape.setRadius(m_blockSize / 2);

        for (int i = 0; i < 4; ++i) {
                m_bounds[i].setFillColor(sf::Color(150, 0, 0));
                if (!((i + 1) % 2)) {
                        m_bounds[i].setSize(sf::Vector2f(m_windowSize.x, m_blockSize));
                }
                else {
                        m_bounds[i].setSize(sf::Vector2f(m_blockSize, m_windowSize.y));
                }
                if (i < 2) {
                        m_bounds[i].setPosition(0, 0);
                }
                else {
                        m_bounds[i].setOrigin(m_bounds[i].getSize());
                        m_bounds[i].setPosition(sf::Vector2f(m_windowSize));
                }
        }
}

World::~World() {}

int World::GetBlockSize() { return m_blockSize; }

void World::RespawnApple() {
        int maxX = (m_windowSize.x / m_blockSize) - 2;
        int maxY = (m_windowSize.y / m_blockSize) - 2;
        m_item = sf::Vector2i(
                rand() % maxX + 1, rand() % maxY + 1);
        m_appleShape.setPosition(
                m_item.x * m_blockSize,
                m_item.y * m_blockSize);
}

void World::Update(Snake& l_player) {
        if (l_player.GetPosition() == m_item) {
                l_player.Extend();
                l_player.IncreaseScore();
                RespawnApple();
        }

        int gridSize_x = m_windowSize.x / m_blockSize;
        int gridSize_y = m_windowSize.y / m_blockSize;

        if (l_player.GetPosition().x <= 0 ||
                l_player.GetPosition().y <= 0 ||
                l_player.GetPosition().x >= gridSize_x - 1 ||
                l_player.GetPosition().y >= gridSize_y - 1)
        {
                l_player.Lose();
        }
}

void World::Render(sf::RenderWindow& l_window) {
        for (int i = 0; i < 4; ++i) {
                l_window.draw(m_bounds[i]);
        }
        l_window.draw(m_appleShape);
}
 

Snake.h

#pragma once
#include <SFML/Graphics.hpp>

#include <vector>

struct SnakeSegment
{
        SnakeSegment(int x, int y) : position(x, y)

        {

        }
        sf::Vector2i position;
};

using SnakeContainer = std::vector<SnakeSegment>;

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

class Snake {
public:
        Snake(int l_blockSize);
        ~Snake();

        // Helper methods.
        void SetDirection(Direction l_dir);
        Direction GetDirection();
        int GetSpeed();
        sf::Vector2i GetPosition();
        int GetLives();
        int GetScore();
        void IncreaseScore();
        bool HasLost();

        void Lose(); // Handle losing here.
        void ToggleLost();

        Direction GetPhysicalDirection();

        void Extend(); // Grow the snake.
        void Reset(); // Reset to starting position.

        void Move(); // Movement method.
        void Tick(); // Update method.
        void Cut(int l_segments); // Method for cutting snake.
        void Render(sf::RenderWindow& l_window);
private:
        void CheckCollision(); // Checking collisions.

        SnakeContainer m_snakeBody; // Segment vector.
        int m_size; // Size of the graphics.
        Direction m_dir; // Current direction.
        int m_speed; // Speed of the snake.
        int m_lives; // Lives.
        int m_score; // Score.
        bool m_lost; // Losing state.
        sf::RectangleShape m_bodyRect; // Shape used in rendering.
       
};
 

Snake.cpp

#include "Snake.h"

Snake::Snake(int l_blockSize) {

        m_size = l_blockSize;   m_bodyRect.setSize(sf::Vector2f(m_size -1 , m_size -1 ));
        Reset();
}

Snake::~Snake() {}

void Snake::SetDirection(Direction l_dir) { m_dir = l_dir; }
Direction Snake::GetDirection() { return m_dir; }
int Snake::GetSpeed() { return m_speed; }
sf::Vector2i Snake::GetPosition() {
        return (!m_snakeBody.empty() ? m_snakeBody.front().position : sf::Vector2i(1, 1));
}

int Snake::GetLives() { return m_lives; }
int Snake::GetScore() { return m_score; }

void Snake::IncreaseScore() {m_score += 10;}
bool Snake::HasLost() { return m_lost; }
void Snake::Lose() { m_lost = true; }
void Snake::ToggleLost() { m_lost = !m_lost; }

Direction Snake::GetPhysicalDirection() {
        if (m_snakeBody.size() <= 1) {
                return Direction::None;
        }

        SnakeSegment& head = m_snakeBody[0];
        SnakeSegment& neck = m_snakeBody[1];

        if (head.position.x == neck.position.x) {
                return (head.position.y > neck.position.y
                        ? Direction::Down : Direction::Up);
        }
        else if (head.position.y == neck.position.y) {
                return (head.position.x > neck.position.x
                        ? Direction::Right : Direction::Left);
        }

        return Direction::None;
}

void Snake::Extend() {
        if (m_snakeBody.empty()) { return; }
        SnakeSegment& tail_head =
                m_snakeBody[m_snakeBody.size() - 1];

        if (m_snakeBody.size() > 1)
        {
                SnakeSegment& tail_bone =
                        m_snakeBody[m_snakeBody.size() - 2];

                if (tail_head.position.x == tail_bone.position.x)
                {
                        if (tail_head.position.y > tail_bone.position.y)
                        {
                                m_snakeBody.push_back(SnakeSegment(
                                        tail_head.position.x, tail_head.position.y + 1));
                        }
                        else
                        {
                                m_snakeBody.push_back(SnakeSegment(
                                        tail_head.position.x, tail_head.position.y - 1));
                        }
                }
                else if (tail_head.position.y == tail_bone.position.y)
                {
                        if (tail_head.position.x > tail_bone.position.x)
                        {
                                m_snakeBody.push_back(SnakeSegment(
                                        tail_head.position.x + 1, tail_head.position.y));
                        }
                        else
                        {
                                m_snakeBody.push_back(SnakeSegment(
                                        tail_head.position.x - 1, tail_head.position.y));
                        }
                }
        }
        else
        {
                if (m_dir == Direction::Up)
                {
                        m_snakeBody.push_back(SnakeSegment(
                                tail_head.position.x, tail_head.position.y + 1));
                }
                else if (m_dir == Direction::Down) {
                        m_snakeBody.push_back(SnakeSegment(
                                tail_head.position.x, tail_head.position.y - 1));
                }
                else if (m_dir == Direction::Left) {
                        m_snakeBody.push_back(SnakeSegment(
                                tail_head.position.x + 1, tail_head.position.y));
                }
                else if (m_dir == Direction::Right) {
                        m_snakeBody.push_back(SnakeSegment(
                                tail_head.position.x - 1, tail_head.position.y));
                }
        }
}

void Snake::Reset() {
        m_snakeBody.clear();
        m_snakeBody.push_back(SnakeSegment(5, 7));
        m_snakeBody.push_back(SnakeSegment(5, 6));
        m_snakeBody.push_back(SnakeSegment(5, 5));

        SetDirection(Direction::None); // Start off still.
        m_speed = 15;
        m_lives = 3;
        m_score = 0;
        m_lost = false;
}

void Snake::CheckCollision() {
        if (m_snakeBody.size() < 5) { return; }
        SnakeSegment& head = m_snakeBody.front();
        for (auto itr = m_snakeBody.begin() + 1;
                itr != m_snakeBody.end(); ++itr)
        {
                if (itr->position == head.position) {
                        int segments = m_snakeBody.end() - itr;
                        Cut(segments);
                        break;
                }
        }
}

void Snake::Move()
{
    for (int i = m_snakeBody.size() - 1; i > 0; --i) {m_snakeBody[i].position = m_snakeBody[i - 1].position;}
       
        if (m_dir == Direction::Left) {--m_snakeBody[0].position.x;}
       
        else if (m_dir == Direction::Right) {++m_snakeBody[0].position.x;}
       
        else if (m_dir == Direction::Up) {--m_snakeBody[0].position.y;}
       
        else if (m_dir == Direction::Down) {++m_snakeBody[0].position.y;}  
}

void Snake::Tick() {
        if (m_snakeBody.empty()) { return; }
        if (m_dir == Direction::None) { return; }
        Move();
        CheckCollision();
}

void Snake::Cut(int l_segments) {
        for (int i = 0; i < l_segments; ++i) {
                m_snakeBody.pop_back();
        }
        --m_lives;
        if (!m_lives) { Lose(); return; }


}

void Snake::Render(sf::RenderWindow& l_window) {
        if (m_snakeBody.empty()) { return; }

        auto head = m_snakeBody.begin();
        m_bodyRect.setFillColor(sf::Color::Yellow);
        m_bodyRect.setPosition(head->position.x * m_size,
                head->position.y * m_size);
        l_window.draw(m_bodyRect);

        m_bodyRect.setFillColor(sf::Color::Green);
        for (auto itr = m_snakeBody.begin() + 1;
                itr != m_snakeBody.end(); ++itr) {
                m_bodyRect.setPosition(itr->position.x * m_size,
                        itr->position.y * m_size);
                l_window.draw(m_bodyRect);
        }
}
 
« Last Edit: August 03, 2018, 10:09:09 am by Programmy »

verdog

  • Newbie
  • *
  • Posts: 25
    • View Profile
    • Email
Re: Where is the value for the Snake size? Snake Game
« Reply #1 on: August 02, 2018, 03:15:09 pm »
Is it here?
SnakeContainer m_snakeBody; // Segment vector.

I think the size of the snake can be obtained like this:
m_snakeBody.size()

Programmy

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Where is the value for the Snake size? Snake Game
« Reply #2 on: August 03, 2018, 10:10:14 am »
but theres no value indicated at m_snakebody....

verdog

  • Newbie
  • *
  • Posts: 25
    • View Profile
    • Email
Re: Where is the value for the Snake size? Snake Game
« Reply #3 on: August 03, 2018, 03:06:21 pm »
I'm not sure what you mean. Are you saying that it doesn't ever get filled?

void Snake::Reset() {
        m_snakeBody.clear();
        m_snakeBody.push_back(SnakeSegment(5, 7));
        m_snakeBody.push_back(SnakeSegment(5, 6));
        m_snakeBody.push_back(SnakeSegment(5, 5));

        SetDirection(Direction::None); // Start off still.
        m_speed = 15;
        m_lives = 3;
        m_score = 0;
        m_lost = false;
}
 

Upon reset, 3 SnakeSegments are inserted into m_snakeBody.

Programmy

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Where is the value for the Snake size? Snake Game
« Reply #4 on: August 04, 2018, 05:34:28 am »
tried fiddling with the numbers on that vector but it only adjusts the position, not the size, 5 of the x and 7 of the y, as an additional note, I tried adjusting m_blocksize from world cpp and all the graphics in the game got larger like the wall, apple and snake, but how is  m_blockSize affecting the Snakeclass? it shows m_Size without a value in Snake class.
« Last Edit: August 04, 2018, 05:41:49 am by Programmy »

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Where is the value for the Snake size? Snake Game
« Reply #5 on: August 04, 2018, 10:25:23 pm »
I don't know the code but it looks like a snake segment represents the location of that segment so yes, the two values are x and y.

As verdog mentioned above, the segments are stored in m_snakeBody and you get its size in the same way as with any other normal vector and the segments are added using push_back, again the same as any other vector. The initial ones are added (pushed) in reset() but further ones are added elsewhere; try searching the code for "push_back".
Also, try searching "m_snakeBody.size" and see where and how it's used.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*