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

Author Topic: Snake program not working.  (Read 9142 times)

0 Members and 1 Guest are viewing this topic.

wizh

  • Newbie
  • *
  • Posts: 19
    • View Profile
Snake program not working.
« on: June 09, 2013, 12:56:12 pm »
I was going to make a snake game, and wanted to do a quick "prototype" with just 3 pieces in the tail. However, this isn't working, and I just can't seem to figure out what it is that I'm doing wrong.

while(mainWindow.isOpen())
        {
                handleEvents();
                moveSnake();

                checkForCollisionWithWall();
                               
                mainWindow.clear();

                if(!first) {
               
                        tail.setPosition(snakeSprite.getPosition().x + 3, snakeSprite.getPosition().y - 20);
                        mainWindow.draw(tail);

                        lastPosition1 = tail.getPosition();
                               
                        tail.setPosition(snakeSprite.getPosition().x + 3, snakeSprite.getPosition().y - 40);
                        mainWindow.draw(tail);

                        lastPosition2 = tail.getPosition();
       
                        tail.setPosition(snakeSprite.getPosition().x + 3, snakeSprite.getPosition().y - 60);
                        mainWindow.draw(tail);

                        first = true;
               
                } else {

                        tail.setPosition(lastPosition0);
                        mainWindow.draw(tail);
                        lastPosition1 = tail.getPosition();
                       
                        tail.setPosition(lastPosition1);
                        mainWindow.draw(tail);
                        lastPosition2 = tail.getPosition();

                        tail.setPosition(lastPosition2);
                        mainWindow.draw(tail);
                }
               
                mainWindow.draw(snakeSprite);
                mainWindow.display();
         }
}
 

By using std::cout I figured that my positions were getting set correctly, the sprites are just not showing up.

Thanks in advance :)
« Last Edit: June 09, 2013, 01:12:55 pm by wizh »

The Hatchet

  • Full Member
  • ***
  • Posts: 135
    • View Profile
    • Email
Re: Snake program not working.
« Reply #1 on: June 09, 2013, 01:19:07 pm »
1.  Define what your actual problem is.  Saying "This isn't working" and posting a small part of your code without saying WHAT isn't working isn't helpful.

2.  Please post a minimum and complete executable piece of code if possible.

I'm assuming snakeSprite is a sprite for the 'Head' and tail is a sprite for the 'tail'.  What is 'first'? and what is its purpose?  Where does 'first' get set false?  Your 'Else' chunk seems to be setting tail to all the same spot 3 times and drawing on that same spot 3 times, why?

wizh

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Snake program not working.
« Reply #2 on: June 09, 2013, 01:43:24 pm »
Hmm, sorry - I thought I had provided enough information.

The problem is that the tail isn't drawn to the screen at all. My logic was that the invidual pieces for the tail would have to replace the previous one.

The 'first' bool just makes it so that the initial 3 parts only get's drawn once. It get's set as false when the program executes: i.e. before anything happens.

