4 Replies - 828 Views - Last Post: 21 June 2012 - 07:47 AM Rate Topic: -----

#1 Gonzo0193  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 2
  • View blog
  • Posts: 49
  • Joined: 16-December 09

Looping through a vector.

Posted 20 June 2012 - 11:46 AM

So i am having trouble looping through a vector and drawing everything in it to the screen (using SFML).

Here is the loop:

		for(int i = 0; i < enemyList.size(); i++)
		{
			//sf::Sprite tempSprite = enemyList[i];
			window.draw(enemyList[i]);
		}



The vector is intialised as:

std::vector<sf::Sprite> enemyList; 



and added too with this function:

void Game::addEnemy(int x, int y)
{
	sf::Texture enemyImageTemp;
	sf::Sprite enemyTemp;
	if(!enemyImageTemp.loadFromFile("images/tux.png"))
	{
		//Something went wrong
		std::cout << "Couldnt Load image for enemy" << std::endl;
	}
	enemyTemp.setTexture(enemyImageTemp);
	enemyTemp.setPosition(x,y);
	enemyList.push_back(enemyTemp);
	if(enemyList.size() < 1)
	{
		std::cout << "nothing added" << std::endl;
	}
}



here is all my code:

main.h
#ifndef _main_H_
    #define _main_H

#include <SFML/Graphics.hpp>
#include <iostream>
#include <Windows.h>
#include <vector>


class Game {

private:

public:

	sf::RenderWindow window;
	std::vector<sf::Sprite> enemyList;
	sf::Sprite playerSprite;
	sf::Texture playerTexture;

	void addEnemy(int x, int y);
};

#endif



main.cpp
#include "main.h"

const int PLAYER_MOVE_SPEED = 3;

std::vector<sf::Sprite> enemyList; 

void Game::addEnemy(int x, int y)
{
	sf::Texture enemyImageTemp;
	sf::Sprite enemyTemp;
	if(!enemyImageTemp.loadFromFile("images/tux.png"))
	{
		//Something went wrong
		std::cout << "Couldnt Load image for enemy" << std::endl;
	}
	enemyTemp.setTexture(enemyImageTemp);
	enemyTemp.setPosition(x,y);
	enemyList.push_back(enemyTemp);
	if(enemyList.size() < 1)
	{
		std::cout << "nothing added" << std::endl;
	}
}

int main()
{
	Game game;

    sf::RenderWindow window(sf::VideoMode(1024, 768), "SFML works!");
		window.setFramerateLimit(60);
		window.setVerticalSyncEnabled(true);

	 

	sf::Sprite playerSprite;
	sf::Texture playerTexture;

	if(!playerTexture.loadFromFile("images/tux.png"))
	{
		//Something went wrong
		std::cout << "Couldnt Load image for player" << std::endl;
	}
	playerSprite.setTexture(playerTexture);
	playerSprite.setScale(0.2,0.2);
	playerSprite.setPosition(0, 768 - 100);

	game.addEnemy(100,100);

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

		if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
		{
			playerSprite.move(-PLAYER_MOVE_SPEED,0);
		}
		if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
		{
			playerSprite.move(PLAYER_MOVE_SPEED,0);
		}

        window.clear();
		window.draw(playerSprite);
		window.draw(enemyList[0]);

		for(int i = 0; i < enemyList.size(); i++)
		{
			//sf::Sprite tempSprite = enemyList[i];
			window.draw(enemyList[i]);
		}

        window.display();
    }

    TerminateProcess(GetCurrentProcess(), EXIT_SUCCESS);
}



Is This A Good Question/Topic? 1
  • +

Replies To: Looping through a vector.

#2 NickDMax  Icon User is offline

  • Can grep dead trees!
  • member icon

Reputation: 2250
  • View blog
  • Posts: 9,245
  • Joined: 18-February 07

Re: Looping through a vector.

Posted 20 June 2012 - 12:27 PM

Quote

So i am having trouble looping through a vector and drawing everything in it to the screen (using SFML).


Please tell us what KIND of trouble you are having? Help us understand what is happening, is it a syntax thing? Does it compile but does not draw the sprites? That is a lot of code to go swimming though looking for "trouble".

One thing I did note though -- you have two "enemyList" vectors -- one is a global variable (generally we try to avoid global variables) the other is a member of Game.

Make sure you know which one is which when you use it!

This post has been edited by NickDMax: 20 June 2012 - 12:27 PM

Was This Post Helpful? 1
  • +
  • -

#3 Gonzo0193  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 2
  • View blog
  • Posts: 49
  • Joined: 16-December 09

Re: Looping through a vector.

Posted 20 June 2012 - 01:19 PM

View PostNickDMax, on 20 June 2012 - 08:27 PM, said:

Quote

So i am having trouble looping through a vector and drawing everything in it to the screen (using SFML).


Please tell us what KIND of trouble you are having? Help us understand what is happening, is it a syntax thing? Does it compile but does not draw the sprites? That is a lot of code to go swimming though looking for "trouble".

One thing I did note though -- you have two "enemyList" vectors -- one is a global variable (generally we try to avoid global variables) the other is a member of Game.

Make sure you know which one is which when you use it!


