Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon

20. November 2011

 

 

Handling game time is problem that almost all games have to deal with.  A very good question recently came up in my C++ game from scratch tutorial about why I didn’t normalize the players movements which reminded me of a post on the subject.

 

 

Years ago Shawn Hargreaves of XNA ( and Allegro ) fame blogged about how XNA handles the Update and Render loops.  I simply post it here again because it is one of the most succinct posts I have encountered on the subject.  So, if you are looking into creating a game and need to figure out how to implement the game loop, I recommend you give it a read.

 

By default XNA runs in fixed timestep mode, with a TargetElapsedTime of 60 frames per second. This provides a simple guarantee:

  • We will call your Update method exactly 60 times per second
  • We will call your Draw method whenever we feel like it

 

Digging into exactly what that means, you will realize there are several possible scenarios depending on how long your Update and Draw methods take to execute.

 

The simplest situation is that the total time you spend in Update + Draw is exactly 1/60 of a second. In this case we will call Update, then call Draw, then look at the clock and notice it is time for another Update, then Draw, and so on. Simple!

 

What if your Update + Draw takes less than 1/60 of a second? Also simple. Here we call Update, then call Draw, then look at the clock, notice we have some time left over, so wait around twiddling our thumbs until it is time to call Update again.

 

What if Update + Draw takes longer than 1/60 of a second? This is where things get complicated. There are many reasons why this could happen:

 

  1. The computer might be slightly too slow to run the game at the desired speed.
  2. Or the computer might be way too slow to run the game at the desired speed!
  3. The computer might be basically fast enough, but this particular frame might have taken an unusually long time for some reason. Perhaps there were too many explosions on screen, or the game had to load a new texture, or there was a garbage collection.
  4. You could have paused the program in the debugger.

 

We do the same thing in response to all four causes of slowness:

  • Set GameTime.IsRunningSlowly to true.
  • Call Update extra times (without calling Draw) until we catch up.
  • If things are getting ridiculous and we are too far behind, we just give up.

If you think about how this algorithm deals with the four possible causes of slowdown I listed above, you'll see it handles them all rather well:

  1. Even if the computer is too slow to run Update + Draw inside a single frame, chances are that Update + Update + Draw will fit into two frames. The game may look a little jerky, but it will still play correctly. If the programmer is particularly smart they might even notice that we set IsRunningSlowly, and automatically reduce detail or turn off special effects to speed things up.
  2. If the computer is way too slow (ie. if the Update method alone is too slow to fit into a single frame) there isn't really much we can do, other than set IsRunningSlowly, cross our fingers, and hope the game might do something clever in response to that. Most of the time, though, if you find yourself in this situation you just need a faster computer!
  3. If a particular frame happens to take unusually long, we automatically call Update some extra times to catch up, after which everything carries on as normal. The player may notice a slight glitch, but we automatically correct for this to minimize the impact.
  4. Pausing in the debugger will leave the game a long way behind where the clock says it should be, so our algorithm will give up, accept that it has lost some time, and continue running smoothly from the time execution was resumed.

 

 

Shawn’s blog in general is a very good read, but this this post in particular is one that I seem to keep coming back to.

 

For the record, Pang from the C++ tutorial does not gracefully handle hitting a breakpoint ( it adds a layer of unwanted complexity for learning purposes ), so will do downright stupid things when it hits a breakpoint causing it to pause for a while.  I believe on the next frame it will cause your movement to be really really really far.  It would be as simple as adding if(elapsedTime > someReallyBigValue) startTimeOver() if you really wanted to fix this.

 

 

Sorry for digging up the past, now back to your regular broadcast!

Programming , ,

15. November 2011

 

 

Eclipse has this annoying habit of using the JRE instead of a JDK you have installed.  It isn’t immediately obvious what is happening until you attempt to build a project.  For example, I just move some PlayN source to a new laptop and when I try to compile I get:

 

