Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 835 | chris | 1 | package com.gebauz.bauzoid.game; |
| 2 | |||
| 3 | public class StateMachine<T extends Enum<T>> |
||
| 4 | { |
||
| 5 | |||
| 6 | |||
| 7 | // Constants======================================================================================== |
||
| 8 | |||
| 9 | // Embedded Types=================================================================================== |
||
| 10 | |||
| 11 | /** Event Listener interface. */ |
||
| 12 | public interface EventListener<T extends Enum<T>> |
||
| 13 | { |
||
| 14 | /** Callback for switching states. |
||
| 15 | * Called right before a state is switched. |
||
| 16 | * @param newState The new state being switched to. |
||
| 17 | * @return true to continue with the switching, or false if the switch should be aborted. |
||
| 18 | */ |
||
| 19 | public abstract boolean onSwitchState(T newState); |
||
| 20 | |||
| 21 | /** Callback for updating states. |
||
| 22 | * Called every frame. |
||
| 23 | * @param deltaTime The amount of time passed since last frame. |
||
| 24 | * @param currentState The current State being updated. |
||
| 25 | * @param stateTime The time passed in the current state. |
||
| 26 | */ |
||
| 27 | public abstract void onUpdate(float deltaTime, T currentState, float stateTime); |
||
| 28 | |||
| 29 | /** Callback for ending states. |
||
| 30 | * Is called when the state timer has reached zero. It is advised to switch to a new state here. |
||
| 31 | * @param currentState The current State being ended. |
||
| 32 | */ |
||
| 33 | public abstract void onEndState(T currentState); |
||
| 34 | } |
||
| 35 | |||
| 36 | // Fields=========================================================================================== |
||
| 37 | |||
| 38 | private EventListener<T> mEventListener; |
||
| 39 | private T mState; |
||
| 40 | private float mStateTime; |
||
| 41 | private float mTotalStateTime; |
||
| 42 | |||
| 43 | // Methods========================================================================================== |
||
| 44 | |||
| 45 | /** Constructor. |
||
| 46 | * Sets up the StateMachine object |
||
| 47 | * @param initialState The initial state the state machine should be in |
||
| 48 | * @param eventListener The event listener to register. |
||
| 49 | */ |
||
| 50 | public StateMachine(T initialState, EventListener<T> eventListener) |
||
| 51 | { |
||
| 52 | mEventListener = eventListener; |
||
| 53 | switchState(initialState); |
||
| 54 | } |
||
| 55 | |||
| 56 | /** Updates the state. |
||
| 57 | * Advances the state and state timer. Calls the event listener's onUpdate() each frame, and onEndState() when the state timer has run out. |
||
| 58 | * @param deltaTime The amount of time to advance. |
||
| 59 | */ |
||
| 60 | public void update(float deltaTime) |
||
| 61 | { |
||
| 62 | if (mEventListener != null) |
||
| 63 | mEventListener.onUpdate(deltaTime, getState(), getStateTime()); |
||
| 64 | |||
| 65 | if (mTotalStateTime > 0.0f) |
||
| 66 | { |
||
| 67 | // only check the end if a total state time is set |
||
| 68 | if (mStateTime < mTotalStateTime) |
||
| 69 | { |
||
| 70 | mStateTime += deltaTime; |
||
| 71 | if (mStateTime >= mTotalStateTime) |
||
| 72 | { |
||
| 73 | mStateTime = mTotalStateTime; |
||
| 74 | // reached the total state time -> send message to event listener |
||
| 75 | if (mEventListener != null) |
||
| 76 | mEventListener.onEndState(getState()); |
||
| 77 | } |
||
| 78 | } |
||
| 79 | } |
||
| 80 | else |
||
| 81 | { |
||
| 82 | // simply advance state time |
||
| 83 | mStateTime += deltaTime; |
||
| 84 | } |
||
| 85 | } |
||
| 86 | |||
| 87 | /** Switch the state. |
||
| 88 | * Switches the state. Calls the event listener's onSwitchState() before switching. |
||
| 89 | * @param state The state to switch to. |
||
| 90 | * @param stateTime The duration the state should be active or 0.0f if the state doesn't have a fixed end. |
||
| 91 | */ |
||
| 92 | public void switchState(T state, float stateTime) |
||
| 93 | { |
||
| 94 | if ((mEventListener != null) && (!mEventListener.onSwitchState(state))) |
||
| 95 | return; |
||
| 96 | |||
| 97 | mState = state; |
||
| 98 | mStateTime = 0.0f; |
||
| 99 | mTotalStateTime = stateTime; |
||
| 100 | } |
||
| 101 | |||
| 102 | /** Switch the state. |
||
| 103 | * Switches the state. Calls onSwitchState() before switching. The state is set to not have a fixed end. |
||
| 104 | * @param state The state to switch to. |
||
| 105 | */ |
||
| 106 | public void switchState(T state) |
||
| 107 | { |
||
| 108 | switchState(state, 0.0f); |
||
| 109 | } |
||
| 110 | |||
| 111 | |||
| 112 | // Getters/Setters================================================================================== |
||
| 113 | |||
| 114 | public final T getState() { return mState; } |
||
| 115 | public final float getStateTime() { return mStateTime; } |
||
| 116 | public final float getTotalStateTime() { return mTotalStateTime; } |
||
| 117 | |||
| 118 | /** Return a number between 0.0f and 1.0f to indicate how far we are into the state. |
||
| 119 | * If no total time is set, returns 0.0f always. |
||
| 120 | * @return A number between 0.0f and 1.0f to indicate how far we are into the state. |
||
| 121 | */ |
||
| 122 | public final float getStateTimeFactor() |
||
| 123 | { |
||
| 124 | if (getTotalStateTime() == 0.0f) |
||
| 125 | return 0.0f; |
||
| 126 | |||
| 127 | return mStateTime / getTotalStateTime(); |
||
| 128 | } |
||
| 129 | |||
| 130 | |||
| 131 | } |
||
| 132 | |||
| 133 |