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

Author Topic: How to structure a SFML game?  (Read 10523 times)

0 Members and 1 Guest are viewing this topic.

Canvas

  • Full Member
  • ***
  • Posts: 107
    • View Profile
How to structure a SFML game?
« on: June 19, 2014, 03:33:51 pm »
Hello there fellow SFML users,

This is going to be a big question so get ready. First off I have attempted to create quite a few games with C++ and SFML, programming the functionality isn't to hard, but after a few weeks, or months or even days my structure does always seem to mess up, what I mean by that is, due to something I did way back means i have to amend something new to fix that problem but some of my old functions are using that function, this happens all the time and I completely understand it is my fault for not fully understanding the structure of my game or the program.

So basically I am trying to create a simple clone of Mario Bros, so we have a title screen, a character, some enemies, a map made of blocks, score, time, lives, levels, continues, projectiles etc. So here is the my problem, using SFML i have myself a imageService, soundService and musicService, now these basically just load a file and store it inside of a map so I can call on that file when I need. But here is the main problem

I have a State which has a ImageService, the state has a hero and a level, would I assign them each a image? for example hero.sprite = imageService.images["heroImg"]; would that be the best way? Second lets say if a level had some blocks, but some blocks are infront of the hero, would I have to write out my render function to say

//Draw level blocks

//Draw hero

//Draw upper level blocks

//Draw menu

//etc...
 

But then a really big important part is, the renderwindow is 800 by 600, in most computer games the user is allowed to change the size of the game, so lets say the user wants to display 1280 by 768, where would be the best place to draw the sprites differently? What about collision detection? if the view was 800 by 600 and now it is 1280 by 768 the width has go up by 1.5 and a bit and the height has changed by 168 pixels, would I save a global variable in my state which has the "ratios" of the screen? so 800 by 600 = 1:1 and 1280 by 768 = 1.6:1.28 would I then use that to modify all sprites displaying and also use that to modify collision detection?

I'm just really trying to get my head around the structure of a game, does anyone have any simple links to books or articles on how to structure one, or even better a tutorial on how to structure a simple SFML game.
« Last Edit: June 19, 2014, 03:37:56 pm by Canvas »

Mörkö

  • Jr. Member
  • **
  • Posts: 96
    • View Profile
Re: How to structure a SFML game?
« Reply #1 on: June 19, 2014, 07:31:06 pm »
I have been trying to teach myself programming since two years back, and an important part about asking for help is this: Try to be as specific as possible in your questions. You will have better luck getting help if you try to ask specific and technical questions instead of broad and possibly open ended ones. For example, your post contains many questions, most of which aren't precise enough to have any single answer, or not enough context to do so. Therefore answering your post as a whole would be much more difficult than if you had posed a single technical question. In short, try to help the people who want to help you, it's easier for them to answer small questions.

That's just some friendly advice from a someone who asks a lot of questions.

Quote
due to something I did way back means i have to amend something new to fix that problem but some of my old functions are using that function, this happens all the time and I completely understand it is my fault for not fully understanding the structure of my game or the program.

Sounds like you may benefit from making an effort to follow the principles of `Separation of Concerns.` That means encapsulating different areas of functionality such that they aren't entangled in other areas. Making the different concerns into strictly defined and separated modules, with a clearly defined API, will make it so that if you need to rewrite, say, the rendering module down the line, then you don't need to go deep into every area of your project changing function calls and so on, because you defined the interface clearly from the start.

Other ideas include:
Trying to plan your program flow more carefully before actually writing any code.

Writing unit tests for every function, and writing your tests before actually writing your functions.

Trying to make your code `purely functional` whenever possible. That means to minimize your use of functions that have side effects such as changing a global value, or functions that have varying return value depending on something else than their input parameters. This takes some getting used to, but you may very well find that your code is much more robust and reusable.

Quote
I have a State which has a ImageService, the state has a hero and a level, would I assign them each a image? for example hero.sprite = imageService.images["heroImg"];

Without knowing anything about the rest of the structure of your code, I don't think it's too weird or unusual to have some kind of entity system, that includes some kind of Entity.Sprite or Entity.getSprite() attribute. In any case, for small games, I think that's acceptable because it's pretty straightforward and clear what is going on. But I'm not really sure what you are asking, so forgive me if I'm not making sense.

Quote
Second lets say if a level had some blocks, but some blocks are infront of the hero, would I have to write out my render function to say

//Draw level blocks

//Draw hero

//Draw upper level blocks

//Draw menu

//etc...

Well, not explicitly unless there is some other reason to. Maybe you could just assign every sprite a Z value, and render them in order going from least Z to most Z.

