Subversion Repositories AndroidProjects

Rev

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();
        }
       
       
}