for (int i = 0; i < grassSprites.size(); i++)
{
grassSprites.setTexture(grassTexture);
grassSprites.setPosition(100 + (i * 50), 200);
App.draw(grassSprites);
}
Should be:
for (int i = 0; i < grassSprites.size(); i++)
{
cout << i << endl;
grassSprites[i].setTexture(grassTexture);
grassSprites[i].setPosition(100 + (i * 50), 200);
App.draw(grassSprites[i]);
}
and you need to Load your texture first before you make the vectors containing the sprites. so this:
if (grassTexture.loadFromFile("Images/grass.png") == 0)
{
return 1;
}
if (waterTexture.loadFromFile("Images/water.png") == 0)
{
return 1;
}
vector<sf::Sprite> grassSprites(10, sf::Sprite(grassTexture));
vector<sf::Sprite> waterSprites(10, sf::Sprite(waterTexture));
This works for me after the changes. BUT with that said I do not think you are using vectors correctly. You are using them as if they are an array. If you know how many items are gonna be in it just use an array. If you need to dynamically change how many items are being stored then you a vector and you push and pop items off of it. As well using a simple for(int i) loop to go through a vector is bad coding practice. If you are going to iterate through a vector or other specific container like a map you want to do something like this:
for(std::vector<int>::size_type i = 0; i != items.size(); i++)
items.at(i)->Draw(game);
Where items is my vector of an item class.
You also should not be assigning a texture everytime you want to draw a sprite. Ideally as you push sprites into your container you want to set their texture only once then. Or make your container, fill it with sprites then in a single loop set all their textures. Setting the texture everytime you are going to draw is gonna be a big performance hit later on.
I'm trying to help another user in the 'Graphics' sub-forum also trying to make a snake game. This is the quick and dirty 'snake' program I made to try and help it out. I know it still does some things in a brute force way but maybe it'll help you a bit.
#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;
}
Arrow keys to move
Learning to properly use vectors will make a snake game easy, since a snake can grow as you eat you just push a new segment onto the vector. If doing this 'for real' I would make a snake class containing a vector of pointers pointing to the segment sprite so that we don't waste resources and memory filling it with multiples of the same sprite and textures.
The easiest way for a grid with lines on it is to have the lines on the actual image file. Basically if a tile image is 32x32 pixels have a 1 pixel border of that image that is black(or whatever color you want) and when it tiles it will be a grid with lines.
Grid based maps are usually stored in a container class of one sort or another. The most basic would be an array. You can use some math and just use a 1 dimension array or store it in a 2d array so you can access each x and y in a more natural way. such as:
int map[10][10] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
Where each int represents a different type of tile, the 4 '1's in the middle are different squares than the '0'. Only do this tho if you have a set size level. If you want dynamic size levels there are better approaches to this.
Here's a small example for 2d arrays of set size: http://www.cplusplus.com/forum/beginner/42045/