The Source for Java Technology Collaboration
User: Password:



Chet Haase

Chet Haase's Blog

Java Game Development: JDJ article and code

Posted by chet on October 06, 2004 at 07:55 PM | Comments (7)

At the end of our JavaOne talk on Desktop Game Development this year, I opened my big mouth and asked who wanted to see the code we'd written to our game demo (a simple version of a well-known paddle-and-ball type game, cleverly named "Ping"). Just about the whole room raised their hands.

Dang! And I thought we were finally done with JavaOne content for the year.

We couldn't very well just post the code alone, and our presentation didn't have enough extra material to fill in the gaps. So we decided to write an article around the whole topic; Java game frameworks and issues, 2D rendering, and graphics performance tips.

Well, it took a couple of months, but Dmitri and I have finally written and published the article. It's a two-part series starting in the October issue of Java Developers Journal.. You can also check out the source code for the demo.

Part 1 is all about the game framework and related development issues. Part 2 (next month's issue) will dive into 2D rendering and performance specifics.


Bookmark blog post: del.icio.us del.icio.us Digg Digg DZone DZone Furl Furl Reddit Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment

  • interesting topic!
    in the method:
    public void syncFrameRate() {
    2: long nextFrameTime = prevFrameTime + nsPerFrame;
    3: long currTime = System.nanoTime();
    4: while (currTime < nextFrameTime) {
    5: Thread.yield();
    6: try {
    7: Thread.sleep(1);
    8: } catch (Exception e) {}
    9: currTime = System.nanoTime(};
    10: }
    11: elapsedFrameTime = currTime - prevFrameTime;
    12: prevFrameTime = currTime;
    13: }

    is the Thread.yield() call necessary? since other threads will execute while this thread is sleeping (line 7).
    I wounder too if you would get better results if the sleep call was simply:
    Thread.sleep(nextFrameTime - currTime);
    neither method is true Real Time (of course)....some testing perhaps :)

    further, I wounder if it would be better to call the methods in this order:

    //mark start time
    gatherInput();
    updateObjects();
    syncFrameRate(); <-- moved.
    render();

    in this way, the time it takes to gatherInput and updateObjects is accounted for by the sync method. Not really sure how this effects the case where gatherInput() and updateObjects() takes longer then msPerFrame...maby msPerFrame is just simply to low and should be increased in that case.

    I look forward to the next issue!
    -Lucas

    Posted by: lucasjordan on October 07, 2004 at 07:05 AM

  • oops!
    interesting topic!
    in the method:
    public void syncFrameRate() {
    2: long nextFrameTime = prevFrameTime + nsPerFrame;
    3: long currTime = System.nanoTime();
    4: while (currTime
    5: Thread.yield();
    6: try {
    7: Thread.sleep(1);
    8: } catch (Exception e) {}
    9: currTime = System.nanoTime(};
    10: }
    11: elapsedFrameTime = currTime - prevFrameTime;
    12: prevFrameTime = currTime;
    13: }

    is the Thread.yield() call necessary? since other threads
    will execute while this thread is sleeping (line 7).
    I wounder too if you would get better results if the sleep call was simply:
    Thread.sleep(nextFrameTime - currTime);
    neither method is true Real Time (of course)....some testing perhaps :)

    further, I wounder if it would be better to call the methods in thisorder:

    //mark start time
    gatherInput();
    updateObjects();
    syncFrameRate();
    render();

    in this way, the time it takes to gatherInput and updateObjects is accounted for by the sync method. Not really sure how this effects the case where gatherInput() and updateObjects() takes longer then msPerFrame...maby msPerFrame is just simply to low and should be increased in that case.

    I look forward to the next issue!
    -Lucas

    Posted by: lucasjordan on October 07, 2004 at 07:08 AM

  • I haven't tested this, but if Jerason Bane's comments on his web page are true, calling Thread.sleep(1) can screw up the Windows clock.

    To read his comments, go to:

    http://java.dnsalias.com/

    and scroll aaaall the way down to the bottom and start reading at "There's a bug in GAGETimer! It makes my CPU run at 100%!"

    I haven't actually tried this myself, so I'd like to hear comments.

    Posted by: afishionado on October 07, 2004 at 04:54 PM

  • Oops, now I'm wondering whether or not I got the poor guy's name right. Anyway, his website is http://java.dnsalias.com.

    Posted by: afishionado on October 07, 2004 at 04:56 PM


  • Hmmm. I haven't seen the artifacts he mentions (system clock drifting, CPU pegging). Simply calling sleep(1) doesn't peg the CPU itself ( just tried this out to verify). Maybe some combination of yield() contributes to this (as mentioned on that site), but I haven't seen that behavior myself.


    There is a problem with sleeping for low times in that you may not sleep for the exact time you asked for. This has varied by jdk release, but currently you should be sleeping for close to the correct value on Windows except when you ask to sleep for 10 ms, you'll actually sleep for the minimum resolution of the default system timer. On my XP system, that means you sleep for about ~16 ms instead. I filed a bug on this; check out 5091934 on the java.sun.com bug database for more info.

    Posted by: chet on October 08, 2004 at 07:23 AM

  • Very nice demo, but it crashed quickly on the computer I have at work, probably because it doesn't have a sound card, so as soon as the ball was missed, it wanted to play a sound and produced the following messages:

    Can't load sound due to: java.lang.IllegalArgumentException:
    No line matching interface Clip supporting format
    PCM_SIGNED 22050.0 Hz, 16 bit, mono, 2 bytes/frame, little-endian is supported.
    [repeated several times, ending with "PCM_UNSIGNED 22050.0 Hz, 8 bit, mono, 1 bytes/frame" (sic)]
    Followed by:

    Exception in thread "Thread-3" java.lang.NullPointerException
    at ping.SoundFactory.playClip(SoundFactory.java:116)
    at ping.SoundFactory.playPaddleHitSound(SoundFactory.java:107)
    at ping.Collider.intersect(Collider.java:215)
    at ping.Ball.processCollisions(Ball.java:126)
    at ping.DynamicGameObjects.updatePosition(DynamicGameObjects.java:75)
    at ping.Ping.run(Ping.java:142)
    at java.lang.Thread.run(Unknown Source)


    This case is probably becoming scarce nowadays, but perhaps you should handle such case more nicely...

    PS: There is a bug in the Preview page of comments, the editing part is broken (no textarea, partial HTML...).

    Posted by: philho on January 04, 2006 at 06:09 AM


  • Thanks for the bug report - I'll forward it to the right people. It would be nice if our little app handled the failure a little nicer, although I did kind of count on the audio doing its job; seems like a breakdown in java sound that should be fixed.

    I'll also forward the comment about the comments preview. I've seen a similar problem when previewing a blog posting. It's an intermittent thing where sometimes the preview is fine and sometimes the html is incomplete. I've learned the hard way to copy my text before I hit the Preview button.

    Posted by: chet on January 04, 2006 at 06:48 AM





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds