Thursday, February 14, 2013

Countdown to Awesome Games

‹prev | My Chain | next›

I had me a good old time building a scoreboard for kids to use in some of the 3D Game Programming for Kids chapters. I am doing this as a possible way to avoid teaching kids about DOM programming (and thus scaring them off from programming forever). But I have to admit—I had a good time whipping the scoreboard up. I also think that it could prove pretty useful for kids. Having slept on it, I think that the scoreboard could use a countdown timer in addition to the regular elapsed time timer.

Specifically, I can see it being pretty darn handy in the multi-level game that I whipped up recently. Each of the levels can be timed and I can use callbacks to decide what happens when time expires on any given level. For this to work, the countdown will need to support that time-expired callback as well as a way to reset the countdown when new levels of the game are reached.

My attempt at doing this involves subclassing last night's Timer class:
function __Countdown(options) {
  this.start = (new Date).getTime();
  this.length = options.length || 10;
  this.waitForTimeExpired();
}

__Countdown.prototype = new __Timer();
This gives me access to the methods that covert time to a printable string. In addition to needing a new waitForTimeExpired() method that will call the necessary callbacks, I have to override the diff() method from the sequential timer:
__Countdown.prototype.diff = function() {
  var now = this.last(),
      diff = now - this.start;

  if (diff > this.length * 1000) return 0;
  return this.length * 1000 - diff;
};
In this case, I do not want to print the different between the start time and the current time. Rather I want to print the difference between the elapsed time and the duration of this timer.

The new waitForTimeExpired() method is just a simple timeout:
__Timer.prototype.waitForTimeExpired = function() {
  var that = this;

  function _wait() {
    if (that.diff() > 0) return setTimeout(_wait, 500);
    that.stop();
    return that.onTimeExpired(that.toString());
  }
  _wait();
};
I add the countdown timer to yesterday's Scoreboard class so that I can display it with a boolean option:
  var scoreboard = new Scoreboard({
    showTimer: true,
    showCountdown: true,
    message: "Get the green ring. " +
             "Click and drag blue ramps. " +
             "Click and R to rotate. " +
             "Left and right arrows to move player. " +
             "Be quick!"
  });
  scoreboard.show();
Lastly, I add a reset method so that I can reset the time in between levels:
  var current_level = 0;
  function drawCurrentLevel() {
    scoreboard.resetCountdown(50 - current_level * 10);
    var obstacles = levels[current_level];
    obstacles.forEach(function(obstacle) {
      scene.add(obstacle);
    });      
  }
That seems to do the trick.



I still have a few kinks to work out—mostly in the API. With an elapsed timer, a countdown timer, a message, and a score tracker, the scoreboard class has gotten complicated. Especially the constructor. Still, this seems a promising thing to be able to include in the book.


Day #662

No comments:

Post a Comment