The lastPosition0 (the head's position) get's set when the snake moves:

void Game::moveSnake() {
        elapsed = gameClock.getElapsedTime();
        if (elapsed.asSeconds() >= 0.15) {
                switch(Direction)
                {
                case Up:
                        snakeSprite.setPosition(snakeSprite.getPosition().x, snakeSprite.getPosition().y - 20);
                        break;
                case Down:
                        snakeSprite.setPosition(snakeSprite.getPosition().x, snakeSprite.getPosition().y + 20);
                        break;
                case Right:
                        snakeSprite.setPosition(snakeSprite.getPosition().x + 20, snakeSprite.getPosition().y);
                        break;
                case Left:
                        snakeSprite.setPosition(snakeSprite.getPosition().x - 20, snakeSprite.getPosition().y);
                        break;
                }

                lastPosition0 = (snakeSprite.getPosition());
                gameClock.restart();
        }

}
 

The different positions for the tail is all respectively set to their previous position, thus different positions.

I've been programming for less than a week so bare with me :)

All constructive criticism is welcomed.
« Last Edit: June 09, 2013, 01:56:31 pm by wizh »

The Hatchet

  • Full Member
  • ***
  • Posts: 135
    • View Profile
    • Email
Re: Snake program not working.
« Reply #3 on: June 09, 2013, 02:14:36 pm »
Kudos for learning to program, but I'm going to say the best thing you could probably do would be to find a c++ snake game tutorial online, there are lots if you google it.  They may not use SFML but really all you need SFML for is to draw to the screen anyways, most will probably use some other openGL library or raw openGL calls. 

Go find some basic coding tutorials since the logic of "I need to draw these first parts once at this spot then use a bool to not draw them again at that spot" is not very good logic. 

And your Else chunk is drawing the tail on the same spot 3 times.  Lets say 'lastPosition0' is at (10, 10):
tail.setPosition(lastPosition0); //sets tail to (10, 10)
            mainWindow.draw(tail); //draws the tail at (10, 10)
            lastPosition1 = tail.getPosition(); //sets lastPosition1 to (10, 10) since tail was at (10, 10)
           
            tail.setPosition(lastPosition1); //sets tail to (10, 10)
            mainWindow.draw(tail); //draws at (10, 10)
            lastPosition2 = tail.getPosition(); //sets lastPosition2 to (10, 10) since tail was still at (10, 10)

            tail.setPosition(lastPosition2); // sets tail to (10, 10)
            mainWindow.draw(tail);

Since i have nothing better to do I could try and prototype a simple snake game in the next while to give you a base example of what I would do I suppose.

wizh

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Snake program not working.
« Reply #4 on: June 09, 2013, 02:48:09 pm »
Kudos for learning to program, but I'm going to say the best thing you could probably do would be to find a c++ snake game tutorial online, there are lots if you google it.  They may not use SFML but really all you need SFML for is to draw to the screen anyways, most will probably use some other openGL library or raw openGL calls. 

Go find some basic coding tutorials since the logic of "I need to draw these first parts once at this spot then use a bool to not draw them again at that spot" is not very good logic. 

And your Else chunk is drawing the tail on the same spot 3 times.  Lets say 'lastPosition0' is at (10, 10):
tail.setPosition(lastPosition0); //sets tail to (10, 10)
            mainWindow.draw(tail); //draws the tail at (10, 10)
            lastPosition1 = tail.getPosition(); //sets lastPosition1 to (10, 10) since tail was at (10, 10)
           
            tail.setPosition(lastPosition1); //sets tail to (10, 10)
            mainWindow.draw(tail); //draws at (10, 10)
            lastPosition2 = tail.getPosition(); //sets lastPosition2 to (10, 10) since tail was still at (10, 10)

            tail.setPosition(lastPosition2); // sets tail to (10, 10)
            mainWindow.draw(tail);

Since i have nothing better to do I could try and prototype a simple snake game in the next while to give you a base example of what I would do I suppose.

I think you misunderstood my idea.

I made this little part just as a fun little sideproject to the 'real' game. I wanted to make the program myself, but I guess I could see how you'd handle it ^^

Still wondering why the sprite is not being displayed, though - even if it were 3 at the same place.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Snake program not working.
« Reply #5 on: June 09, 2013, 02:49:38 pm »
Kudos for learning to program, but I'm going to say the best thing you could probably do would be to find a c++ snake game tutorial online, there are lots if you google it.
I'd say that would probably be the worst thing.

You'll certainly find a lots that use plain old arrays, or worse new[] and delete[], or even worse self-built data structures. Global variables, reinvented wheels, and general bad style is unfortunately very common in C++ tutorials on the internet, especially in those on YouTube. By learning from internet tutorials, you get used to a lot of bad habits that are difficult to get rid of. Of course there are exceptions.

Anyway, wizh, you're doing it far too complicated. In order to draw a snake, it is enough to store a list of segments, for example in the STL container std::deque. One possibility is to have a pure logical class called Segment that stores the position (tile indices, not world units) of the segment, and possibly its type.
struct Segment
{
    enum Type { Head, Body, Tail };

    Type type;
    sf::Vector2i gridPosition;
};

class Game
{
    ...
    private:
        std::deque<Segment> segments;
};
In each step, you remove the last segment with pop_back() and insert a new one with push_front(). If you use different segment types, you have to adapt the front one before inserting the new head.

Of course you can also iterate through all segments and just update their positions, that requires less memory allocations. In this case, you could also use std::vector (in fact, for such tiny sizes the container choice is almost irrelevant, so you choose the one that's easiest to handle). There are many possibilities, but it's important to have a clear view of the parts of your game. This is where classes help a lot.

To render, you can just loop through all segments, create a sprite for each segment on the fly, and draw it. This won't be a performance issue. Otherwise you could still store the sprite in the segment, but it's usually cleaner to keep graphics and logics separated.

Also, don't mix event handling with game logics. Upon user inputs, you just set a variable such as the direction, but you don't change the snake directly. The snake (describing the gameplay) is modified during the update step of your game, which usually happens in regular intervals.
« Last Edit: June 09, 2013, 02:53:55 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

The Hatchet

  • Full Member
  • ***
  • Posts: 135
    • View Profile
    • Email
Re: Snake program not working.
« Reply #6 on: June 09, 2013, 03:08:08 pm »
Kudos for learning to program, but I'm going to say the best thing you could probably do would be to find a c++ snake game tutorial online, there are lots if you google it.
I'd say that would probably be the worst thing.

You'll certainly find a lots that use plain old arrays, or worse new[] and delete[], or even worse self-built data structures. Global variables, reinvented wheels, and general bad style is unfortunately very common in C++ tutorials on the internet, especially in those on YouTube. By learning from internet tutorials, you get used to a lot of bad habits that are difficult to get rid of. Of course there are exceptions.

It may not be the best but it sounded like he has no programming experience with the "Been only programming for under a week" line.  So I thought maybe seeing some examples would give him ideas.  Once he learned to get the bad ideas working we could set him on the path to good ideas.

As far as why it's not drawing, you could have loaded the texture out of order of order of when you set it to your sprite, could be not loading the texture at all.  You didn't show us where you load and set the textures only where you draw it(which seems as though it should draw it even if only on the same spot).

And yes, as Nexus said you are making this far more complicated than it needs be I think.  This is my stupid, quick and dirty 'snake' program that only consists of 3 segments.

#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <iostream>
#include <vector>

#define StageWidth 800
#define StageHeight 600
#define BitsPerPixel 32

int main(int argc, char** argv)
{
    sf::RenderWindow window(sf::VideoMode(StageWidth, StageHeight, BitsPerPixel), "Game");

    sf::Texture snakeTile;
    sf::Sprite snakeSprite;
    if(snakeTile.loadFromFile("Assets/Textures/basictile.png") != true){
                std::cout << "Texture failed to load" << std::endl;
                return 1;
        }
        snakeSprite.setTexture(snakeTile);

        std::vector<sf::Sprite> snakeBits; //a vector to hold our snake bits, [0] will be the head

        snakeBits.push_back(snakeSprite); //[0] //this makes an actual copy in the vector
        snakeBits.push_back(snakeSprite); //[1]
        snakeBits.push_back(snakeSprite); //[2]

    snakeBits.at(0).setPosition(100, 100); //set initual position
    snakeBits.at(1).setPosition(132, 100); //my sprites are 32x32
    snakeBits.at(2).setPosition(164, 100);

    while (window.isOpen())
    {
        sf::Event event;//storage for events
        while(window.pollEvent(event)){
            if(event.type == sf::Event::KeyPressed){
                int oldX = snakeBits.at(0).getPosition().x;
                int oldY = snakeBits.at(0).getPosition().y;
                if(event.key.code == sf::Keyboard::Down){
                    snakeBits.at(0).setPosition(oldX, oldY+32);
                    snakeBits.at(2).setPosition(snakeBits.at(1).getPosition().x, snakeBits.at(1).getPosition().y);
                    snakeBits.at(1).setPosition(oldX, oldY);
                }
                if(event.key.code == sf::Keyboard::Left){
                    snakeBits.at(0).setPosition(oldX-32, oldY);
                    snakeBits.at(2).setPosition(snakeBits.at(1).getPosition().x, snakeBits.at(1).getPosition().y);
                    snakeBits.at(1).setPosition(oldX, oldY);
                }
                if(event.key.code == sf::Keyboard::Right){
                    snakeBits.at(0).setPosition(oldX+32, oldY);
                    snakeBits.at(2).setPosition(snakeBits.at(1).getPosition().x, snakeBits.at(1).getPosition().y);
                    snakeBits.at(1).setPosition(oldX, oldY);
                }
                if(event.key.code == sf::Keyboard::Up){
                    snakeBits.at(0).setPosition(oldX, oldY-32);
                    snakeBits.at(2).setPosition(snakeBits.at(1).getPosition().x, snakeBits.at(1).getPosition().y);
                    snakeBits.at(1).setPosition(oldX, oldY);
                }
            }
            if (event.type == sf::Event::Closed)
                window.close();
        }
        window.clear();

        for(std::vector<int>::size_type i = 0; i != snakeBits.size(); i++)
            window.draw(snakeBits.at(i));

        window.display();
    }

   return 0;
}

It only moves as you press the keys, it doesn't move on its own.  That's some game logic you could work out for yourself.
« Last Edit: June 09, 2013, 03:09:39 pm by The Hatchet »

wizh

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Snake program not working.
« Reply #7 on: June 09, 2013, 03:22:45 pm »
Kudos for learning to program, but I'm going to say the best thing you could probably do would be to find a c++ snake game tutorial online, there are lots if you google it.
I'd say that would probably be the worst thing.

You'll certainly find a lots that use plain old arrays, or worse new[] and delete[], or even worse self-built data structures. Global variables, reinvented wheels, and general bad style is unfortunately very common in C++ tutorials on the internet, especially in those on YouTube. By learning from internet tutorials, you get used to a lot of bad habits that are difficult to get rid of. Of course there are exceptions.

Anyway, wizh, you're doing it far too complicated. In order to draw a snake, it is enough to store a list of segments, for example in the STL container std::deque. One possibility is to have a pure logical class called Segment that stores the position (tile indices, not world units) of the segment, and possibly its type.
struct Segment
{
    enum Type { Head, Body, Tail };

    Type type;
    sf::Vector2i gridPosition;
};

class Game
{
    ...
    private:
        std::deque<Segment> segments;
};
In each step, you remove the last segment with pop_back() and insert a new one with push_front(). If you use different segment types, you have to adapt the front one before inserting the new head.

Of course you can also iterate through all segments and just update their positions, that requires less memory allocations. In this case, you could also use std::vector (in fact, for such tiny sizes the container choice is almost irrelevant, so you choose the one that's easiest to handle). There are many possibilities, but it's important to have a clear view of the parts of your game. This is where classes help a lot.

To render, you can just loop through all segments, create a sprite for each segment on the fly, and draw it. This won't be a performance issue. Otherwise you could still store the sprite in the segment, but it's usually cleaner to keep graphics and logics separated.

Also, don't mix event handling with game logics. Upon user inputs, you just set a variable such as the direction, but you don't change the snake directly. The snake (describing the gameplay) is modified during the update step of your game, which usually happens in regular intervals.

Thanks for your detailed response. About handling game logics and user input, I actually what you suggest (I think):

void Game::handleEvents() {
         sf::Event event;
        while (mainWindow.pollEvent(event))
        {
                        switch(event.type)
                        {
                        case sf::Event::Closed:
                                mainWindow.close();
                                break;
                        }

                        switch (event.key.code)
                        {
                        case sf::Keyboard::Up:
                                if (Direction != Down) {
                                        Direction = Up;
                                } break;
                        case sf::Keyboard::Down:
                                if (Direction != Up) {
                                        Direction = Down;
                                } break;
                        case sf::Keyboard::Right:
                                if (Direction != Left) {
                                        Direction = Right;
                                } break;
                        case sf::Keyboard::Left:
                                if (Direction != Right) {
                                        Direction = Left;
                                } break;
                        }
        }
}

void Game::moveSnake() {
        elapsed = gameClock.getElapsedTime();
        if (elapsed.asSeconds() >= 0.15) {
                switch(Direction)
                {
                case Up:
                        snakeSprite.setPosition(snakeSprite.getPosition().x, snakeSprite.getPosition().y - 20);
                        break;
                case Down:
                        snakeSprite.setPosition(snakeSprite.getPosition().x, snakeSprite.getPosition().y + 20);
                        break;
                case Right:
                        snakeSprite.setPosition(snakeSprite.getPosition().x + 20, snakeSprite.getPosition().y);
                        break;
                case Left:
                        snakeSprite.setPosition(snakeSprite.getPosition().x - 20, snakeSprite.getPosition().y);
                        break;
                }

                lastPosition0 = (snakeSprite.getPosition());
                gameClock.restart();
        }

}

Kudos for learning to program, but I'm going to say the best thing you could probably do would be to find a c++ snake game tutorial online, there are lots if you google it.
I'd say that would probably be the worst thing.

You'll certainly find a lots that use plain old arrays, or worse new[] and delete[], or even worse self-built data structures. Global variables, reinvented wheels, and general bad style is unfortunately very common in C++ tutorials on the internet, especially in those on YouTube. By learning from internet tutorials, you get used to a lot of bad habits that are difficult to get rid of. Of course there are exceptions.

It may not be the best but it sounded like he has no programming experience with the "Been only programming for under a week" line.  So I thought maybe seeing some examples would give him ideas.  Once he learned to get the bad ideas working we could set him on the path to good ideas.

As far as why it's not drawing, you could have loaded the texture out of order of order of when you set it to your sprite, could be not loading the texture at all.  You didn't show us where you load and set the textures only where you draw it(which seems as though it should draw it even if only on the same spot).

And yes, as Nexus said you are making this far more complicated than it needs be I think.  This is my stupid, quick and dirty 'snake' program that only consists of 3 segments.


It only moves as you press the keys, it doesn't move on its own.  That's some game logic you could work out for yourself.

Thanks for the code! My program is actually already doing that (making the snake move on it's own) :)
« Last Edit: June 09, 2013, 03:24:48 pm by wizh »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Snake program not working.
« Reply #8 on: June 09, 2013, 03:51:11 pm »
About handling game logics and user input, I actually what you suggest (I think):
Yes, Game::handleEvents() is exactly how I meant it :)

Now you can apply the direction to more than one segment. By the way, you can use the sf::Sprite::move() function.

Once he learned to get the bad ideas working we could set him on the path to good ideas.
That's unfortunately not how it works. If people have a running solution, they tend not to adapt to better alternatives. You see that at every C programmer who wants to learn C++: he struggles with new features and stays fixed at old concepts, because "they still work".

This is my stupid, quick and dirty 'snake' program that only consists of 3 segments.
I wouldn't use #define for constants. And of course a loop for more than 3 segments ;)

As a side note: wizh, please don't quote the full post, but rather the specific sentence you refer to. Otherwise, discussions with a lot of text like this one become quickly unreadable.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

The Hatchet

  • Full Member
  • ***
  • Posts: 135
    • View Profile
    • Email
Re: Snake program not working.
« Reply #9 on: June 09, 2013, 04:08:36 pm »
This is my stupid, quick and dirty 'snake' program that only consists of 3 segments.
I wouldn't use #define for constants. And of course a loop for more than 3 segments ;)
[/quote]

Which I normally don't, like I said, a quick dirty stupid version I made in like 10 minutes.  I should also only be creating 1 sprite and just pushing pointers to it unto the vector to save on memory resources, but again, quick and dirty. 

And yes, it is true that most devs tend to keep using what they first learn works which is unfortunate.  So in that regards maybe we could try and point him in the direction of Good coding tutorials?  Even in academia some of the coding idioms aren't very good.  After learning what I could there I focused to refine, refine and refine some more to learn good coding ways which is hard when online is sooooo full of bad tutorials.  I've learned a half dozen different ways to structure, load, draw, loop before I was finally able to distill what was actually needed on a bare bones level to do everything.

Before I found SFML I just about went crazy trying to learn openGL stuff even with just initializing it.  Some tutorials use like 2 lines to initialize, some use over 30 to set all kinds of initilization parameters, but did any of those tutorials actually go over any of what the commands were actually doing?  NO!  very few actually talked about what each thing did.  Sure reading through the openGL docs helps some but if you already don't know what certain features do, describing a feature with another feature or word you don't understand doesn't help.

wizh

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Snake program not working.
« Reply #10 on: June 09, 2013, 05:09:19 pm »
I can't for the love of god find out why this isn't working. I implemented the way The Hatchet did it (kinda). Going to make it into for loops and make it able to obtain more peices that you pick up. That part shouldn't be so hard I guess. However in the first place, the code that I have at the moment is not working as intended.
The snake is not being printed on the screen at all. I removed some of the methods that wasn't related to the problem:

Header file:

#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <iostream>
#include <vector>

class Game {
private:
        sf::RenderWindow mainWindow;
        sf::Texture snakeTexture;
        sf::Texture tailTexture;
        sf::Sprite snakeSprite;
        sf::Sprite tail;

        std::vector<sf::Sprite> snakeSegments;
       
        int oldX;
        int oldY;
        enum direction {Up, Down, Right, Left} Direction;

        void handleEvents();
        void moveSnake();
        void setupSegments();

        //void checkForCollisionWithWall();
        //bool collisionWithTail();
               
        void createMainWindow();

public:
        void run();
        Game();
};

Implementation file:

#include "Game.h"

void Game::createMainWindow() {
        mainWindow.create(sf::VideoMode(800,600), "Snake", sf::Style::Titlebar | sf::Style::Close);
        mainWindow.setMouseCursorVisible(false);
}

void Game::handleEvents() {
         sf::Event event;
        while (mainWindow.pollEvent(event))
        {
                        switch(event.type)
                        {
                        case sf::Event::Closed:
                                mainWindow.close();
                                break;
                        }

                        switch (event.key.code)
                        {
                        case sf::Keyboard::Up:
                                if (Direction != Down) {
                                        Direction = Up;
                                } break;
                        case sf::Keyboard::Down:
                                if (Direction != Up) {
                                        Direction = Down;
                                } break;
                        case sf::Keyboard::Right:
                                if (Direction != Left) {
                                        Direction = Right;
                                } break;
                        case sf::Keyboard::Left:
                                if (Direction != Right) {
                                        Direction = Left;
                                } break;
                        }
        }
}

void Game::moveSnake() {
                oldX = snakeSegments.at(0).getPosition().x;
        oldY = snakeSegments.at(0).getPosition().y;

                switch(Direction)
                {
                case Up:
                        snakeSegments.at(0).setPosition(oldX, oldY-20);
            snakeSegments.at(2).setPosition(snakeSegments.at(1).getPosition().x, snakeSegments.at(1).getPosition().y);
            snakeSegments.at(1).setPosition(oldX, oldY);
                        break;
                case Down:
                        snakeSegments.at(0).setPosition(oldX, oldY+20);
            snakeSegments.at(2).setPosition(snakeSegments.at(1).getPosition().x, snakeSegments.at(1).getPosition().y);
            snakeSegments.at(1).setPosition(oldX, oldY);
                        break;
                case Right:
                        snakeSegments.at(0).setPosition(oldX+20, oldY);
            snakeSegments.at(2).setPosition(snakeSegments.at(1).getPosition().x, snakeSegments.at(1).getPosition().y);
            snakeSegments.at(1).setPosition(oldX, oldY);       
                        break;
                case Left:
                        snakeSegments.at(0).setPosition(oldX-20, oldY);
            snakeSegments.at(2).setPosition(snakeSegments.at(1).getPosition().x, snakeSegments.at(1).getPosition().y);
            snakeSegments.at(1).setPosition(oldX, oldY);
                        break;
                }
}

void Game::setupSegments() {
        for (int i = 0; i < 3; i++) {
                snakeSegments.push_back(snakeSprite);
                snakeSegments.at(i).setPosition(100 + i*20, 100);
        }
}

void Game::run() {
    createMainWindow();

        while(mainWindow.isOpen())
        {
                handleEvents();
                moveSnake();
                               
                mainWindow.clear();

                for(std::vector<int>::size_type i = 0; i != snakeSegments.size(); i++) {
                        mainWindow.draw(snakeSegments.at(i));
                }

                mainWindow.display();
        }
}

Game::Game() {
        setupSegments();

        Direction = Down;

        snakeTexture.loadFromFile("pTexture.png");
        tailTexture.loadFromFile("tailTexture.png");

        snakeSprite.setTexture(snakeTexture);
        tail.setTexture(tailTexture);
}

Thanks in advance!

wizh

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Snake program not working.
« Reply #11 on: June 09, 2013, 05:09:58 pm »
I can't for the love of god find out why this isn't working. I implemented the way The Hatchet did it (kinda). Going to make it into for loops and make it able to obtain more peices that you pick up. That part shouldn't be so hard I guess. However in the first place, the code that I have at the moment is not working as intended - the snake is not being printed on the screen at all. I removed some of the methods that wasn't related to the problem:

Header file:

#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <iostream>
#include <vector>

class Game {
private:
        sf::RenderWindow mainWindow;
        sf::Texture snakeTexture;
        sf::Texture tailTexture;
        sf::Sprite snakeSprite;
        sf::Sprite tail;

        std::vector<sf::Sprite> snakeSegments;
       
        int oldX;
        int oldY;
        enum direction {Up, Down, Right, Left} Direction;

        void handleEvents();
        void moveSnake();
        void setupSegments();

        //void checkForCollisionWithWall();
        //bool collisionWithTail();
               
        void createMainWindow();

public:
        void run();
        Game();
};

Implementation file:

#include "Game.h"

void Game::createMainWindow() {
        mainWindow.create(sf::VideoMode(800,600), "Snake", sf::Style::Titlebar | sf::Style::Close);
        mainWindow.setMouseCursorVisible(false);
}

void Game::handleEvents() {
         sf::Event event;
        while (mainWindow.pollEvent(event))
        {
                        switch(event.type)
                        {
                        case sf::Event::Closed:
                                mainWindow.close();
                                break;
                        }

                        switch (event.key.code)
                        {
                        case sf::Keyboard::Up:
                                if (Direction != Down) {
                                        Direction = Up;
                                } break;
                        case sf::Keyboard::Down:
                                if (Direction != Up) {
                                        Direction = Down;
                                } break;
                        case sf::Keyboard::Right:
                                if (Direction != Left) {
                                        Direction = Right;
                                } break;
                        case sf::Keyboard::Left:
                                if (Direction != Right) {
                                        Direction = Left;
                                } break;
                        }
        }
}

void Game::moveSnake() {
                oldX = snakeSegments.at(0).getPosition().x;
        oldY = snakeSegments.at(0).getPosition().y;

                switch(Direction)
                {
                case Up:
                        snakeSegments.at(0).setPosition(oldX, oldY-20);
            snakeSegments.at(2).setPosition(snakeSegments.at(1).getPosition().x, snakeSegments.at(1).getPosition().y);
            snakeSegments.at(1).setPosition(oldX, oldY);
                        break;
                case Down:
                        snakeSegments.at(0).setPosition(oldX, oldY+20);
            snakeSegments.at(2).setPosition(snakeSegments.at(1).getPosition().x, snakeSegments.at(1).getPosition().y);
            snakeSegments.at(1).setPosition(oldX, oldY);
                        break;
                case Right:
                        snakeSegments.at(0).setPosition(oldX+20, oldY);
            snakeSegments.at(2).setPosition(snakeSegments.at(1).getPosition().x, snakeSegments.at(1).getPosition().y);
            snakeSegments.at(1).setPosition(oldX, oldY);       
                        break;
                case Left:
                        snakeSegments.at(0).setPosition(oldX-20, oldY);
            snakeSegments.at(2).setPosition(snakeSegments.at(1).getPosition().x, snakeSegments.at(1).getPosition().y);
            snakeSegments.at(1).setPosition(oldX, oldY);
                        break;
                }
}

void Game::setupSegments() {
        for (int i = 0; i < 3; i++) {
                snakeSegments.push_back(snakeSprite);
                snakeSegments.at(i).setPosition(100 + i*20, 100);
        }
}

void Game::run() {
    createMainWindow();

        while(mainWindow.isOpen())
        {
                handleEvents();
                moveSnake();
                               
                mainWindow.clear();

                for(std::vector<int>::size_type i = 0; i != snakeSegments.size(); i++) {
                        mainWindow.draw(snakeSegments.at(i));
                }

                mainWindow.display();
        }
}

Game::Game() {
        setupSegments();

        Direction = Down;

        snakeTexture.loadFromFile("pTexture.png");
        tailTexture.loadFromFile("tailTexture.png");

        snakeSprite.setTexture(snakeTexture);
        tail.setTexture(tailTexture);
}

Thanks in advance!

The Hatchet

  • Full Member
  • ***
  • Posts: 135
    • View Profile
    • Email
Re: Snake program not working.
« Reply #12 on: June 09, 2013, 05:32:04 pm »
void Game::setupSegments() {
    for (int i = 0; i < 3; i++) {
        snakeSegments.push_back(snakeSprite);
        snakeSegments.at(i).setPosition(100 + i*20, 100);
    }
}

You aren't setting the texture to the segments.  try
void Game::setupSegments() {
    for (int i = 0; i < 3; i++) {
        snakeSegments.push_back(snakeSprite);
        snakeSegments.at(i).setPosition(100 + i*20, 100);
        snakeSegments.at(i).setTexture(tailTexture);
    }
}

wizh

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Snake program not working.
« Reply #13 on: June 09, 2013, 06:01:34 pm »
Still nothing... Not even if I call the setupSegmunts() method at the bottom of the Game() method.

The Hatchet

  • Full Member
  • ***
  • Posts: 135
    • View Profile
    • Email
Re: Snake program not working.
« Reply #14 on: June 09, 2013, 06:11:09 pm »
I just made a new project, copied all your code, changed the setupSegments() to
void Game::setupSegments() {
    for (int i = 0; i < 3; i++) {
        snakeSegments.push_back(snakeSprite);
        snakeSegments.at(i).setPosition(100 + i*20, 100);
        snakeSegments.at(i).setTexture(tailTexture);
    }
}
and called setupSegments() AFTER createMainWindow() and it works fine for me. I also disabled the moveSnake() because it immediately shot off the screen, just so i could see that it loaded and displayed.

You should never try to do any SFML related functions before you create your SFML window, things tend to not work correctly.
« Last Edit: June 09, 2013, 06:34:43 pm by The Hatchet »