I'm in the early stages of a game I would love to create and i'm trying to work out how the game program should be structured (classes, headers etc). I'm using C++ and SFML for this project.
Let me first by showing you my basic image of the structure. Don't pay attention to MainMenuState.cpp and NewGameState.cpp
(http://i.stack.imgur.com/dymw5.png)
Game.cpp will have an instance of all those services, it will also have the MainMenuState, NewGameState and LevelState. Now here is my problem.
Game.cpp will have a method that will call the RenderService.RenderWindow, I'm trying to work out exactly how I should code this method? Should I pass in an arrayList of sf::sprites? If I do this, the LevelState.cpp will need an ArrayList of sf::Sprites. which will be updated on each game step. But lets say the Hero.cpp has 1 sf::Sprite. the Map.cpp has 20 sf::sprites and Monster.cpp has 1 sf::Sprite. this would mean I have to pass 22 sf::Sprites back to the RenderService every game step (60fps). so that is 1320 sf::Sprites per second back to the RenderService. I understand game structure is a very hard thing to do and hard to implement correctly, because there isn't a "set" way. I have created a Vector which holds sf::Sprites and every time I call my Render function I clear the vector before so everything is removed for memory. This works fine. Would that be the answer? But as I stated before is passing a lot of sf::Sprites to be rendered ok?
Here is my simple SFML program to test this
#include <SFML/Graphics.hpp>
#include "ImageService.h"
#include "DisplayObject.h"
#include "Enums.h"
ImageService is;
DisplayObject displayObject;
int main()
{
sf::RenderWindow window(sf::VideoMode(1024, 768), "SFML works!");
sf::CircleShape shape(100.f);
shape.setFillColor(sf::Color::Green);
is.Images[image1].loadFromFile("ship1.tga");
displayObject.sprite.setTexture(is.Images[displayObject.spriteType]);
std::vector<sf::Sprite> displayObjects;
while (window.isOpen())
{
displayObjects.clear();
displayObjects.push_back(displayObject.sprite);
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(shape);
//Draw out the selected sprites
for (int i = 0; i < displayObjects.size(); i++)
{
window.draw(displayObjects.at(i));
}
window.display();
}
return 0;
}
Let me know if you would like me to explain any part of my program
Ok so, here is a snippet of code I just created.
#include <SFML/Graphics.hpp>
#include "ImageService.h"
#include "DisplayObject.h"
#include "Enums.h"
ImageService is;
DisplayObject obj1;
DisplayObject obj2;
DisplayObject obj3;
DisplayObject obj4;
DisplayObject obj5;
int timer = 0;
int main()
{
sf::RenderWindow window(sf::VideoMode(1024, 768), "SFML works!");
is.Images[image1].loadFromFile("Block.png");
obj1.sprite.setTexture(is.Images[obj1.spriteType]);
obj1.sprite.setColor(sf::Color(255, 0, 0));
obj1.sprite.setPosition(100,100);
obj2.sprite.setTexture(is.Images[obj2.spriteType]);
obj2.sprite.setColor(sf::Color(0, 255, 0));
obj3.sprite.setPosition(200, 100);
obj3.sprite.setTexture(is.Images[obj3.spriteType]);
obj3.sprite.setColor(sf::Color(0, 0, 255));
obj4.sprite.setPosition(300,100);
obj4.sprite.setTexture(is.Images[obj4.spriteType]);
obj4.sprite.setColor(sf::Color(127, 127, 127));
obj5.sprite.setPosition(400,100);
obj5.sprite.setTexture(is.Images[obj5.spriteType]);
std::vector<sf::Sprite> displayObjects;
displayObjects.push_back(obj1.sprite);
displayObjects.push_back(obj2.sprite);
displayObjects.push_back(obj3.sprite);
displayObjects.push_back(obj4.sprite);
displayObjects.push_back(obj5.sprite);
window.setFramerateLimit(60);
while (window.isOpen())
{
timer++;
if (timer == 60)
{
obj1.sprite.setPosition(100, 200);
obj2.sprite.setPosition(200, 200);
obj4.sprite.setPosition(400, 200);
}
for (int i = 0; i < displayObjects.size(); i++)
{
window.draw(displayObjects.at(i));
}
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
//Draw out the selected sprites
for (int i = 0; i < displayObjects.size(); i++)
{
window.draw(displayObjects.at(i));
}
window.display();
}
return 0;
}
a DisplayObject at the moment just holds a Sprite and has a Sprites, Sprites is an enum which is used for loading the correct sprite for that object.
So as you can see we have 5 display objects, these are then pushed onto the vector, now that I have updated obj1, obj2 and obj4, how would I then tell the vector to update these? I can just say at position 0, 1 and 3, but if I were to do that where would I get the numbers 0, 1 and 3 from? Would i have to do something on the lines of this?
#include <SFML/Graphics.hpp>
#include "ImageService.h"
#include "DisplayObject.h"
#include "Enums.h"
ImageService is;
DisplayObject obj1;
DisplayObject obj2;
DisplayObject obj3;
DisplayObject obj4;
DisplayObject obj5;
int timer = 0;
int main()
{
sf::RenderWindow window(sf::VideoMode(1024, 768), "SFML works!");
is.Images[image1].loadFromFile("Block.png");
obj1.sprite.setTexture(is.Images[obj1.spriteType]);
obj1.sprite.setColor(sf::Color(255, 0, 0));
obj1.sprite.setPosition(100,100);
obj2.sprite.setTexture(is.Images[obj2.spriteType]);
obj2.sprite.setColor(sf::Color(0, 255, 0));
obj2.sprite.setPosition(200, 100);
obj3.sprite.setTexture(is.Images[obj3.spriteType]);
obj3.sprite.setColor(sf::Color(0, 0, 255));
obj3.sprite.setPosition(300,100);
obj4.sprite.setTexture(is.Images[obj4.spriteType]);
obj4.sprite.setColor(sf::Color(127, 127, 127));
obj4.sprite.setPosition(400,100);
obj5.sprite.setTexture(is.Images[obj5.spriteType]);
std::vector<sf::Sprite> displayObjects;
displayObjects.push_back(obj1.sprite);
obj1.positionInVector = displayObjects.size() - 1;
displayObjects.push_back(obj2.sprite);
obj2.positionInVector = displayObjects.size() - 1;
displayObjects.push_back(obj3.sprite);
obj3.positionInVector = displayObjects.size() - 1;
displayObjects.push_back(obj4.sprite);
obj4.positionInVector = displayObjects.size() - 1;
displayObjects.push_back(obj5.sprite);
obj5.positionInVector = displayObjects.size() - 1;
window.setFramerateLimit(60);
while (window.isOpen())
{
timer++;
if (timer == 60)
{
obj1.sprite.setPosition(100, 200);
displayObjects.at(obj1.positionInVector) = obj1.sprite;
obj2.sprite.setPosition(200, 200);
displayObjects.at(obj2.positionInVector) = obj2.sprite;
obj4.sprite.setPosition(400, 200);
displayObjects.at(obj4.positionInVector) = obj4.sprite;
}
for (int i = 0; i < displayObjects.size(); i++)
{
window.draw(displayObjects.at(i));
}
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
//Draw out the selected sprites
for (int i = 0; i < displayObjects.size(); i++)
{
window.draw(displayObjects.at(i));
}
window.display();
}
return 0;
}
It does seem a little long winded, but it does work. Is that what you were thinking?
Update
dwarfman78 I do agree with you, but I don't want to get into a habit that is seen as "wrong" or "not great for performance" code.