Commit 86cba188 authored by Terence Martin's avatar Terence Martin

Enhance state machine

In order to handle some upcoming timing changes, make the state
machine aware of how long it has been in the current state so that we
can check it, knowing when to transition to another state or perform
an event at a set interval.
parent 1fffad2a
......@@ -1731,6 +1731,8 @@ var nurdz;
// Set the current and previous states.
this._currentState = GameState.NO_STATE;
this._previousState = GameState.NO_STATE;
// Default our tick value.
this._ticksInState = 0;
// Create the listener array.
this._listeners = new Array();
}
......@@ -1754,6 +1756,8 @@ var nurdz;
// Save the current state, then switch it.
this._previousState = this._currentState;
this._currentState = newState;
// Reset the number of ticks that have happened in this state.
this._ticksInState = 0;
// Trigger listeners.
for (var i = 0; i < this._listeners.length; i++)
this._listeners[i].stateChanged(this, this._currentState);
......@@ -1778,6 +1782,52 @@ var nurdz;
enumerable: true,
configurable: true
});
/**
* This is invoked once per update loop while this scene is the active
* scene
*
* @param {number} tick the game tick; this is a count of how many times
* the game loop has executed
*/
StateMachine.prototype.update = function (tick) {
// Count this as an elapsed tick.
this._ticksInState++;
};
/**
* Check to see if the machine has been in the current state for at
* least the number of ticks provided, returning a boolean that
* indicates if this is the case.
*
* This is not meant to be used as a timer that you check multiple times,
* as once the tick count hit has elapsed, this will continue to return
* true.
*
* @param {number} tickCount the tick count to check
*
* @returns {boolean} true if at least this many ticks have
* elapsed, or false otherwise.
*/
StateMachine.prototype.hasElapsed = function (tickCount) {
return this._ticksInState >= tickCount;
};
/**
* Check to see if a timer that triggers on a multiple of the number of
* ticks given has triggered or not. Unlike hasElapsed(), this can be
* used for a recurring timer.
*
* In order to use this effectively this needs to be checked on every
* frame update; if you skip a check during a frame you run the risk of
* missing the tick that causes the timer to fire.
*
* @param {number} tickMultiple the multiple of the tick to trigger
* for, e.g. 30 triggers once a second
*
* @returns {boolean} true if the timer triggers during
* this tick or false otherwise
*/
StateMachine.prototype.timerTrigger = function (tickMultiple) {
return this._ticksInState % tickMultiple == 0;
};
/**
* Add the given object to the list of objects that get informed
* whenever the state of this machine changes.
......
......@@ -114,6 +114,13 @@ module nurdz.game
*/
private _listeners : Array<StateMachineChangeListener>;
/**
* The number of ticks that have elapsed since the state machine was
* switched into the current state. This gets updated when our update
* method is invoked and reset when our state changes.
*/
private _ticksInState : number;
/**
* Get the current state of this state machine.
*
......@@ -138,6 +145,9 @@ module nurdz.game
this._previousState = this._currentState;
this._currentState = newState;
// Reset the number of ticks that have happened in this state.
this._ticksInState = 0;
// Trigger listeners.
for (let i = 0 ; i < this._listeners.length ; i++)
this._listeners[i].stateChanged (this, this._currentState);
......@@ -167,10 +177,65 @@ module nurdz.game
this._currentState = GameState.NO_STATE;
this._previousState = GameState.NO_STATE;
// Default our tick value.
this._ticksInState = 0;
// Create the listener array.
this._listeners = new Array<StateMachineChangeListener> ();
}
/**
* This is invoked once per update loop while this scene is the active
* scene
*
* @param {number} tick the game tick; this is a count of how many times
* the game loop has executed
*/
update (tick : number) : void
{
// Count this as an elapsed tick.
this._ticksInState++;
}
/**
* Check to see if the machine has been in the current state for at
* least the number of ticks provided, returning a boolean that
* indicates if this is the case.
*
* This is not meant to be used as a timer that you check multiple times,
* as once the tick count hit has elapsed, this will continue to return
* true.
*
* @param {number} tickCount the tick count to check
*
* @returns {boolean} true if at least this many ticks have
* elapsed, or false otherwise.
*/
hasElapsed (tickCount : number) : boolean
{
return this._ticksInState >= tickCount;
}
/**
* Check to see if a timer that triggers on a multiple of the number of
* ticks given has triggered or not. Unlike hasElapsed(), this can be
* used for a recurring timer.
*
* In order to use this effectively this needs to be checked on every
* frame update; if you skip a check during a frame you run the risk of
* missing the tick that causes the timer to fire.
*
* @param {number} tickMultiple the multiple of the tick to trigger
* for, e.g. 30 triggers once a second
*
* @returns {boolean} true if the timer triggers during
* this tick or false otherwise
*/
timerTrigger (tickMultiple : number) : boolean
{
return this._ticksInState % tickMultiple == 0;
}
/**
* Add the given object to the list of objects that get informed
* whenever the state of this machine changes.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment