Wiley.Games.on.Symbian.OS.A.Handbook.for.Mobile.Development.Apr.2008 (779888), страница 17
Текст из файла (страница 17)
For any length of time, on a mobileoperating system, this kind of regular looping can lead to a drain inbattery power. The requirement to regularly run the game thread preventsthe OS from powering down all but the most essential resources to makeefficient use of the battery.2.6.1 Loss of FocusAs a developer, you need to be aware that the game is consuming batterypower whenever it is running the loop, and ensure that the heartbeattimer runs only when required. For example, the game loop should bepaused when the game is interrupted by a system event, such as anincoming call, or because the user has tasked to another application.
Thegame loop should also pause if the user stops interacting with the gamefor any length of time; for example, if she is playing the game on the busand has to get off at her stop without quitting the game before doing so.You should implement CCoeControl::FocusChanged() to benotified of a change in focus of the game – that is, when another application or system dialog sends the game to the background. As the exampleshows, the timer is halted when the focus is lost, and started when it isregained.
The benefit of having a single heartbeat time to drive the gameloop is that it is very straightforward to stop and start it when necessary.void CSkeletonAppView::FocusChanged(TDrawNow aDrawNow){if (IsFocused()){// Focus gainedStartHeartbeat(); // Starts the gameloop}else{// Focus lostif (iPeriodicTimer->IsActive()){StopHeartbeat(); // Pauses the game loop}// Save game data here if necessary}if(aDrawNow)DrawNow();}2.6.2 User InactivityIf no user input is received, after a certain length of time, to minimize thephone’s power usage, the system will gradually dim the backlight, andeventually turn it off completely. The length of inactivity time before eachSYSTEM EVENTS55step occurs is often customizable by the phone’s owner, and usually, ascreensaver is displayed, such as the time and date, which can also becustomized.Regardless of the fact that the phone appears to be in power-savingmode, the game loop will continue running, even when the screensaveris showing and the backlight is off, unless the developer adds code toexplicitly stop it.
To save power, it is usual practice for the game to moveinto ‘attract’ mode, or to display a pause menu and stop the game loopafter user inactivity of a certain duration.Attract mode is so called because it displays a graphics sequence whichlooks something like the game running in a demo mode, showing off thegame to attract the user to play it. Attract mode also consumes power,because it is still displaying regularly updated graphics and running agame loop, even if the frequency of the timer is much reduced fromthat of normal gameplay.
Unless the phone is running on main power(i.e., connected to its charger), it is usual to run the attract mode fora pre-determined amount of time only, perhaps two minutes, and thendisplay the pause menu and halt the game loop by completely stoppingthe heartbeat timer.User inactivity can be detected by creating a class that inherits fromthe CTimer active object and calling the Inactivity() method.
Theobject receives an event if the interval specified, passed as a parameterto the method, elapses without user activity.class CInactivityTimer : public CTimer{public:static CInactivityTimer* NewL(CSkeletonAppView& aAppView);void StartInactivityMonitor(TTimeIntervalSeconds aSeconds);protected:CInactivityTimer(CSkeletonAppView& aAppView);virtual void RunL();private:CSkeletonAppView& iAppView;TTimeIntervalSeconds iTimeout;};CInactivityTimer::CInactivityTimer(CSkeletonAppView& aAppView): CTimer(EPriorityLow), iAppView(aAppView){CActiveScheduler::Add(this);}CInactivityTimer* CInactivityTimer::NewL(CSkeletonAppView& aAppView){CInactivityTimer* me = new (ELeave) CInactivityTimer(aAppView);CleanupStack::PushL(me);me->ConstructL();CleanupStack::Pop(me);return (me);}56SYMBIAN OS GAME BASICSvoid CInactivityTimer::StartInactivityMonitor(TTimeIntervalSecondsaSeconds){if (!IsActive()){iTimeout = aSeconds;Inactivity(iTimeout);}}void CInactivityTimer::RunL(){// Game has been inactive - no user input for iTimeout secondsiAppView.SetPausedDisplay(ETrue); // Displays the pause screeniAppView.StopHeartbeat(); // Stop the game loop}The CInactivityTimer::StartInactivityMonitor() method must be called each time the game loop starts, to monitor for userinactivity while it is running.Following any kind of pause, when the user returns to the game and itregains focus, the game should remain in the paused state until the usermakes an explicit choice to proceed, quit, or perform another action,depending on what the pause menu offers.The usability of the pause menu is a hot topic – it’s been said that youcan tell the quality of a mobile game from how easy it is to resume fromthe pause menu.
This aspect of game design is outside the scope of thisbook, but you can find an interesting paper called At The Core Of MobileGame Usability: The Pause Menu in the Usability section of the ForumNokia website (www.forum.nokia.com/main/resources/documentation/usability).3 This section has a number of other useful documents formobile game developers and designers, and I recommend that youbrowse them regularly, even if you are developing a mobile game for theother Symbian OS UI platforms.2.6.3 Simulating User ActivityThere are occasions when the game may want to simulate activity.For example, while attract mode is playing, it is desirable to preventthe system from dimming the backlight, the screensaver taking over,and eventually the backlight turning off completely.
This may seemcontradictory, but often games will detect user inactivity, move to attractmode, and then actually simulate user activity while attract mode isrunning, so the graphics can be seen. User activity is simulated by calling3The exact location of the paper has a URL which is far too long to type in from a book,and is subject to change anyway, if the content is updated in future. We will keep a set oflinks to papers and resources that are useful to game developers on the Symbian DeveloperNetwork Wiki (developer.symbian.com/wiki/display/academy/Games+on+Symbian+OS).MEMORY MANAGEMENT AND DISK SPACE57User::ResetInactivityTime() regularly, in the game loop.
Thisis unnecessary while the game is being played, because the user isgenerating input. It should also cease when the game changes modesto display the pause menu, to then allow the system to switch off thebacklight and display the screensaver as it normally would do.Since simulating user activity during attract mode prevents the system from saving power by dimming its backlight, the length of timethe game displays its attract mode should be limited, as section 2.6.2described, unless the phone is powered externally by the main charger.The CTelephony class can be used to retrieve information aboutwhether the phone is connected to a main charger, by calling CTelephony::GetIndicator().
To use CTelephony methods, you mustlink against Etel3rdParty.lib, and include the ETel3rdParty.hheader file.2.6.4 Saving Game DataWhen the game is paused, it should save any important game state in caseit is needed to continue the game in the state it was in before pausing.For example, the player may re-boot the phone before the game is nextplayed, but it should still be able to continue the game from the pointbefore it was paused. A player who has got to a particular level in a gamewill not be happy if their progress is lost because they had to interrupttheir session.A game should always save its data at regular intervals so it can berestored to the same state, should the game suddenly be stopped, forexample if the battery power fails or the battery is removed completely.In the event of a ‘battery pull,’ the game’s data manager code shouldbe prepared for the possibility that the data has been corrupted – suchas if an update was under way when the power down occurred.
Thegame should be able to recover from finding itself with corrupt data, forexample, by having a default set available in replacement, or performingdata updates using rollback.When saving game data, it is important to consider the amount ofinformation that should be written to file. If there is a large amountof data, for example over 2 KB, it is advisable not to use the blockingRFile::Write() method, since this could take some time to completeand would block the game thread. It is advisable to use an activeobject to schedule the update, using the asynchronous overload ofRFile::Write(), or to use one of the higher-level stream store APIs.2.7 Memory Management and Disk SpaceMobile devices have limitations on the amount of memory (RAM) theycan support for a number of reasons, including size (the limitations of the58SYMBIAN OS GAME BASICSphysical space available), cost, and current draw (the amount of powerrequired to access the memory).