Practical SFML - Game Design Issues

Pages: 12
Heya,

Many of us have been playing around with C++/SFML, but what is the best practical implementation for a lot of subjects that are so briefly discussed in the official tutorials? There are a lot of approaches to different problems, but which is the best?

Getting input
* Using [window identifier].GetInput() all the time.
* Binding the window input to a sf::Input&.
* Other?

Images
* Per class, via static data members.
* Via image-name, using an image handler.
* Other?

Sprites
* Inherit a class from sf::Sprite.
* Per instance, via normal data members.
* Other?

Object-handling (code execution and drawing)
* Hard-coded.
* Dynamically, per level. (a level is simply a set of window specifications and a vector of generic objects)
* Dynamically, via an identifier data member.
* Other?

Time-consistency
* Setting the frame rate limit and hoping the best.
* Multiplying the movement by a factor which is relational to the framerate.
* Other?

Multi-threaded code
When to use it?
When to avoid it?

Discuss!
Last edited on
Getting Input:
I use the Window::GetInput method for handling input. I have an input stack along with a series of input event handlers that are called whenever a specific event occurs, the GetInput method is obviously a requirement here.

Images/Sprites:
Doing mine on my own via OpenGL. I'm not willing to edit the SFML source to allow access to pixel buffers since Xcode is a pain my ass when it comes to projects, but I don't think that the available JPEG- and PNG-loading libraries will be difficult to integrate.

Object-handling:
Callback queues. Sorry Disch, still went with callbacks on this one.

I have a series of... well, I'll just call them function pointers to be simple, std::list<bool (*)()> maintained in classes. The classes have the basic insertion and deletion functions, but it also has a LoopThrough function which goes through and calls each callback in order. I use this for rendering and object processing, along with whatever other tasks need to be done. This is useful for keeping rendering and processing two entirely different things, and it works great for online expandability. The insertion of new mechanisms only require loading the necessary functions from a DLL and pushing those functions onto the call list.

Time-Consistency:
This one is debatable, and I believe this should be an option. In games where there are going to be slight fluctuations with a maintainable high FPS, then I'd suggest delta-time based movement. However, in the case where a game is too demanding and runs on a computer at, say, 10-15 FPS, then constant motion vectors will be optimal so that there are no collision detection issues.

Multi-threaded code:
The use of multi-threaded code depends entirely on the system on which you're building your game. In my system I follow the list<> method for collision detection as well, with a series of blank masks and masks with handlers (callbacks). I loop through the handlers and for each handler I loop through the blank masks. The handlers and masks have identification types, for example maybe a 1 means a tile. If the handler is meant to handle a tile and the mask that's found is a tile, then you'd go through and do your collision detection.

With this in mind I'd probably have a secondary callback list for the actual handling of collisions and have the detection be done through multi-threading, one thread for each handler. Whenever a collision would be detected I'd simply push a structure containing the handler and the object collided with onto the stack.
Getting Input:
I use the Window::GetInput method for handling input. I have an input stack along with a series of input event handlers that are called whenever a specific event occurs, the GetInput method is obviously a requirement here.

Images/Sprites:
Doing mine on my own via OpenGL. I'm not willing to edit the SFML source to allow access to pixel buffers since Xcode is a pain my ass when it comes to projects, but I don't think that the available JPEG- and PNG-loading libraries will be difficult to integrate.

Object-handling:
Callback queues. Sorry Disch, still went with callbacks on this one.

I have a series of... well, I'll just call them function pointers to be simple, std::list<bool (*)()> maintained in classes. The classes have the basic insertion and deletion functions, but it also has a LoopThrough function which goes through and calls each callback in order. I use this for rendering and object processing, along with whatever other tasks need to be done. This is useful for keeping rendering and processing two entirely different things, and it works great for online expandability. The insertion of new mechanisms only require loading the necessary functions from a DLL and pushing those functions onto the call list.

Time-Consistency:
This one is debatable, and I believe this should be an option. In games where there are going to be slight fluctuations with a maintainable high FPS, then I'd suggest delta-time based movement. However, in the case where a game is too demanding and runs on a computer at, say, 10-15 FPS, then constant motion vectors will be optimal so that there are no collision detection issues.

Multi-threaded code:
The use of multi-threaded code depends entirely on the system on which you're building your game. In my system I follow the list<> method for collision detection as well, with a series of blank masks and masks with handlers (callbacks). I loop through the handlers and for each handler I loop through the blank masks. The handlers and masks have identification types, for example maybe a 1 means a tile. If the handler is meant to handle a tile and the mask that's found is a tile, then you'd go through and do your collision detection.

With this in mind I'd probably have a secondary callback list for the actual handling of collisions and have the detection be done through multi-threading, one thread for each handler. Whenever a collision would be detected I'd simply push a structure containing the handler and the object collided with onto the stack.
NGen wrote:
Sorry Disch, still went with callbacks on this one.
Did he make some recommendation on that subject? (If so, what?)

The callback queue seems like a good way to go. I had planned to do something like:
1
2
3
4
5
class Object // every class is derived from this
{  public:
     virtual void Execution() = 0;
     virtual void Render() = 0;
};

And then keep track of all base class pointers/references through some STL container, but that would even execute functions that are empty. (Like for plain blocks, they are only rendered, they don't have some code to be executed.)

NGen wrote:
Multi-threaded code:
The use of ... your collision detection.

I have seen a similar method (it's described in the book "Beginning OpenGL Game Programming, Second Edition"), it would involve the generic class Object described above. We would simply add another pure virtual member function with this prototype:
virtual void Collision(Object&) = 0;
Different objects could react differently depending on the object it collides with.
:< I posted twice? Where's the Delete button?
There are a lot of approaches to different problems, but which is the best?


There's hardly ever a hands-down "best" solution for a given problem. One may be better than others in some circumstances, but might be worse in other circumstances.

In programming, there is never a one-size-fits-all.

That said.... here are my personal thoughts on the above mentioned topics

Getting input

Passing window identifiers around to parts of the program that only need input is rather strange, so I would probably bind to a Input reference.

However, the real question here should be "do I use sf::Input or should I use events?"

Events have the perk of being less likely that they'll be missed. For example say the user presses and releases a button really fast while your program is stalled. If you poll the realtime status with sf::Input, you can miss the button press entirely. However if you work with events, you'll still catch it.

Of course most things in games are based on real-time states and not one-time events, so I tend to favor using sf::Input directly for in-game play. Although I try to use events for things like when the user is customizing their controls.


Images

I tend to prefer having a manager with a unique identifier for each image (typically the identifier is the filename). The advantage to this is that you don't have to concern yourself with preloading the image. The manager can just load the image as it's needed.

This works well with other resources as well.. like sound effects and BGM.

Sprites

IMO it's best not to derive from sf::Sprite, since:

1) it doesn't really make logical sense to do so
2) it means you can only have 1 sprite per object.

What if you want a complex drawn object... like having the arms drawn separately from the torso so that they could be rotated. Or if you draw the face separately so you can have different expressions. Or if you draw different pieces of armor based on what equipment the player is wearing, etc, etc.

Object-handling

There is definitely no one-size-fits-all or even a one-size-fits-most for this problem. This is definately something that needs to be carefully examined and decided on a per project basis.

I do vaguely recall recommending NGen stay away from callbacks because they're unnecessary, confusing, error prone, and have difficult syntax. IIRC, he could just as easily have had a virtual function... but wanted to simulate virtual functions with callbacks for whatever reason. I don't recall the details that well.


For my latest project I'm trying to KISS with hard coded (but rationally organized) objects. That is, enemies and whatnot's logic will all be coded in C++, but will be organized into different classes in a logical hierarchy.

Objects are created dynamically when the map is loaded (which object is where is all stored in the map file) and each object will have different functions called upon different events. Like when they are hit, when they die, etc.

In previous projects I tried to go a step further and have a mini scripting language with which I would code all my object AI and things. The game would then run it all through an interpretter/VM. The problem is coming up with an effective model for that is rather difficult. On the plus side... it makes your game incredibly dynamic, and the possibilities for user mods expands dramatically, since they can just write their own enemies and things.

Time-consistency

I'm not a fan of letting the framerate determine the logic speed. An alternative that I'm currently experimenting and working with is to run your logic at a fixed speed based on a clock (not the framerate). Then interpolate the drawing between logic updates.

For example, if the player moves from x=0 to x=10 on an update, and the screen is drawn 60% of the way between those two updates, you would draw the player at x=6.

There's are pros and cons to each though.

framerate based
pro: easy
pro: smoothest graphics possible when vsyncing
con: if user has mismatching refresh rate, you either can't vsync (which means your graphics aren't smooth anymore) or you'll run at incorrect speed

time based with interpolated graphics
pro: can always vsync
pro: consistent game logic rate no matter what
con: much more difficult to implement correctly


Multi-threading

I don't really have any thoughts on the subject, as I have yet to find a way to work multi-threading into my game projects.
closed account (S6k9GNh0)
With time consistency, for PC, it's standard to do everything based on a timer for even and proper graphics and movement. PC's never have perfect frame-rate. Even on a Console where the frame-rate should always be the same, you'll often find timer-based code in there.

As for threads, networking, input, audio, can all go on separate threads. The theory is that its simplified. In networking, you'll normally start up a thread that will throw out some inventory to a server and will reply while you start preparing for audio and loading a menu or a map or starting an input loop in other threads. As all of these normally contain some sort of infinite loop with benefit. For instance, you could program your entire program without threads but it's actually complexioned by many times. You'll have to have your networking loop and input loop jumbled with your game logic loop. Your network portion could also not be non-blocking, as it would take your whole program to block (however this is easily avoided using some event libraries and polling which is usually what we want anyways). So:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main()
{
  SetupNetwork();
  SetupAudio();
  SetupInput();

   //Just an example.
  for(;;)
  {
     //quickly poll for something in our socket. If nothing exists, move on
     if (Network.Poll()) DoNetworking();
     if (Input.hasEvent()) EventSwitch();
     //game logic and other crap I missed in this shitty example.
  }
}


Granted, this isn't workable code and even if it was, this is barebones example. This can also be wrapped up in an object for us to make the non-threaded logic abstract. HOWEVER, if we were to use threads, we could do something like

1
2
3
4
5
6
7
8
9
10
11
12
int main()
{
  SetupNetwork();
  SetupAudio();
  SetupInput();

   //Just an example.
  for(;;)
  {
     //Game logic with sprites and such
  }
}


Where's our networking and input loop? Well, hotdog, they're handled by that there thread we done setup. Our networking no longer even polls and uses blocking sockets, and our input responds immediately when given an event in an undefined order of logic. When I say undefined, I mean we have no clue when a thread is accessing a variable in this case so when it does, and if that variable can be accessed by other threads or the main program, then we must lock the variable until we are done with it so it doesn't get changed randomly by another thread. This is normally to do with mutexes. This is also the number one cause of thread failureness. People will come up with jumbled variables and wonder why as they expect the threads to automagically wait their turns which doesn't happen. It's usually a one time mistake though.

I didn't have audio in the loop for reason btw. There isn't really an audio loop (as far as I know). And normally, you wouldn't need audio in a thread for small games since the only time you'd need audio is in the case of an event that happened because of input from the user, networking, or similar. I honestly still don't know much about audio programming. I have no clue how to mix multiple sound sources, etc.

I would totally give a more complete example but being rather fed up with GCC, I'm trying to get Clang working. Wish me luck.
Last edited on
Disch wrote:
An alternative that I'm currently experimenting and working with is to run your logic at a fixed speed based on a clock (not the framerate). Then interpolate the drawing between logic updates.
How would you implement such a thing? I kind of understand what you do here, but not how.
Disch wrote:
1) it doesn't really make logical sense to do so
In some occasions, it DOES make sense. Since sf::Sprite stores all the information where the sprite should be drawn, it's practically the same as where the object is located. Of course, as you pointed out, that only applies to simple objects.. like a bat or ball in a Pong game. Or an asteroid in Asteroids.
Disch wrote:
Multi-threading
I don't really have any thoughts on the subject, as I have yet to find a way to work multi-threading into my game projects.
That is an interesting statement too, why have you not needed it. What kind of things have you been writing without using multi-threaded code?
Practically of course, SFML already implements it's own thread system in a lot of occasions. (As computerquip stated above, it can be applied in a lot of situations.) A lot of networking and sound commands are all run on separate threads.
What I've thought to do for something online is have a list<> (of course) set to handle structs that contain information that a message was meant to send. Parsing is done on the thread and then sorted into the structs (or maybe union that contains structs, haven't implemented it yet so I'm not 100% sure on the overall design), where other threads can lock a mutex to access this list. Sure you could just use a non-blocking socket, but then there's the hassle of sending information to multiple threads. It's obviously possibly to do by adding more variables, but this is messy.
I made a big post this morning before work but the site swallowed it, so now I have to repost. =(

How would you implement such a thing? I kind of understand what you do here, but not how.


For positional updates, you keep two states and simply interpolate between them based on the timestamp of the drawing:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void MyClass::Update()
{
  next = !next;

  // put the object at the new position
  state[next].x = whatever;
  state[next].y = whatever;
}

void MyClass::Draw(float pct)
{
  // pct is the percentage with which to interpolate.  If pct==0.5, then drawing occurred exactly
  //  between logic updates

  pos = state[next] - state[!next];  // newstate - oldstate = difference
  pos *= pct;  // interpolate the difference
  pos += state[!next];  // add the oldstate back

  DrawObjectAt( pos );  // that's where we draw
}


For texture animations, I use a millisecond timestamp of when the scene is drawn.

The animation consists of various frames, each of which last for X milliseconds.

When drawing, I use the timestamps to determine how many milliseconds have passed since last scene, and update the animations accordingly.


In some occasions, it DOES make sense. Since sf::Sprite stores all the information where the sprite should be drawn, it's practically the same as where the object is located. Of course, as you pointed out, that only applies to simple objects.. like a bat or ball in a Pong game. Or an asteroid in Asteroids.


Yes and no. sf::Sprite is a class to represent a quad that is drawn on-screen. It isn't interactive.

Inheriting and making it interactive may be convenient, but it's not really logical IMO.

Personally, I don't have my objects deal with sf::Sprite directly anyway. When you do so you have to have each object manage their own animations.

So instead, I have each object have one or more 'Animator's, which is similar in concept to sf::Sprite, but it maintains and updates an animated sequence. That way for my logic, all I have to do is something like body.SetAnimation("jumping"); and the animation is handled automatically.

What kind of things have you been writing without using multi-threaded code?


1 player games without networking.

Practically of course, SFML already implements it's own thread system in a lot of occasions. (As computerquip stated above, it can be applied in a lot of situations.) A lot of networking and sound commands are all run on separate threads.


Which is probably why I haven't had the need to work with threads myself.

SFML already manages audio, so you don't need to create your own audio thread.

I haven't really dealt with networking stuff yet so I can't say. But I'm betting it's similar.

The only other issue I can think of is events, and creating a separate thread for event polling doesn't seem like a good idea to me, since events would impact your game logic.

If you want to have a separate thread, then you have to have some kind of queue or something where you add events to the queue after they've been processed so that the game logic thread can process them. But that's absurd because the event system is already a queue so you might as well poll it directly instead of creating a second queue that does the same thing.
In your code, pct would be the amount of milliseconds that have occured divided by the amount of milliseconds that should have occured?

The scripting language approach seems nice too, but wouldn't a diverse amount of states suffice for something like that? Something like:
1
2
3
4
5
6
creature Goblin {
Can_Attack, // Indicates that this creature is indeed a very nasty opponent
Can_Die, // Indicates that this creature can be killed
Can_Fall, // Indicates that this creature cannot fly
Can_Walk, // Indicates that this creature can move around
etc.}

A similar effect to the scripting language can also be achieved by using C++ together with Python, but I don't know too many details on that subject.

Off-topic:
Have had the post swallowing too, a few times. I tend to save my posts before I post them now, but I will probably forget it someday and hate myself for it, again.
In your code, pct would be the amount of milliseconds that have occured divided by the amount of milliseconds that should have occured?


pct would be a floating point value scaled to be between [0..1] which represents the time the scene is drawn in relationship to the to surrounding logic updates.

For example if you had logic updates at timestamps 100 and 110, and the scene was drawn at timestamp 107, then pct would be 0.7

The formula for calculating it would be:

1
2
3
4
5
// drawtime = timestamp of scene drawing
// updatetime0 = timestamp of "previous" logic update
// updatetime1 = timestamp of "next" logic update

pct = (drawtime - updatetime0) / (updatetime1 - updatetime0);



The scripting language approach seems nice too, but wouldn't a diverse amount of states suffice for something like that?


Well the primary goal of external scripting would be so that you could design new enemies and things without having to recompile the executable.

This makes it especially nice for people to make game mods, since they don't have to worry about getting the program source or compiling it. They can just add their own scripts.
If you want to have a separate thread, then you have to have some kind of queue or something where you add events to the queue after they've been processed so that the game logic thread can process them.
Actually, this is exactly what I did, once. I needed to always handle certain event immediately (e.g. alt+enter for toggling fullscreen), while queuing other events for processing elsewhere. Polling straight from the regular queue wasn't an option because relatively long periods during which polling would be impossible were expected. A non-blocking approach would have made the design far more complicated while offering nothing in return.
I just stumbled upon some old GML codes I had written a long time ago, of which one contained some movement code for a platformer:
NOTE: This is GML, not C++.
1
2
3
4
5
6
// xspeed was declared above here
for(i = 0;i<abs(xspeed);i+=1)
{
   if (place_free(x+sign(xspeed),y)) then x+=sign(xspeed);
   else break;
}
And I realized how simple it was, compared to doing the collision checking yourself. (The above code will move the current object so, that it will never hit a non-moving object horizontally.) So..

What is/are your approach(es) or vision(s) on implementing collision detection?
My current system involves a map based on a series of line segments. It operates by examining line-on-line intersections.

I have a working exe that I can upload when I get home. I'll go into more detail then as well.
I'm trying to make a system that can work with bounding boxes along with polygon-based collision masks. The difficulty is that bounding box-bounding box collisions are much faster to implement, and so I want to place an optimization for that. However, I don't want to have some member being used to identify the mask type. I'd rather have it based on inherent data within the object, but the obvious implementation would require relatively too much time-intensive trig.

Kyon, you are aware that if Precise Collision Checking is enabled, you're doing (sprite_width*sprite_height)^i bounding-box checks against each other collision mask, which may be sprite_width*sprite_height individual boxes in size, right? That's what I hate about Game Maker's resource handling in general, there's no customization. If there was a method for adding resources and editors into the IDE, then you wouldn't have to go out of your way to make your own entirely separate collision detection system and mesh editor, and you wouldn't have to worry about messing with GMLIB for integration. With C++ this is practically forced, so I don't feel like I'm at a disadvantage or that I'm in a situation that could be corrected when I need to make my own editor.
Last edited on
Okay here's a quick screenshot of my WIP game engine: http://i51.tinypic.com/35jvuro.png


The player (and all objects that interact with the map) are represented by a 5 sided polygon.

The bottom point is the "focal point" which represents where the object is standing. The two lines at the bottom of the shape that form a 'V' represent how steep a slope the object can climb. As you can see from the picture, the player can stand on that slope just fine because the slope is at a lower incline than their 'V'. However that floor to the left of the player is too steep, and if you try to jump on it, you just slide down.

Having the map as line-based instead of the more traditional tile based actually simplifies a lot of things. In particular, you don't have to worry about complex slope collision detection, since colliding with slopes is no different from colliding with flat surfaces. And since movement is based on lines, you don't have to worry about tunnelling (moving so fast that you go through a thin wall). You can also have slopes at any angle.

Here's a diagram to help show how it works:

http://i51.tinypic.com/10i6udg.png

Starting with figure 1A: The player is the green blob and they want to move to the light blue blob.

As shown in figure 1B, lines are projected from each corner of the player to the new position. If any of these lines intersect with a wall, the player is trying to move through a wall, so you have to stop them. Whichever line intersects at a point closest to the original position (green blob) is how far the player can move before hitting the wall. This line is the dark red one in the figure.

You take this distance, subtract a little bit to give yourself some padding so you're not actually on top of the wall, and that is how far you move.

Figure 1C was supposed to show where you move to, but it's kind of a dumb picture now that I look at it.



Figure 2 shows another part. For sharp corners (or really any corners) in the walls, the above method won't work, as the projected lines won't intersect with any of the walls.

So in figure 2 I project another line from the corners of the wall in the reverse direction (towards the player). If any of these projected lines intersect with one of the player's sides, that also counts and a collision and needs to stop the player.
Last edited on
As shown in figure 1B, lines are projected from each corner of the player to the new position. If any of these lines intersect with a wall, the player is trying to move through a wall, so you have to stop them. Whichever line intersects at a point closest to the original position (green blob) is how far the player can move before hitting the wall. This line is the dark red one in the figure.
In which case, wouldn't it be entirely possible to move through a horizontal or vertical wall if you moved the right way?
Not if you also do the part illustrated in figure 2 -- by projecting lines backwards from corners/endpoints of walls and seeing if they intersect the boundaries of the player.
Line-based collision detection can be costly in larger amounts, are you sure that's entirely necessary? What would be going so fast that it would completely go through an object?
Pages: 12