Jump to content

Event Register-able Clock Object JS / Am I re-inventing the wheel here?


63
 Share

Recommended Posts

Hello, 

Very new to game dev. New, as in this is the first thing I've written.

Basically the code below is a simple in-game clock, where you can set how many real seconds is in each game hour, you can define how many game hours in a game day, etc. On the object you should be able to register hourly and daily events, that's about all I think I need to be able to do atm, though I'm afraid I will have to keep coming back to this class and refine it as I realize new functionalities it has to accommodate. Basically what I want to do is to have player stats and other NPC stats update on an in-game hourly basis, and world/scene stats and chances re-roll on a daily basis.

I'm just wondering if I'm reinventing the wheel here and shouldn't be bothering with this low-level stuff, and if yes where can I find a more robust library I can rely on. I did give it a good day of looking and didn't find anything making me think that I probably shouldn't really be making a clock, and that this is something that should be handled by some other interval/beat related object.

// usage example: where 1 real second = 1 game hour
// says "did it" every game hour, i.e. every real second
/*
var clock = new Clock();
clock.onHourPass({
  name: 'dothat',
  fn: function(args){
    console.log('did it');
  }
});
clock.start();
*/

function Clock(args) {
  var self = this;
  args = args || {};
  self.realSecondsInGameHour = args.gameHour || 1;
  self.gameMinutesInGameHour = args.gameMinutesInGameHour || 4;
  self.gameHoursInGameDay = args.gameHoursInGameDay || 15;
  self.gameDay = self.realSecondsInGameHour * self.gameHoursInGameDay;
  self.hourlyEvents = {};
  self.dailyEvents = {};
  self.interval;
  self._hour;

  this.onHourPass = function(args) {
    self.hourlyEvents[args.name] = args.fn;
  }

  this.onDayPass = function(args) {
    self.dailyEvents[args.name] = args.fn;
  }

  this._triggerHourlyEvents = function(){
    var events = Object.keys(self.hourlyEvents);
    events.forEach(function(e){
      self.hourlyEvents[e](self);
    });
  }

  this._triggerDailyEvents = function(){
    var events = Object.keys(self.dailyEvents);
    events.forEach(function(e){
      self.dailyEvents[e](self);
    });
  }

  this.start = function() {
    self._hour = 0;
    self._minute = 0;
    console.log('clock interval start');
    self.interval = window.setInterval(function(){
      self._minute++;
      self._hour = self._minute / self.gameMinutesInGameHour;

      if(self._minute % self.gameMinutesInGameHour == 0) {
        self._triggerHourlyEvents();
      }

      if(self._hour == self.gameHoursInGameDay) {
        self._triggerDailyEvents();
        self.end();
      }
    }, (self.realSecondsInGameHour/self.gameMinutesInGameHour) * 1000);
  }

  this.end = function() {
    console.log('clock day ended in ' + self._hour + ' hours');
    window.clearInterval(self.interval);
  }
}

Also here: https://gist.github.com/anonymous/ab675299b50d5f34adc1

Link to comment
Share on other sites

Looks about right, there are plenty of improvements/changes you could make, but not related to the core concept i.e. create a tick set to an arbitrary interval and mutate the time passed into 'game time'; sounds like a good plan.

A quick note though, JS timing isn't particularly accurate and whilst people often advocate using setTimeout (i.e. call a function that then uses setTimeout to call that function again in the future) it wont help here, your clock will get out of sync with 'real-life' if it runs for any length of time. The only way around that is to create a tick and then get the browser to query system time using Date.now() or performance.now() and then work out the difference between the current time and the last time. Of course, if absolute precision is not necessary, and/or you restart the process every so often, your solution is fine.

There are a fair number of modules that deal with this sort of thing. You can use npm to search for modules but many modules on npm (particularly for timing) would require a commonJS build system (i.e. webpack, browserify etc etc) which you may not be using. Bower is another repository of modules, it is aimed more at front-end so most of the modules you'll find there should have versions to 'just use' in the browser (usually that means polluting global, but, without knowing your setup that is probably fine). NPM will give you better quality modules but its probably useless to you if you aren't doing the commonJS step.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...