Quote
But then a really big important part is, the renderwindow is 800 by 600, in most computer games the user is allowed to change the size of the game, so lets say the user wants to display 1280 by 768, where would be the best place to draw the sprites differently? What about collision detection? if the view was 800 by 600 and now it is 1280 by 768 the width has go up by 1.5 and a bit and the height has changed by 168 pixels, would I save a global variable in my state which has the "ratios" of the screen? so 800 by 600 = 1:1 and 1280 by 768 = 1.6:1.28 would I then use that to modify all sprites displaying and also use that to modify collision detection?

I don't understand the first part of that, you may want to clarify what you mean.

As for collision detection, it would be unusual to scale distances in the game world according to window size. More sane is to apply all game logic such as collision detection using your normal measures, and just scale the final image in rendering.

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: How to structure a SFML game?
« Reply #2 on: June 19, 2014, 07:53:15 pm »
Might as well answer the one part I have an opinion on (and think I understand).

But then a really big important part is, the renderwindow is 800 by 600, in most computer games the user is allowed to change the size of the game, so lets say the user wants to display 1280 by 768, where would be the best place to draw the sprites differently? What about collision detection? if the view was 800 by 600 and now it is 1280 by 768 the width has go up by 1.5 and a bit and the height has changed by 168 pixels, would I save a global variable in my state which has the "ratios" of the screen? so 800 by 600 = 1:1 and 1280 by 768 = 1.6:1.28 would I then use that to modify all sprites displaying and also use that to modify collision detection?

The aspect ratio shouldn't matter at all.  If any part of your game logic depends on that in some way, you've probably made a big mistake.

I'm aware of two good and simple ways to handle multiple window sizes:

1) All game objects have the same sizes and positions no matter what, and all you do is upscale/downscale the whole thing to the current window size using sf::View.

2) The scale/view remains constant (or the user controls it separately), so that different window sizes simply mean more or less of the world around the player is visible.  In this case you'll typically the GUI/HUD to change positions at different window sizes, which is easily done by having it always draw itself X pixels away from a certain corner of the window.

In either case the "actual" sizes and positions of all things in the game world (as opposed to GUI/HUD bits) remain identical, regardless of what happens to the window.

Canvas

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Re: How to structure a SFML game?
« Reply #3 on: June 19, 2014, 08:53:51 pm »
First off thank you for reading my post, I do understand it is quite open which doesn't help.

Mårran your information is awesome, but by any change could you explain more about the Z axis? I understand it is the layer in front of others but what I mean is, how would I get my render method to go though them correctly without sorting them?

Ixrec that to me does make sense, I shouldn't have to change my collision detection due to screen size, you said something about sf::View, I will be using a sf::RenderWindow for my game, can I still leave that to do the scaling for me?

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: How to structure a SFML game?
« Reply #4 on: June 19, 2014, 08:56:38 pm »
No matter how much you think about the overall design, class interfaces, encapsulation etc, upfront - it's a fact of life that you'll never think of everything before you start coding (doesn't mean you shouldn't try though).
For any reasonably large project (and even small ones) you will always discover things you didn't anticipate, learn new things and find bugs (in the code as well as the design) as you go about writing your code. That will inevitably lead to a need/want to refactoring parts of the code along the way - nothing wrong with that, that's perfectly normal.
It's a rare piece of code that's designed once, implemented and debugged once and then never touched again. Most code undergoes multiple - smaller or larger - rewrites/refactorings during the lifetime of a project. Just a fact of life.

Of course a good design, good encapsulation, good separation of responsibilities etc. goes a long way towards minimizing the need for ongoing refactoring, but you will never eliminate it and you shouldn't be afraid of it. When you learn new and better ways to do things, discover flaws in your design and so on, the smart thing to do is often to embrace that new knowledge and refactor your code to benefit from it.

Just my $0.02  :)
« Last Edit: June 19, 2014, 08:58:11 pm by Jesper Juhl »

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: How to structure a SFML game?
« Reply #5 on: June 19, 2014, 09:14:47 pm »
but by any change could you explain more about the Z axis? I understand it is the layer in front of others but what I mean is, how would I get my render method to go though them correctly without sorting them?

The Z order in 2d graphics is the depth or layering. To control what gets drawn on top you must draw it from back to front.

Quote
I will be using a sf::RenderWindow for my game, can I still leave that to do the scaling for me?

The window classes will automatically scale current view to fit the window so stuff will be stretched according the the current view's size. If this is what you want then you do not need to worry about sf::View.
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Canvas

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Re: How to structure a SFML game?
« Reply #6 on: June 19, 2014, 10:02:02 pm »
Thank you Jesper Juhl for the information

