Wiley.Games.on.Symbian.OS.A.Handbook.for.Mobile.Development.Apr.2008 (779888), страница 64
Текст из файла (страница 64)
Thegame is a traditional 2D arcade-style game which embodies most ofthe techniques I’ve discussed here. I strongly suggest downloading theFigure 9.1 Splash screen displayCASE STUDY: THIRD DEGREE283Figure 9.2 Action shot of our hero in mid jumpsource code and getting familiar with it, as there’s not going to beenough room here to cover it in depth. The point that I want to makehere is to demonstrate one way of undertaking the game developmentprocess – and there are certainly others.It’s at this point where the author usually says ‘‘it’s just a sample gamefor illustrative purposes.’’ Well it’s not; it’s a complete game. While itcertainly doesn’t have all the features I wanted to put into it, I’ve tried tomake it as functional and interesting as possible (although I’m a terriblegraphic artist and an even worse sound engineer).In this game, you’re the hero who has to jump across a series ofmoving platforms over an endless pit of fiery death, racing the clock toreach safety (and presumably long life and happiness).
You get points forsuccessful jumps and bonuses along the way as well as negotiating thedeadly Rings of Fire (which burn you and reduce your jump power). Youget three lives to make it to the end and a time bonus if you do.And if you haven’t worked it out yet, if you miss or fall off a platformat any stage along the way, you die.The process of building this game started off with a set of 10 fundamental questions. And there’s no point even thinking about startingdevelopment if you can’t answer these clearly at the outset:1.What are the aims of the player?2.How will pausing be handled (whether system or user initiated)?3.What is the ‘Game Over’ condition?4.What controls will be used for player input?5.How will the game world be represented and simulated (is a physicsor AI engine appropriate)?284MIDP GAMES ON SYMBIAN OS6.How will the frame rate and simulation rate affect each other (if atall)?7.How will changes in display size affect game play?8.What media effects will be used (audio, video, vibra)?9.How will scores, lives, bonuses and damage be handled and displayed to the player, e.g., through a heads-up display (HUD)?10.What optimizations should be employed in the simulation andrendering phases?I also made the following design decisions right at the start:• to favor a stronger class design at the cost of a larger JAR file• to limit the frame rate to keep consistent performance across devices• to use a virtual simulation rate whereby a fixed number of game ticksrepresents one unit of time in the physics model• that user input would be limited to move left, move right and jumpactions• to dynamically adjust the main menu to handle pauses (no pausemenu)• to use the MIDlet class only as an interface to the AMS and screenchanges• to combine the roles of simulation/physics engine and sprite (layer)management into a single class derived from the LayerManagerclass• to use the MVC design pattern for the application framework, butkeep the game sub-system separate.By keeping the actual game sub-system separate, it’s easier to cleanlydelineate MIDlet life cycle events from game life cycle events.
To harpon pausing (again), remember that pausing the game doesn’t (necessarily)pause the MIDlet, but that pausing the MIDlet should pause the game(if it’s running). Likewise, should stopping the game equate to stopping(exiting) the MIDlet? If you’ve kept the event handlers separate, that’s adesign decision that’s easily changed later.The high-level class diagram for Third Degree is shown in Figure 9.3.Note that only the main classes have been included for clarity.The core of the game comes down to three main classes and theworld objects themselves which I’ll now discuss in turn, focusing on theirhigh-level roles.CASE STUDY: THIRD DEGREEjavax.microedition.lcdui.game.GameCanvas285GameMIDIetControllerGameStateGameEffectsGameEngineGameScreenjavax.microedition.lcdui.game.LayerManagerFlipSpriteFireHerojavax.microedition.lcdui.game.SpriteFigure 9.39.9.1PlatformBackgroundjavax.microedition.lcdui.game.TiledLayerUML class diagram for Third DegreeController ClassThe Controller class links the outside world (the AMS and the MIDletclass) to the game sub-system.
It serves as the conduit through which allhigh-level applications events are handled. It is responsible for monitoringand changing the state of the game sub-system in response to system,game, or user events.It also holds an instance of the GameState class that contains thecurrent score, health, and number of lives of the player. This can bepersisted if necessary to allow a paused game to be re-started after theMIDlet exits or the device is shut off. The controller also creates theGameScreen instance upon which all rendering is performed.public class Controller{...private final static int GAME_STATUS_NONEprivate final static int GAME_STATUS_INITIALISEDprivate final static int GAME_STATUS_PAUSEDprivate final static int GAME_STATUS_RUNNINGprivate final static int GAME_STATUS_STOPPEDprivate final static int GAME_STATUS_OVER...private GameMidlet iMidlet;private int iGameStatus;private GameState iGameState;======0;1;2;3;4;5;286MIDP GAMES ON SYMBIAN OSprivate GameScreen iGameScreen;...public void startApplication(){if(iGameStatus == GAME_STATUS_NONE){initialise();}if(iGameStatus == GAME_STATUS_PAUSED){resumeGame();}}public void pauseApplication(){if(iGameStatus == GAME_STATUS_RUNNING){pauseGame();}}public void stopApplication(){if(iGameStatus == GAME_STATUS_PAUSED| | iGameStatus == GAME_STATUS_RUNNING){stopGame();}}private void resumeGame(){iGameScreen.resumeGame(iGameState);iGameStatus = GAME_STATUS_RUNNING;...}private void pauseGame(){iGameScreen.pauseGame();iGameStatus = GAME_STATUS_PAUSED;}}9.9.2GameScreen ClassGameScreen creates the game engine and is primarily responsible forexecuting the game loop.
On instantiation and on a sizeChanged event,it calculates an optimal layout for the world items in terms of the availablescreen real estate. In terms of rendering, it draws the heads up display(HUD) for the player data and delegates any remaining rendering to thegame engine (which, if you’ll remember, sub-classes LayerManager). Italso captures user input via standard key stroke game mappings to controlthe hero and handles commands to pause or resume the game loop.public class GameScreen extends GameCanvas implements Runnable{...public void run(){while(!stopped){processUserInput();integrateWorld();render();CASE STUDY: THIRD DEGREE287flushGraphics();synchroniseFrameRate();}}...private void integrateWorld(){long currentTime = System.currentTimeMillis();long elapsedTime = currentTime - lastIntegrationTime;if(elapsedTime > GameEngine.MILLISECONDS_PER_TIMESTEP){gameEngine.integrateWorld();lastIntegrationTime = System.currentTimeMillis();}}private void synchroniseFrameRate(){long currentTime = System.currentTimeMillis();long elapsedTime = currentTime - lastFrameTime;lastFrameTime = currentTime;if(elapsedTime < GameEngine.MILLISECONDS_PER_FRAME){try{gameThread.sleep(GameEngine.MILLISECONDS_PER_FRAME - elapsedTime);}catch(Exception e){}}else{gameThread.yield();}}}As can be seen in the listing above, the frame rate is kept to amaximum value, so that the animations do not proceed unrealistically onfaster hardware.
This is done by sleeping the game thread if it has takenless than MILLISECONDS_PER_FRAME to complete the game loop. Bysetting this to 40 ms, we ensure a rate of about 25 frames per second,which is plenty.We also track how often we integrate the world to effect the simulation.This should not occur at the same rate as rendering (which is a commonmistake).
By using the MILLISECONDS_PER_TIMESTEP constant, wecan tick the world simulation at a rate of our choosing to keep it smoothand realistic, minimizing what are often complex calculations.9.9.3GameEngine ClassNot surprisingly GameEngine’s responsibilities include generating theworld, scrolling through it in response to movement, and detectingcollisions between world objects.
It also handles all updates to theplayer’s health, lives, and score.Fundamentally, the game engine must run (physics) sequences to givethe game a realistic effect – so that when our hero runs, falls, lands on amoving platform, jumps, or catches alight, the changes in movement288MIDP GAMES ON SYMBIAN OSand world state all look fairly realistic. The engine ticks all worldobjects whenever its integrateWorld() method is called from theGameScreen.