-
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 :)
-
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?
-
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.
-
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.
-
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.
-
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.
-
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.
-
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) :)
-
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.
-
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.
-
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!
-
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!
-
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);
}
}
-
Still nothing... Not even if I call the setupSegmunts() method at the bottom of the Game() method.
-
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.
-
Aaaaand it's working. Didn't realize that was happening. I just setup a timer to fix that problem :)
Thanks a bunch! Will report back if I get stuck ^^
-
You should never try to do any SFML related functions before you create your SFML window, things tend to not work correctly.
I actually thought SFML would ensure a valid OpenGL context when it needs one. wizh, is the Game instance global?
Some suggestions concerning the STL (even if it was just a quick and dirty example, writing the correct code doesn't really take longer):
for(std::vector<int>::size_type i = 0; i != snakeSegments.size(); i++)
That's not the usual way to iterate. First, you can use std::size_t directly if you need indices. But generally, prefer iterators if you don't need random access, because they allow you to switch containers. Also, pre-increment ++i can be faster for complexer types (not integers).
for (std::vector<int>::iterator itr = snakeSegments.begin(); itr != snakeSegments.end(); ++itr)
With C++11, you can infer the type:
for (auto itr = snakeSegments.begin(); itr != snakeSegments.end(); ++itr)
Or directly use the range-based for loop:
for (sf::Sprite& sprite : snakeSegments)
Furthermore, std::vector::at() is almost always the wrong choice. It performs an index check and throws an exception. If your indices are correct, you don't need that (definitely not in an iteration loop). If they are not correct, the STL implementation will still check the error in debug mode with an assertion.
In short: Use std::vector::operator[] for random access. And use iterators to iterate.
-
Furthermore, std::vector::at() is almost always the wrong choice. It performs an index check and throws an exception. If your indices are correct, you don't need that (definitely not in an iteration loop). If they are not correct, the STL implementation will still check the error in debug mode with an assertion.
In short: Use std::vector::operator[] for random access. And use iterators to iterate.
Like I said, I've found 3+ ways to do everything between all the tutorials and examples I've ever seen, and most of the time no one bothers to explain WHY you want to use one way over another. Thank you for this knowledge.
I want to start using C++11 so bad but I'm stuck developing across multiple machines stuck with multiple dev environments from different points in time so I'm not sure if I can without a huge headache. Smart pointers look frickin awesome
-
Thanks for the additional comments :)
If you mean global as being instantiated in another class, then yes. It's not globally available though.
-
Hmm. I just can't seem to get it working... When I pickup another piece, I'm trying to get something that's out of bounds of my vector. I can't seem to get the logic down. Here is the code: http://pastebin.com/Fw9CgdUd.
I'm going to bed now. Thanks a bunch in advance! I don't want you to code it for me, just give me a pointer as wto what should be done differently :)
-
I must go to bed as well. Looking quickly over your code I can't see anything blaringly obvious. One of the easiest and most basic debugging techniques I can share with you is make massive use of std::cout, or printf(), whichever you prefer. Whenever something gives you grief, like an 'Out of Bounds' error, throw some COUTs where you think its happening to check where you iterators are pointing to. Hell sometimes a simple COUT can show whethere you even get into a function or not.
-
wizh, you should really use the debugger to solve such problems, because you will encounter them again and again. Out of bound errors are found in seconds with the debugger.
And generally, if you really can't solve an issue and want us to help you, consider the advice given in this post (http://en.sfml-dev.org/forums/index.php?topic=5559.msg36368#msg36368). Nobody likes to look at 250 lines of your custom code, even less if there is no meaningful error description.
-
I posted all the code since I had no idea where the error was occurring. I fixed the problem by using breakpoints - that was a really helpful method! :)
If someone was wondering, there were several problems in the moveSnake() method and the eatCircle() method. Here is the changes i made: http://pastebin.com/abdxsKMG
Have a great day everybody, and thanks for the help :D