[ERROR] Failed to execute goal on project tictactoe: Could not resolve dependencies for project com.gamefromscratch:tictactoe:pom:0.0.1-SNAPSHOT: Could not find artifact com.sun:tools:jar:1.6 at specified path C:\Program Files (x86)\Java\jre6\..\lib\tools.jar -> [Help 1]
[ERROR]

 

Which can be a bit of a head scratcher if you haven’t been bit by it before, but there error is exactly right, the JRE unlike the JDK doesn’t have everything installed, including the aforementioned tools.jar.  Fortunately the fix is quite simple.

 

 

 

In Eclipse, select the Window menu->Preferences.  Then select Java->Installed JRE’s.  Then click Add… select Standard VM then click Next.  In the JRE home, navigate to the folder you’ve installed the JDK to ( c:\Program Files\Java\jdk1.6.0_21\ in my case ).  It will now churn away for a while.  After a few seconds, it should look like this:

 

 

image

 

 

Now click Finish.

 

This will bring you back to the installed JRE’s window, unclick the JRE and click your newly added JDK, like this:

 

image

 

 

And voila!  you are now configured to properly use the JDK instead of the JRE in Eclipse.  So if you run into the error saying tools.jar is missing and you are using Eclipse, this is probably the problem.

 

 

If you launch Eclipse from the command line or via a shortcut, you can also set this value using the –vm command line setting, simply type:

 

eclipse.exe –vm c:\path\to\jdk\bin\javaw.exe

General

14. November 2011

 

Chapter 8 of the GFS beginner C++ tutorial, Pang! is now live and can be accessed here.

 

 

This chapter represents a bit of a break from the norm, in that it deals with code design more than it does actual SFML and game implementation.  I actually had a great deal of fun writing this chapter, but the end result is very little usable code.  There is a companion post to this one that illustrates much better use of SFML’s audio classes, that should be up shortly.  That said, I think you could learn a great  deal from this post, it may even alter the way you program!

 

 

Instead this post introduces the concept of design patterns and illustrates a way to de-couple  your code, so you don’t end up littered with global and manager classes.  It covers a concept that I have never seen covered by a game tutorial before, but then, there might be a good reason for that! Winking smile

 

 

So give it a read and let me know what you think.  Would you like to see more posts like this, or would you like me to focus on more implementation specific aspects?

Programming ,

12. November 2011

 

The new update should make the install process even easier. The process still works the same, just now with less annoying warnings and work around required.  Also, the Java (target) has been split out as an individual sub-project, a move which makes lots of sense.  I would describe why, but frankly the original author Michael Bayne did a good job already.

Howdy everyone,

I just released PlayN 1.0.1 to Maven Central (and the mirroring to the
public servers is complete).

This release corrects a bunch of pesky errors relating to building
PlayN that crept into the 1.0 release in the eleventh hour.

It should now be possible to import the PlayN sample projects and to
create a new PlayN project using the Maven Archetype without
encountering a single error or mysterious weirdness in Eclipse. I
would have liked to be able to say "warning or error," but annoyingly
my Eclipse complains that certain XML files lack a DTD specification,
which seems excessively anal to me, but that's how they like to roll
over there at Eclipse HQ.

One other important change was introduced in this release. The PlayN
archetype now generates a separate "java" submodule which contains the
Java backend entry point file (FooGameJava) and which has a dependency
on playn-java. The core submodule now only depends on playn-core.

Prior to this change, the core submodule depended on playn-java (and
by transitivity playn-core) and the Java entry point was in the core
submodule. This eventually causes problems, because all of the other
submodules (html, android) depend on the core submodule, and if one
added some Java-only dependency to their code submodule so that they
could use it when testing with the Java backend, it would show up in
the html and android submodules and cause problems. Now the core
submodule can remain "pure" with only PlayN-safe dependencies, and if
you need additional dependencies for your Java backend, you add them
to the java submodule where they won't cause problems with the other
submodules.

