Blame |
Last modification |
View Log
| RSS feed
package com.gebauz.bauzoid.game;
public class StateMachine
<T
extends Enum<T
>>
{
// Constants========================================================================================
// Embedded Types===================================================================================
/** Event Listener interface. */
public interface EventListener<T
extends Enum<T
>>
{
/** Callback for switching states.
* Called right before a state is switched.
* @param newState The new state being switched to.
* @return true to continue with the switching, or false if the switch should be aborted.
*/
public abstract boolean onSwitchState
(T newState
);
/** Callback for updating states.
* Called every frame.
* @param deltaTime The amount of time passed since last frame.
* @param currentState The current State being updated.
* @param stateTime The time passed in the current state.
*/
public abstract void onUpdate
(float deltaTime, T currentState,
float stateTime
);
/** Callback for ending states.
* Is called when the state timer has reached zero. It is advised to switch to a new state here.
* @param currentState The current State being ended.
*/
public abstract void onEndState
(T currentState
);
}
// Fields===========================================================================================
private EventListener<T
> mEventListener
;
private T mState
;
private float mStateTime
;
private float mTotalStateTime
;
// Methods==========================================================================================
/** Constructor.
* Sets up the StateMachine object
* @param initialState The initial state the state machine should be in
* @param eventListener The event listener to register.
*/
public StateMachine
(T initialState,
EventListener<T
> eventListener
)
{
mEventListener = eventListener
;
switchState
(initialState
);
}
/** Updates the state.
* Advances the state and state timer. Calls the event listener's onUpdate() each frame, and onEndState() when the state timer has run out.
* @param deltaTime The amount of time to advance.
*/
public void update
(float deltaTime
)
{
if (mEventListener
!=
null)
mEventListener.
onUpdate(deltaTime, getState
(), getStateTime
());
if (mTotalStateTime
> 0.0f
)
{
// only check the end if a total state time is set
if (mStateTime
< mTotalStateTime
)
{
mStateTime += deltaTime
;
if (mStateTime
>= mTotalStateTime
)
{
mStateTime = mTotalStateTime
;
// reached the total state time -> send message to event listener
if (mEventListener
!=
null)
mEventListener.
onEndState(getState
());
}
}
}
else
{
// simply advance state time
mStateTime += deltaTime
;
}
}
/** Switch the state.
* Switches the state. Calls the event listener's onSwitchState() before switching.
* @param state The state to switch to.
* @param stateTime The duration the state should be active or 0.0f if the state doesn't have a fixed end.
*/
public void switchState
(T state,
float stateTime
)
{
if ((mEventListener
!=
null) && (!mEventListener.
onSwitchState(state
)))
return;
mState = state
;
mStateTime = 0.0f
;
mTotalStateTime = stateTime
;
}
/** Switch the state.
* Switches the state. Calls onSwitchState() before switching. The state is set to not have a fixed end.
* @param state The state to switch to.
*/
public void switchState
(T state
)
{
switchState
(state, 0.0f
);
}
// Getters/Setters==================================================================================
public final T getState
() { return mState
; }
public final float getStateTime
() { return mStateTime
; }
public final float getTotalStateTime
() { return mTotalStateTime
; }
/** Return a number between 0.0f and 1.0f to indicate how far we are into the state.
* If no total time is set, returns 0.0f always.
* @return A number between 0.0f and 1.0f to indicate how far we are into the state.
*/
public final float getStateTimeFactor
()
{
if (getTotalStateTime
() == 0.0f
)
return 0.0f
;
return mStateTime / getTotalStateTime
();
}
}