Path: blob/master/SLICK_HOME/src/org/newdawn/slick/state/StateBasedGame.java
1457 views
package org.newdawn.slick.state;12import java.util.HashMap;3import java.util.Iterator;45import org.newdawn.slick.Game;6import org.newdawn.slick.GameContainer;7import org.newdawn.slick.Graphics;8import org.newdawn.slick.Input;9import org.newdawn.slick.InputListener;10import org.newdawn.slick.SlickException;11import org.newdawn.slick.state.transition.EmptyTransition;12import org.newdawn.slick.state.transition.Transition;1314/**15* A state based game isolated different stages of the game (menu, ingame, hiscores, etc) into16* different states so they can be easily managed and maintained.17*18* @author kevin19*/20public abstract class StateBasedGame implements Game, InputListener {21/** The list of states making up this game */22private HashMap states = new HashMap();23/** The current state */24private GameState currentState;25/** The next state we're moving into */26private GameState nextState;27/** The container holding this game */28private GameContainer container;29/** The title of the game */30private String title;3132/** The transition being used to enter the state */33private Transition enterTransition;34/** The transition being used to leave the state */35private Transition leaveTransition;3637/**38* Create a new state based game39*40* @param name The name of the game41*/42public StateBasedGame(String name) {43this.title = name;4445currentState = new BasicGameState() {46public int getID() {47return -1;48}49public void init(GameContainer container, StateBasedGame game) throws SlickException {50}51public void render(StateBasedGame game, Graphics g) throws SlickException {52}53public void update(GameContainer container, StateBasedGame game, int delta) throws SlickException {54}55public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {56}57};58}5960/**61* @see org.newdawn.slick.ControlledInputReciever#inputStarted()62*/63public void inputStarted() {6465}6667/**68* Get the number of states that have been added to this game69*70* @return The number of states that have been added to this game71*/72public int getStateCount() {73return states.keySet().size();74}7576/**77* Get the ID of the state the game is currently in78*79* @return The ID of the state the game is currently in80*/81public int getCurrentStateID() {82return currentState.getID();83}8485/**86* Get the state the game is currently in87*88* @return The state the game is currently in89*/90public GameState getCurrentState() {91return currentState;92}9394/**95* @see org.newdawn.slick.InputListener#setInput(org.newdawn.slick.Input)96*/97public void setInput(Input input) {98}99100/**101* Add a state to the game. The state will be updated and maintained102* by the game103*104* @param state The state to be added105*/106public void addState(GameState state) {107states.put(new Integer(state.getID()), state);108109if (currentState.getID() == -1) {110currentState = state;111}112}113114/**115* Get a state based on it's identifier116*117* @param id The ID of the state to retrieve118* @return The state requested or null if no state with the specified ID exists119*/120public GameState getState(int id) {121return (GameState) states.get(new Integer(id));122}123124/**125* Enter a particular game state with no transition126*127* @param id The ID of the state to enter128*/129public void enterState(int id) {130enterState(id, new EmptyTransition(), new EmptyTransition());131}132133/**134* Enter a particular game state with the transitions provided135*136* @param id The ID of the state to enter137* @param leave The transition to use when leaving the current state138* @param enter The transition to use when entering the new state139*/140public void enterState(int id, Transition leave, Transition enter) {141if (leave == null) {142leave = new EmptyTransition();143}144if (enter == null) {145enter = new EmptyTransition();146}147leaveTransition = leave;148enterTransition = enter;149150nextState = getState(id);151if (nextState == null) {152throw new RuntimeException("No game state registered with the ID: "+id);153}154155leaveTransition.init(currentState, nextState);156}157158/**159* @see org.newdawn.slick.BasicGame#init(org.newdawn.slick.GameContainer)160*/161public final void init(GameContainer container) throws SlickException {162this.container = container;163initStatesList(container);164165Iterator gameStates = states.values().iterator();166167while (gameStates.hasNext()) {168GameState state = (GameState) gameStates.next();169170state.init(container, this);171}172173if (currentState != null) {174currentState.enter(container, this);175}176}177178/**179* Initialise the list of states making up this game180*181* @param container The container holding the game182* @throws SlickException Indicates a failure to initialise the state based game resources183*/184public abstract void initStatesList(GameContainer container) throws SlickException;185186/**187* @see org.newdawn.slick.Game#render(org.newdawn.slick.GameContainer, org.newdawn.slick.Graphics)188*/189public final void render(GameContainer container, Graphics g) throws SlickException {190preRenderState(container, g);191192if (leaveTransition != null) {193leaveTransition.preRender(this, container, g);194} else if (enterTransition != null) {195enterTransition.preRender(this, container, g);196}197198currentState.render(container, this, g);199200if (leaveTransition != null) {201leaveTransition.postRender(this, container, g);202} else if (enterTransition != null) {203enterTransition.postRender(this, container, g);204}205206postRenderState(container, g);207}208209/**210* User hook for rendering at the before the current state211* and/or transition have been rendered212*213* @param container The container in which the game is hosted214* @param g The graphics context on which to draw215* @throws SlickException Indicates a failure within render216*/217protected void preRenderState(GameContainer container, Graphics g) throws SlickException {218// NO-OP219}220221/**222* User hook for rendering at the game level after the current state223* and/or transition have been rendered224*225* @param container The container in which the game is hosted226* @param g The graphics context on which to draw227* @throws SlickException Indicates a failure within render228*/229protected void postRenderState(GameContainer container, Graphics g) throws SlickException {230// NO-OP231}232233/**234* @see org.newdawn.slick.BasicGame#update(org.newdawn.slick.GameContainer, int)235*/236public final void update(GameContainer container, int delta) throws SlickException {237preUpdateState(container, delta);238239if (leaveTransition != null) {240leaveTransition.update(this, container, delta);241if (leaveTransition.isComplete()) {242currentState.leave(container, this);243GameState prevState = currentState;244currentState = nextState;245nextState = null;246leaveTransition = null;247if (enterTransition == null) {248currentState.enter(container, this);249} else {250enterTransition.init(currentState, prevState);251}252} else {253return;254}255}256257if (enterTransition != null) {258enterTransition.update(this, container, delta);259if (enterTransition.isComplete()) {260currentState.enter(container, this);261enterTransition = null;262} else {263return;264}265}266267currentState.update(container, this, delta);268269postUpdateState(container, delta);270}271272/**273* User hook for updating at the game before the current state274* and/or transition have been updated275*276* @param container The container in which the game is hosted277* @param delta The amount of time in milliseconds since last update278* @throws SlickException Indicates a failure within render279*/280protected void preUpdateState(GameContainer container, int delta) throws SlickException {281// NO-OP282}283284/**285* User hook for rendering at the game level after the current state286* and/or transition have been updated287*288* @param container The container in which the game is hosted289* @param delta The amount of time in milliseconds since last update290* @throws SlickException Indicates a failure within render291*/292protected void postUpdateState(GameContainer container, int delta) throws SlickException {293// NO-OP294}295296/**297* Check if the game is transitioning between states298*299* @return True if we're transitioning between states300*/301private boolean transitioning() {302return (leaveTransition != null) || (enterTransition != null);303}304305/**306* @see org.newdawn.slick.Game#closeRequested()307*/308public boolean closeRequested() {309return true;310}311312/**313* @see org.newdawn.slick.Game#getTitle()314*/315public String getTitle() {316return title;317}318319/**320* Get the container holding this game321*322* @return The game container holding this game323*/324public GameContainer getContainer() {325return container;326}327328/**329* @see org.newdawn.slick.InputListener#controllerButtonPressed(int, int)330*/331public void controllerButtonPressed(int controller, int button) {332if (transitioning()) {333return;334}335336currentState.controllerButtonPressed(controller, button);337}338339/**340* @see org.newdawn.slick.InputListener#controllerButtonReleased(int, int)341*/342public void controllerButtonReleased(int controller, int button) {343if (transitioning()) {344return;345}346347currentState.controllerButtonReleased(controller, button);348}349350/**351* @see org.newdawn.slick.InputListener#controllerDownPressed(int)352*/353public void controllerDownPressed(int controller) {354if (transitioning()) {355return;356}357358currentState.controllerDownPressed(controller);359}360361/**362* @see org.newdawn.slick.InputListener#controllerDownReleased(int)363*/364public void controllerDownReleased(int controller) {365if (transitioning()) {366return;367}368369currentState.controllerDownReleased(controller);370}371372/**373* @see org.newdawn.slick.InputListener#controllerLeftPressed(int)374*/375public void controllerLeftPressed(int controller) {376if (transitioning()) {377return;378}379380currentState.controllerLeftPressed(controller);381}382383/**384* @see org.newdawn.slick.InputListener#controllerLeftReleased(int)385*/386public void controllerLeftReleased(int controller) {387if (transitioning()) {388return;389}390391currentState.controllerLeftReleased(controller);392}393394/**395* @see org.newdawn.slick.InputListener#controllerRightPressed(int)396*/397public void controllerRightPressed(int controller) {398if (transitioning()) {399return;400}401402currentState.controllerRightPressed(controller);403}404405/**406* @see org.newdawn.slick.InputListener#controllerRightReleased(int)407*/408public void controllerRightReleased(int controller) {409if (transitioning()) {410return;411}412413currentState.controllerRightReleased(controller);414}415416/**417* @see org.newdawn.slick.InputListener#controllerUpPressed(int)418*/419public void controllerUpPressed(int controller) {420if (transitioning()) {421return;422}423424currentState.controllerUpPressed(controller);425}426427/**428* @see org.newdawn.slick.InputListener#controllerUpReleased(int)429*/430public void controllerUpReleased(int controller) {431if (transitioning()) {432return;433}434435currentState.controllerUpReleased(controller);436}437438/**439* @see org.newdawn.slick.InputListener#keyPressed(int, char)440*/441public void keyPressed(int key, char c) {442if (transitioning()) {443return;444}445446currentState.keyPressed(key, c);447}448449/**450* @see org.newdawn.slick.InputListener#keyReleased(int, char)451*/452public void keyReleased(int key, char c) {453if (transitioning()) {454return;455}456457currentState.keyReleased(key, c);458}459460/**461* @see org.newdawn.slick.InputListener#mouseMoved(int, int, int, int)462*/463public void mouseMoved(int oldx, int oldy, int newx, int newy) {464if (transitioning()) {465return;466}467468currentState.mouseMoved(oldx, oldy, newx, newy);469}470471/**472* @see org.newdawn.slick.InputListener#mouseDragged(int, int, int, int)473*/474public void mouseDragged(int oldx, int oldy, int newx, int newy) {475if (transitioning()) {476return;477}478479currentState.mouseDragged(oldx, oldy, newx, newy);480}481/**482* @see org.newdawn.slick.InputListener#mouseClicked(int, int, int, int)483*/484public void mouseClicked(int button, int x, int y, int clickCount) {485if (transitioning()) {486return;487}488489currentState.mouseClicked(button, x, y, clickCount);490}491492/**493* @see org.newdawn.slick.InputListener#mousePressed(int, int, int)494*/495public void mousePressed(int button, int x, int y) {496if (transitioning()) {497return;498}499500currentState.mousePressed(button, x, y);501}502503/**504* @see org.newdawn.slick.InputListener#mouseReleased(int, int, int)505*/506public void mouseReleased(int button, int x, int y) {507if (transitioning()) {508return;509}510511currentState.mouseReleased(button, x, y);512}513514/**515* @see org.newdawn.slick.InputListener#isAcceptingInput()516*/517public boolean isAcceptingInput() {518if (transitioning()) {519return false;520}521522return currentState.isAcceptingInput();523}524525/**526* @see org.newdawn.slick.InputListener#inputEnded()527*/528public void inputEnded() {529}530531/**532* @see org.newdawn.slick.InputListener#mouseWheelMoved(int)533*/534public void mouseWheelMoved(int newValue) {535if (transitioning()) {536return;537}538539currentState.mouseWheelMoved(newValue);540}541542}543544545