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

Author Topic: Drawing to window from a seperate function/tile engine help  (Read 4165 times)

0 Members and 1 Guest are viewing this topic.

Walker

  • Full Member
  • ***
  • Posts: 181
    • View Profile
Drawing to window from a seperate function/tile engine help
« on: January 16, 2010, 05:52:24 am »
Hey there,

I am working on a simple tile based strategy game. The problem I am having comes from needing to create my window in the main function, but I want to draw sprites/tiles from a seperate function. Is it possible to do this?

Should I just draw every sprite in the main function, and just move them in my other function?

Additionally, the map is only 15x10 tiles, they are all on screen at once. Should I loop through and draw every tile each frame, or should I perhaps parse the map at setup and draw it to a background image/sprite and just draw that each frame?

Cheers

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Drawing to window from a seperate function/tile engine help
« Reply #1 on: January 16, 2010, 04:15:53 pm »
You could pass your window as reference or pointer to other functions in order to access it there.

But you should keep the code inside main really small, if you develop a bigger project. Try to write classes for every task, such as rendering, game logics, input-handling, and so on. Like this, you split up a big problem into multiple classes which act independently from the concrete implementation of others. This design is much more flexible, as it allows the individual parts to be altered or even exchanged without forcing the whole code to adapt. By splitting up game logics and graphics, you achieve a similar effect.

To come back to your question, I recommend to make the sf::RenderWindow a member of a specific class, for example GraphicManager (or whatever you want it to be called). This class provides methods to draw the single elements of your game, as for instance enemies or buildings. Like this, the elements themselves don't know how to be drawn; the rendering-related code is centralized in GraphicManager.

That's just a suggestion, I have made the experience that this design is more powerful and flexible than the probably straightforward way that every game unit owns a sprite (or even worse, derives from a sprite). Actually, I used to do it like this as well, and encountered several drawbacks. I hope, those tips help you, don't hesitate to ask if you don't understand something. ;)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Walker

  • Full Member
  • ***
  • Posts: 181
    • View Profile
Drawing to window from a seperate function/tile engine help
« Reply #2 on: January 17, 2010, 03:26:27 am »
Thanks for the thorough reply. I'm now working on a graphic manager class, any extra tips on the interface for this would be great.

How would you (or anyone) go about drawing the map? I have read many tutorials on tile based games, but none seem to cover the basic question of how to actually build the basic tile engine. Currently I have a nested for loop to work through an array (that will be filled from a file later), I imagine there isn't many choices for this part, but then I have an ugly series of if statements to work out which tile has what attributes and which sprite to use there. Should I make a tile class (probably yes, make a class for everything  :wink:) and what sort of functions would it need? It probably needs a general map class to tell it what to do as well?

You may have noticed that I find classes a bit scary still. lol

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Drawing to window from a seperate function/tile engine help
« Reply #3 on: January 17, 2010, 04:36:56 am »
I'm glad you're really appreciating the suggestions. A lot of people don't care about the code design at all (mostly to their own disadvantage, at least in the long term). I can tell you a lot about how I implemented my tasks and what I consider practical, however that's not the only solution (as usual, considering design choices). There might be different circumstances in your case, or you might doubt a concrete approach. You have to know, I am not happy with all of my decisions, but sometimes you have just to try out something, or it is never going to be implemented. ;)
I hope you can nevertheless apply some ideas to your project. Just ask if something is not clear.

Quote from: "Walker"
I'm now working on a graphic manager class, any extra tips on the interface for this would be great.
Okay. First, I wrote for every game element a class. In my jump'n'run, there were enemies, the player, projectiles, and so on. These classes inherit from a common base class which stores things like position and velocity. Then, there is the main logic-handling class called Game. It stores the game elements (each type in a separate STL container), and inside a member function Game::Output() – not mandatory the best name – I passed the container elements to GraphicManager.

The GraphicManager class provides several overloaded Draw() functions, each taking a const reference to the desired logic object.
Code: [Select]
void Draw(const Player& player);
void Draw(const Enemy& enemy);
void Draw(const Projectile& projectile);
// ...

Inside, the functions create local sprites, set them up according to the objects' states (by invoking getter methods, for example Player::GetPosition()) and call MyRenderWindow.Draw(sprite); where MyRenderWindow is a member of GraphicManager (to be exact, only a reference to an sf::RenderWindow, but that depends on the implementation). Creating every frame new sprites might be a performance issue, if you have got really really many of them. In my case, this was never a problem, so I implement it the easy way. Separating graphics from logics becomes more difficult otherwise, a std::map is one of the alternatives.