Because the Java entry point is in a separate project, it is now
necessary to test the Java backend via Maven in a different way.
Instead of "mvn compile exec:java" in the core submodule directory,
one now invokes "mvn test -Ptest-java" in the top-level project
directory. This is more consistent with the way the HTML backend
works, so that's nice. It's also unfortunately a little slower, and
when you're rapidly edit/compile/debugging, every millisecond counts.
The "ant run-java" target still works great in this new setup, and
remains very fast, so I recommend that command line users use that to
iteratively build and test their project. Eclipse users will now "Run
As -> Java Application" on the mygame-java project instead of the
mygame-core project, but otherwise everything is the same.

Due to current-working-directory related issues exacerbated by the
creation of the java submodule, I rewrote the Java asset manager to
load assets from the classpath (robust) instead of loading them
directly from the file system (fragile). This means that you'll need
to make a change to your Java entry point. Where you probably had
something like:

    platform.assetManager().setPathPrefix("src/main/java/playn/showcase/resourc es");

you should now use:

    platform.assetManager().setPathPrefix("playn/showcase/resources");

As a fringe benefit, this was one of the main challenges preventing
the packaging of the Java backend up for use as a Java applet. Now
that this has been fixed, there are probably only a few niggling bits
that need fixing, and PlayN games can be deployed as Java applets by
anyone crazy enough to want to do so. :)

Also, for those of you using sound in your games, the Java backend
used to require that you maintain separate .wav versions of your sound
resources. The HTML backend used .mp3 versions of said resources. The
Java version has been updated so that it uses the .mp3 versions as
well, so you no longer need to maintain .wav versions of your sounds.
Sounds on the Android backend remain largely untested (meaning they're
probably broken), but when I get a chance, I'll make sure that they
also work properly with .mp3 files, so that things remain consistent
across platforms.

Between these and other small improvements to the archetype, it is
probably worth the small bit of trouble to regenerate your project
from the latest archetype, and move your sources and resources into
the new project, just to be sure that all the little fixes that have
made it into the archetype templates are applied to your project.
Alternatively, you could generate a new project using the latest
archetype with specifications equivalent to your project and then diff
the files that were generated against those in your project and
migrate any fixes you find into your project. Whether one or the other
is easier will depend on how much you've customized your poms.

The flash submodule has been completely disabled in the latest
archetype. If the Flash backend is made functional again, it will be
reinstated.

 

The other key things to note is the removal of the Flash target ( which was apparently quite a ways from ready for prime time, and was breaking the build ).  Anyways, good job to the PlayN team.

Programming ,

9. November 2011

 

According to ZDNet Adobe just took Flash for mobile out to the pasture and put a bullet in it.

 

Our future work with Flash on mobile devices will be focused on enabling Flash developers to package native apps with Adobe AIR for all the major app stores. We will no longer adapt Flash Player for mobile devices to new browser, OS version or device configurations. Some of our source code licensees may opt to continue working on and releasing their own implementations. We will continue to support the current Android and PlayBook configurations with critical bug fixes and security updates.

 

I am no fan of Flash, but frankly HTML5 isn’t even close to be a valid replacement yet.  This move seems ill advised at best and downright stupid at worst.  I know hands down my Asus Transformer tablet gets far more usage than my iPad simply because it supports Flash.  If there was a valid rich media alternative to products like Flash and Silverlight, I would be all over it, but that technology sure as heck isn’t HTML5!

 

 

I don’t really have any stakes in this game at all, but I do think it was an ill advised play by Adobe.  So they are basically going to become a pure tools provider going forward?  This is a bit odd, as I’ve understood it, AIR was a bit of a flop?  Regardless, a move focusing more on AIR and away from Flash, is a move into being fully a development tool provider and out of being a platform provider.  One of the biggest sales bullets for desktop flash, it’s ubiquity, just went away.

Totally Off Topic

Month List

Popular Comments