zsbzsb about the Z order, have you got any small examples on how this is implemented? I am about to start a very basic version of the mario clone now, so hopefully tomorrow I will have some source code you guys can see :)

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: How to structure a SFML game?
« Reply #7 on: June 19, 2014, 10:07:04 pm »
window.clear();

// notice the order
// back to front

window.draw(background); // background first

window.draw(player); // then our player over the background

window.draw(hud); // then our user interface or whatever you want over the player

window.display();
 
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Canvas

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Re: How to structure a SFML game?
« Reply #8 on: June 19, 2014, 10:10:49 pm »
So you don't provide each object with a Z id, you just put them in the correct order in the render function?

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: How to structure a SFML game?
« Reply #9 on: June 19, 2014, 10:34:14 pm »
This problem is more about how you personally want to structure your program than anything else.  If you choose to simply have, let's say, a Background object, a Level object (containing a vector of Block objects), a Player object, and a vector of Enemy objects, then you can just draw them in the obviously correct order and leave it at that.

You can do some more flexible things given a generic base class like Entity for all your drawables.  For instance, you could have vectors called background, middleground and foreground of pointers to Entities.  Or you could give all Entities a Z member and have a single vector of pointers to them which you sort every frame.  But only you can decide if you'll actually need anything like that.  For a Mario clone I would assume you don't.

In my program I use a vector of Layer objects, where each layer points to a number of Entities and the drawing code simply loops over the Layers in the correct order.  But I needed a *lot* of flexibility (some of my entities had child entities!), so this is likely to be overkill for you.

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: How to structure a SFML game?
« Reply #10 on: June 19, 2014, 11:29:04 pm »
So you don't provide each object with a Z id, you just put them in the correct order in the render function?

When it comes down to it, yes - you must order the way you draw them.

But you can also follow Ixrec's advice and add your own Z value to entities and store them in one of the std containers that is sorted. Then just draw the entities in the order that they are stored in the container.
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Canvas

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Re: How to structure a SFML game?
« Reply #11 on: June 20, 2014, 12:55:33 am »
What would be a good variable type for an ordered list? A map?

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
« Last Edit: June 20, 2014, 01:00:52 am by zsbzsb »
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Mörkö

  • Jr. Member
  • **
  • Posts: 96
    • View Profile
Re: How to structure a SFML game?
« Reply #13 on: June 20, 2014, 06:25:41 am »
Or you could give all Entities a Z member and have a single vector of pointers to them which you sort every frame.

Why every frame? You only need to sort them once every time a sprite has just added, and that's assuming the data structure of the layers doesn't have predefined layers that the Z value falls into.

Example 1, each sprite has a Z value deciding it's layer of rendering:
spriteArray = list(sprite for sprite in spritesToBeLoaded)
spriteArray.sort(key=lambda sprite: sprite.z)

# rendering loop
while(gameRunning):
    for sprite in spriteArray:
        render(sprite) # already sorted

# later in the game, some entity is added
spriteArray.append(newSprite)
spriteArray.sort(key=lambda sprite: sprite.z) # we are good until next time something is added
 

Example 2, the sprite data-structure has preexisting layers:
spriteLayers = dict()
for layer in range(maxLayers):
    spriteLayers[layer] = list()

#when adding sprites, they are automatically sorted based on Z attribute
for sprite in spritesToBeLoaded:
    spriteLayers[sprite.Z].append(sprite)

#rendering them in the right order is trivial
for layer in range(maxLayers):
    for sprite in spriteLayers[layer]:
        render(sprite)

#no need to do any sorting, the structure is always sorted
newSprite = Sprite()
spriteLayers[newSprite.Z] = newSprite
 

The second alternative is more similar to the option about having a background-object, level-object and foreground-object, while still retaining all the flexibility offered by Z attribute based layering. 

Canvas

  • Full Member
  • ***
  • Posts: 107
    • View Profile
Re: How to structure a SFML game?
« Reply #14 on: June 20, 2014, 03:20:13 pm »
Mårran yours seems alot easier to implement :), but here is a quick overview of my game structure so far, hopefully I will have some code to show you guys later today.

I have a Game which has an ImageService, RenderService and State
The imageService is used to load images
The renderService has a sf::RenderWindow which has a map of displayObjects known as backgrounds,
These are populated by the State,
The state has a pointer to both imageservice and renderservice which is provided by the Game class.

So every time the game updates, it calls the state update and that then will get all displayObjects from the object it needs (lets say the hero) and pass them into the renderService.DisplayObjects which is a map of DisplayObject,

A DisplayObject is just a custom class which has a sf::Sprite and a DisplayObjectName which is an enum. Is this structure to complex for a simple game? Or am I over complicating the situation?