Making GDI+ Nimble

One thing that the GDI+ (System.Drawing namespace in VB.Net) system is *not* is overly quick.  It does a great job of certain things required by a more general, modern OS-based drawing system -- fonts, alpha, lines & shapes, etc.  But it isn't game-graphics quick.

Mainly, it uses the CPU to do its work (as opposed to the graphics card's GPU, like DirectX and OpenGL use) ... and the CPU is already busy trying to take care of overthing else going on (memory management, math calculations, input/output routing, etc.).  So, there are some things that we'll want to keep in mind when working in the GDI for game graphics.

Read Up:  First, read up on how the GDI works.  Here's a great site for higher-level overviews and some lower-level tips and tricks: http://www.bobpowell.net/gdiplus_faq.htm ... Also, Microsoft's very own official doco page is here: http://msdn.microsoft.com/en-us/library/ms533798.aspx.  These in-depth resources will be useful when you're trying to squeeze the last couple performance drops out of the GDI.

Keep Things Compact:  One of the best things for speeding up the GDI is keeping things as small as possible while still being able to deliver the game experience you're looking for.

Play Area:  The size of the "play area" (the on-screen window used to show what's going on in the game) will have an overall effect on speed.  The bigger it is, the longer it takes to clear, the more surface area available to draw game objects too, and the longer it takes to draw the backbuffer to the screen object.  While not impossible to go 800x600 (a pretty traditional size for retro-style games) on your play area, it will simply mean that the CPU requirement for your end-users will need to be bumped up.  Doing "mini-games" at 500x500 or 640x480 (another traditional size) is very doable.

Game Object Sizes:  Similar to the impact of size on the play area, the size of your actual in-screen game object graphics will matter.  Drawing screen-sized backgrounds will have a greater impact than clearing the game screen to a solid color and drawing just a few smaller items in as the background.  Keeping items that appear in number (particles, explosions, bullets, HUD and UI items, etc.) smaller is even more important.

Game Object Counts:  Limiting the number of game objects being drawn on screen in any particular loop is an area of important balance.  You want to provide the player with a certain type of game experience.  Sometimes, this requires a lot of stuff happening on-screen at the same time.  But the "feel" of the game will be diminished if it becomes chunky and slow while all of those things are happening.  So, balancing the two (and keeping an eye on the CPU horsepower requirements) will be a good challenge for a game programmer using GDI.  One quick solution is to have a (moveable) cap on particles and other things that appear in bulk but are mainly for eye candy.  When we get into putting some particles on the screen, I'll show a "particle manager" class that handles the limiting by ditching older particles for newer ones when its at the limit.  We'll also work through how to auto-test and auto-adjust these systems to be able to give those with better computers a "thicker" experience and still allow those with slower machines to play the game in an enjoyable manner.

Testing for Gaphics Efficiency:  In a lot of cases, there may be 2 or more ways to accomplish a similar effect.  If it seems that it might be a routine that is called often enough, it would be best to find the fastest way to deliver what you're after.  What's the fastest way to draw a 2x2 solid colored square?  DrawRectangle?  FillRectangle?  DrawLine?  DrawImage (with a 2x2 bitmap)?  To be honest, I'm not really sure ... but I plan to test these things as I come across them.  I'll do some searching for other's advice and I'll run some tests similar to what Almar Joling used to do on his VBfibre site (http://www.persistentrealities.com/vbfibre).  Once I have my answer, I'll code that as my go-to routine for that effect.

Coding for Efficiency Everywhere Else:  There are typical programming things that can be done to speed up the rest of your code, freeing up extra cycles for graphics drawing (and making things smoother overall).  Avoiding type conversions or heavy calcs inside loops, etc.  These are the typical good coding practices that we should be doing anyway ... but now we have an extra reason.  (Full disclosure:  I am *not* well brushed up on good coding practices in general ... so, feel free to help me out and point our areas where I can improve ... seriously!)

Beware the Garbage Collector:  Garbage Collectors are nice, helpful and good things.  But you just don't want them to come calling mid-game-loop ... they seem to want to show up when your right in a very intense moment in the game.  When they do their thing, they steal CPU cycles away from your game and usually cause it to give a big hitch.  This can really mess with your physics and logic calcs and generally makes the game look chunk and slow, if only for a fraction of a second.  To avoid this, use a create-hold-dispose approach for objects, where the drawing objects it needs (brushes, pens, bitmaps, paths, etc.) are created when the object is first instantiated.  They're held for the life of the object, and then finally properly disposed of when the object is being destroyed.  It's also important that you are careful of when you create and destroy your game objects.  Use "manager" classes to pre-create the number of game objects you will likely need during the intense part of the game ... then release them during "between level" and other slower times in the game.

The (lack of) speed of the GDI+ system was raised in a comment on my previous post ... and it's a valid concern.  But there are advantages to using GDI+ -- mainly having to do with compatibility and ease of development and deployment.  If a fun game can be made made quickly and easily distributed to work on a lot of machines, that's a good thing.  The trick is keeping a realistic viewpoint -- we won't be creating monster games ... but it should be the perfect fit for small games.

Published Thursday, October 16, 2008 2:58 PM by MattWorden
Filed under: ,

Comments

# vbs cpu memory usage | Bookmarks URL

Pingback from  vbs cpu memory usage | Bookmarks URL

Wednesday, October 22, 2008 2:31 PM by vbs cpu memory usage | Bookmarks URL