I didn't realise that made i global, i was just doing what i would in c#. The problem i was having when it wasn't global was that the vector would be destroyed after the addEnemy function was called.

If i keep the one that belongs to game in, i get a vector subscript out of range. If i leave it as a global it is now seeming to work. So i guess my problem is now how do i get the list from destructing itself after being used in addEnemy?
Was This Post Helpful? 0
  • +
  • -

#4 NickDMax  Icon User is offline

  • Can grep dead trees!
  • member icon

Reputation: 2250
  • View blog
  • Posts: 9,245
  • Joined: 18-February 07

Re: Looping through a vector.

Posted 21 June 2012 - 07:02 AM

Well, ultimately I was able to fix your issue with the list but ran into another problem:

From SFML documentation for sf:Sprite

Quote

It is important to note that the sf::Sprite instance doesn't copy the texture that it uses, it only keeps a reference to it. Thus, a sf::Texture must not be destroyed while it is used by a sf::Sprite (i.e. never write a function that uses a local sf::Texture instance for creating a sprite).


This means that that this little bit of code does not work:
void Game::addEnemy(int x, int y)
{
	sf::Texture enemyImageTemp; //this is a local instance and will be deconstructed at end of scope.
	sf::Sprite enemyTemp;
	if(!enemyImageTemp.loadFromFile("images/tux.png"))
	{
		//Something went wrong
		std::cout << "Couldnt Load image for enemy" << std::endl;
	}
	enemyTemp.setTexture(enemyImageTemp);
	enemyTemp.setPosition(x,y);
	enemyList.push_back(enemyTemp);
	if(enemyList.size() < 1)
	{
		std::cout << "nothing added" << std::endl;
	}
}



You see enemyList.push_back(enemyTemp); makes a COPY of the sf::sprite which DOES NOT make a copy of the Texture, which means as soon as the Texture is out of scope it is destroyed.


So is the code that I got to "work" -- I don't think it is organized the best but that is something you will have to work out. Personally I think you will probably need to create and Enemy class to encapsulate the sprite and to ensure that the Texture remains intact when the object is copied (STL vectors do a lot of copying).

#define SFML_STATIC

#include <SFML/Graphics.hpp>
#include <iostream>
#include <Windows.h>
#include <vector>


class Game {

private:

public:

	sf::RenderWindow& window;
	sf::Texture enemyImage;
	std::vector<sf::Sprite> enemyList;
	Game(sf::RenderWindow& wn);
	void addEnemy(int x, int y);
	void draw();
};


const int PLAYER_MOVE_SPEED = 3;

Game::Game(sf::RenderWindow& wn) : window(wn) {
	if(!enemyImage.loadFromFile("C:\\CProjects\\Blog\\images\\tux.png"))
	{
		//Something went wrong
		std::cout << "Couldnt Load image for enemy" << std::endl;
	}
}

void Game::addEnemy(int x, int y)
{
	sf::Sprite enemyTemp;

	enemyTemp.setTexture(enemyImage);
	enemyTemp.setScale(0.2,0.2);
	enemyTemp.setPosition(x,y);
	window.draw(enemyTemp);
	enemyList.push_back(enemyTemp);
	if(enemyList.size() < 1)
	{
		std::cout << "nothing added" << std::endl;
	}
}

void Game::draw() {
	for(size_t i = 0; i < enemyList.size(); i++)
	{
		window.draw(enemyList[i]);
		//std::cout <<i << std::endl;
	}
}

int main()
{
    sf::RenderWindow window(sf::VideoMode(1024, 768), "SFML works!");
		window.setFramerateLimit(60);
		window.setVerticalSyncEnabled(true);
	Game game(window);



	game.addEnemy(100,100); 

	sf::Sprite playerSprite;
	sf::Texture playerTexture;

	if(!playerTexture.loadFromFile("C:\\CProjects\\Blog\\images\\tux.png"))
	{
		//Something went wrong
		std::cout << "Couldnt Load image for player" << std::endl;
	}
	playerSprite.setTexture(playerTexture);
	playerSprite.setScale(0.2,0.2);
	playerSprite.setPosition(0, 768 - 100);

	game.addEnemy(200,200);

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

		if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
		{
			playerSprite.move(-PLAYER_MOVE_SPEED,0);
		}
		if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
		{
			playerSprite.move(PLAYER_MOVE_SPEED,0);
		}

        window.clear();
		window.draw(playerSprite);
		game.draw();
		window.display();        
    }

    TerminateProcess(GetCurrentProcess(), EXIT_SUCCESS);
}

This post has been edited by NickDMax: 21 June 2012 - 07:05 AM

Was This Post Helpful? 0
  • +
  • -

#5 vividexstance  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 653
  • View blog
  • Posts: 2,240
  • Joined: 31-December 10

Re: Looping through a vector.

Posted 21 June 2012 - 07:47 AM

I haven't tried out the code, but what about using a static array of Sprites? Also, I know this is nit-picking, but I just want to point out that even though this code works, from Game::addEnemy():
if(enemyList.size() < 1)
{
	std::cout << "nothing added" << std::endl;
}


I think this is more explicit:
if(enemyList.empty())
{
	std::cout << "nothing added" << std::endl;
}


Was This Post Helpful? 0
  • +
  • -

Page 1 of 1