Quote from: "Walker"
How would you (or anyone) go about drawing the map? I have read many tutorials on tile based games, but none seem to cover the basic question of how to actually build the basic tile engine.
Sadly, there aren't really good tutorials regarding such stuff. I have learned only very few things from tutorials. Anyway, you gain the most experience by developping own projects and experimenting with new things. A very important thing is in my opinion the knowledge about C++ itsself. I don't only mean the raw language features, although they can be very complex and yet powerful (for example templates), but also common techniques like RAII and modern design patterns. There are a lot of good books (Meyers, Sutter, Alexandrescu) which can teach you quite a lot about effective and modern programming.

Quote from: "Walker"
How would you (or anyone) go about drawing the map? [...] Currently I have a nested for loop to work through an array (that will be filled from a file later), I imagine there isn't many choices for this part,
You're right, a 2-dimensional array (or better container) is the usual way. Note that you only draw the tiles that are really required (calculate the screen bounds, divide by tile size and you get the tile indices).

Quote from: "Walker"
but then I have an ugly series of if statements to work out which tile has what attributes and which sprite to use there. Should I make a tile class (probably yes, make a class for everything  :wink:) and what sort of functions would it need? It probably needs a general map class to tell it what to do as well?
A class is certainly no bad idea here. However, you don't need to put everything in a class, we're not in Java. For example, you should generally rather use global functions when appropriate (i.e. when they don't need access to private member data).

But for tiles, a class is helpful, especially if they become more complicated. In my project, the tile class just stores some state about its representation. I had a public enum in the class to name the distinct tile types and a private member variable to store the type. Additionally, there were related getter and setter functions. Depending on your specific needs, you can establish further methods to form the interface.
Code: [Select]
class Tile
{
    public:
        enum TileType
        {
            Empty,
            Grass,
            Rock,
            // ...
        };

    public:
        void SetType(TileType Type);
        TileType GetType() const;

    private:
        TileType MyType;
        // other tile-related logic data
};

My design decision was not to store the tile position in the tiles themselves. Their position is given by the index in the nested container, and duplicating information is always bad. Not only because it consumes unnecessarily memory, you also have to make sure both informations are always consistent. Besides (at least in my case), a tile doesn't care about where it stands, so why should it know about the position?

Now comes the interesting part, namely the integration of tiles into game logics and graphics. It's standing to reason that we can store the tiles together with other logic elements, in a new nested container inside the Game class. In my project, it first looked like this:
Code: [Select]
std::vector<std::vector<Tile> > MyTiles;
But now I'm using a TileMap class. This is just for convenience, because I need some special operations (for example resizing the map at the edges, and so on). You actually don't need an own class for this. Maybe, a typedef helps you not to write std::vector<std::vector<Tile> > or whatever all the time (and to be able to change the container type).

The tiles are looped through as usual and each of them is passed to GraphicManager. Here, the overload has more parameters: The tile indices. This is required because as mentioned, the tiles don't store their position, and the GraphicManager has to know where to draw them.
Code: [Select]
void GraphicManager::Draw(const Tile& tile, unsigned int x, unsigned int y);
Invoking the function is straightforward:
Code: [Select]
void Game::OutputTiles()
{
    // calculate bounds
    for (unsigned int x = BeginX; x < EndX; ++x)
    {
        for (unsigned int y = BeginY; y < EndY; ++y)
        {
            GraphicMgr.Draw(Tiles[x][y], x, y);
        }
    }
}

GraphicMgr is here not a member of Game, but member of a superior, singleton-like class holding all the managers. The identifier GraphicMgr is a macro for convenience (actually, a reference would be prettier, but I came into trouble because at definition time, the target wasn't constructed yet). Just if you wonder... :)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Walker

  • Full Member
  • ***
  • Posts: 181
    • View Profile
Drawing to window from a seperate function/tile engine help
« Reply #4 on: January 17, 2010, 12:39:47 pm »
Quote
A lot of people don't care about the code design at all


I have done enough small projects to know (or atleast think) that code design is equally important as the game design as a whole. If you start off with a good, solid code base, things should go much easier once you start adding little features.

You've given me a fair bit to think about now, encasing the entire game in a class for one. I will have to meditate on this a bit.

Do you know any examples of well coded open source games I could look at? The simpler the better, I guess, but built like a larger, more complex game.

Thanks for all the tips, I'm sure I will be back with more questions in a short while.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Drawing to window from a seperate function/tile engine help
« Reply #5 on: January 17, 2010, 02:01:07 pm »
Quote from: "Walker"
I will have to meditate on this a bit.
Yeah, do this. :)

As mentioned, just be sceptical! If you have got a better idea for something, implement it your way. ;)

Quote from: "Walker"
Do you know any examples of well coded open source games I could look at?
No, sorry. I haven't looked at a lot of other's game code yet...
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: