Not logged inGosu Forums
Forum back to Help Search Register Login
Up Topic Gosu / Gosu Exchange / Advices for game performance, anyone?
- - By kuehkookies Date 2012-10-10 09:10
I wonder how to make as many objects as possible in a game_state...

I got some cases when I add several 'enemies' (it's actually only five enemies in a room) and the FPS in-game is below expectation. I testplayed the game, then as I managed to clear out the room the FPS goes back to normal. I suspected the update method which each enemy has one, but since those enemies shared the same attribute, I think there's another thing that may degrade the performance of the game itself.
Next one is the usage of tiled terrains (Chingu has this one, which is useful for me to build levels). I think that the tiles may decreases performance of the game, CMIIW.

So, is there any suggestion to make as many objects as possible without degrading the game's performance when played?

Thanks in advance.
Parent - - By Spooner Date 2012-10-10 14:04
In terms of sprites, rather than static tiles, your big issue with be Ruby code run in each #update. If you are performing collisions using Chingu; the time it takes to actually render them will be negligible. This time will get combinatorially slower, the more objects are being checked. If you have a lot of objects potentially colliding with each other, you should consider abandoning Chingu's slow collision system for something like Chipmunk. Chingu is fine if you are just checking if the player has collided with 20 world objects (floor/walls/etc) and 5 enemies (25 collision checks) but say if you have 20 objects all colliding with each other, then you have 400 potential collisions, which is incredibly slow.

Rendering tiles will be relatively slow. You should probably record the draw operation to ensure that those tiles can be rendered quickly each frame in your gamestate:

def initialize
   # #create all your dynamic sprites normally, so Chingu manages them for you.
   # Create your tiles using #new (NOT #create) and put them into @tiles
   # If Chingu creates them for you, then take them out of @game_objects and put them into
   # @tiles manually, so they won't be individually drawn.

def draw
  # Draw the static tilemap all at once and ONLY once.
  @recorded_tilemap ||= $window.record 1, 1 do
      @tiles.each &:draw
  @recorded_tilemap.draw 0, 0, 0

  # Get Chingu to draw all your dynamic sprites normally.

I find that I must pick and choose Chingu's features, since all of them are very much built for ease of use, not performance once you get past trivial games.
Parent - - By kuehkookies Date 2012-10-11 16:14
Seems it's applicable. But I still can't figure the method you posted. More over, I saw the load_game_objects method will #create everything listed in the file instead of #new.
And now, the game's frame rate itself decreased into 30 by only adding 6 mobs which walking on the ground.

Is it possible to optimize the performance when the sprites are updating? If yes, how to do it?

Thanks in advance.
Parent - - By Spooner Date 2012-10-11 16:41
"But I still can't figure the method you posted" - helps to be more specific about where you are struggling :D

All that #create does that #new doesn't is put the objects into @game_objects in the game-state. In the game-state's #initialize or #setup (whichever you use load_game_objects in), you need to pull the tiles out before you do anything else:

# do your #load_game_objects normally

# Then pull the tiles out of the game objects list (drawn individually
# every frame => SLOW)  and put them into the @tiles list (which
# will be recorded so they can be drawn as one later => FAST).
@tiles = @game_objects.grep Tile
@game_objects  -= @tiles

Now #update will not bother to update the Tiles (which are static) nor will #draw draw them individually.

As to speed when you add 6 mobs, again I point out that it depends on how many collisions you need to check. If you have 50 solid tiles for them to interact with, then that will be 300 collision checks (SLOW). You really need to explain your system (e.g. "I have one player object, which collides with 50 tiles and 6 mobs. I have 6 mobs which collide with the player and 50 tiles") AND show me what code you are using to check those collisions before I can reasonably help you optimise either the code or the system you are trying to develop. It might be that what you want is impossible to do at a reasonable speed in Ruby or it might just be that it is impossible in Chingu's high-level system or only impossible the way you are implementing it it!
Parent - - By kuehkookies Date 2012-10-12 14:57
Sorry for my latest response. I felt bad after stressed out myself. Sorry :(

By the way, last night I tried again and after reading your explanation several times, the frame rate boosted to approx. 50-55. You're right, I didn't struggle enough :D

Once again, I'm sorry, and thanks in advance :D
Parent - - By pete_mw Date 2012-10-14 11:53 Edited 2012-10-14 13:14
If you want to improve this further, a popular optimisation is to use a data structure such as a spatial hash or a quadtree. Both work by using the object's position to determine where it's stored, which allows you to quickly identify objects that are quite close together and avoid running collision checks on things that are quite far apart. This is a fairly good tutorial on spatial hashing.

I'm not proficient enough with Chingu to tell you how to integrate this sort of thing into your project, however. You might end up having to skip Chingu's collision-detection features altogether and roll your own instead.
Parent - - By RavensKrag Date 2012-10-14 14:34
This is what Chipmunk is for.

I believe implementing any system of this sort at the ruby level will probably be too slow for a game which requires that level of complexity in collisions. Chipmunk is written in C for speed, but has a nice ruby extension :D

Only downside is that it's based on Chipmunk 5, not the new version 6.
Parent - - By Spooner Date 2012-10-14 15:02
I'm with RavensKrag on this - collisions in Ruby, even if optimised, are never going to approach the speed of a dedicated C library (and "don't roll your own if it already exists" is a good motto). If you just use Chipmunk for collisions (that is, make all shapes into sensors) you can still manage your physics yourself in Ruby when they are detected, so it doesn't play like a "bouncy physics game".
Parent - - By pete_mw Date 2012-10-14 15:30 Edited 2012-10-14 16:11
It can be good advice to use libraries where they exist, sure. Chipmunk is a perfectly valid option here.

That said, unless you're doing something very extreme, I don't think it's that likely that doing this Ruby-side is going to impact play.
Parent - By kuehkookies Date 2012-10-15 03:18
Seems like Chipmunk worth a try for this issue. And right, even the collisions are optimized, it's still can't be as fast as those written in C.
Thanks for your share, guys!
Parent - - By erisdiscord Date 2012-10-16 20:57
Using Chipmunk also means you don't have to write your own spatial hash implementation, though. C:
Parent - By RavensKrag Date 2012-10-19 20:05
Though I believe Chipmunk 6 uses quadtrees by default. Doesn't really affect Ruby devs, but it's good to keep in mind.

There is an option to use the spatial hash like in Chipmunk 5 though.  I think the C guys complained that the hash was too hard to optimize.
Up Topic Gosu / Gosu Exchange / Advices for game performance, anyone?

Powered by mwForum 2.29.7 © 1999-2015 Markus Wichitill