#include <CGameFramework.h>
Collaboration diagram for CGameFramework:

Public Types | |
| enum | TGameState { EDied, ELevelCompleted, EPaused } |
| Current state of the game. More... | |
Public Methods | |
| ~CGameFramework () | |
| delete level information. More... | |
| TGameState | RunL (TBool aReset) |
| Run a level of the game. More... | |
| void | LoadLevelL (const TDesC &aLevelName, const TDesC &aMapName, TBool aResetShip) |
| Load level and map files. More... | |
| TInt | Score () |
| Allow the ui access to the players score. More... | |
| void | CancelL () |
| Cancel paused game. More... | |
Static Public Methods | |
| CGameFramework * | NewL () |
| Leave safe constuction. More... | |
Private Methods | |
| TBool | Play (RWsSession &aWindSession) |
| Loop getting window server events. More... | |
Static Private Methods | |
| TInt | GameThread (TAny *aGameData) |
| Game thread start point. More... | |
Private Attributes | |
| TGameData | iData |
| Game data, key presses level information etc. More... | |
| RThread | iGameThread |
| Thread within which the CGame object runs. More... | |
| TRequestStatus | iGameStatus |
| Status of game thread. More... | |
| HBufC8 * | iLevel |
| Sprite, background and status sprites for level. More... | |
| HBufC8 * | iMap |
| Map and path data for game. More... | |
Loads levels, starts/suspends the thread that owns the CGame object, talks direct to the window server to collect key presses and focus change events.
Definition at line 30 of file CGameFramework.h.
|
|
Current state of the game.
Definition at line 33 of file CGameFramework.h. Referenced by CGameAppUi::HandleCommandL(), and RunL().
00033 {
00034 EDied,
00035 ELevelCompleted,
00036 EPaused,
00037 };
|
|
|
delete level information.
Definition at line 31 of file CGameFramework.cpp.
|
|
|
Leave safe constuction. Not really nessesary as there is no ConstuctL, but there might be in the future Definition at line 25 of file CGameFramework.cpp. Referenced by CGameAppUi::ConstructL().
00025 {
00026 CGameFramework* self= new (ELeave) CGameFramework;
00027 return(self);
00028 };
|
|
|
Run a level of the game. This class creates a connection to the window server, and creates a window to cover the screen. Sets iData.iForceRedraw so that is we are resuming a previous game the status screen is updated in full. If this returns and the game hasn't been paused the level has been deleted.
Definition at line 106 of file CGameFramework.cpp. References EDied, ELevelCompleted, TGamePanics::ENoLevelLoaded, EPaused, iData, TGameData::iForceRedraw, iGameStatus, iGameThread, iLevel, TGameData::iLevelCompleted, TGameData::iLives, iMap, TGameData::iScore, TGamePanics::Panic(), Play(), and TGameState. Referenced by CancelL(), and CGameAppUi::HandleCommandL().
00106 {
00107 // assert that LoadLevelL has been called and succeded in
00108 // loading a level
00109 __ASSERT_ALWAYS(iLevel!=NULL && iMap!=NULL,TGamePanics::Panic(TGamePanics::ENoLevelLoaded));
00110
00111 // if this is a new game reset the score and lives
00112 if(aReset!=EFalse) {
00113 iData.iLives=3;
00114 iData.iScore=0;
00115 }
00116
00117 // connect to the window server.
00118 RWsSession winSession;
00119 User::LeaveIfError(winSession.Connect());
00120 CleanupClosePushL(winSession);
00121
00122 // these can be whatever we like, as long as they are unique,
00123 // as we have only one window and one windowgroup we don't
00124 // actually use them.
00125 const TUint32 KWindowHandle=1;
00126 const TUint32 KWindowGroupHandle=2;
00127
00128 // create a window group so we can create a window
00129 RWindowGroup winGroup(winSession);
00130 User::LeaveIfError(winGroup.Construct(KWindowGroupHandle));
00131 CleanupClosePushL(winGroup);
00132
00133 // create a blank window, blank windows can't be drawn on,
00134 // however as the game code writes directly to the screen this
00135 // isn't a problem.
00136 RBlankWindow window(winSession);
00137 User::LeaveIfError(window.Construct(winGroup,KWindowHandle));
00138 CleanupClosePushL(window);
00139 window.Activate();
00140 window.SetSize(TSize(640,200));
00141 // request focus events so we can pause the game thread when
00142 // we move to the background, this stops us writing over some other
00143 // apps screen.
00144 window.EnableFocusChangeEvents();
00145
00146 // first time in we want want to redraw everything,
00147 iData.iForceRedraw=ETrue;
00148
00149 // logon to the thread so we get informed when it exits.
00150 iGameThread.Logon(iGameStatus);
00151 iGameThread.Resume();
00152
00153 // play the game
00154 TBool finished=Play(winSession);
00155
00156 // cancel any outstanding request for key strokes/focus changes etc
00157 winSession.EventReadyCancel();
00158 // and watching the state of the thread
00159 iGameThread.LogonCancel(iGameStatus);
00160
00161 // I think this is the EventReady completing.
00162 User::WaitForAnyRequest();
00163
00164 // remove our window
00165 CleanupStack::PopAndDestroy(3,&winSession); //winGroup, window
00166
00167
00168 if(finished==EFalse) {
00169 // this is the thread notifying that it has suspended
00170 User::WaitForAnyRequest();
00171 // we have just paused the thread/game
00172 return EPaused;
00173 } else {
00174 // game finished, so close the thread, and delete the level
00175 iGameThread.Close();
00176 delete iLevel;
00177 iLevel=NULL;
00178 delete iMap;
00179 iMap=NULL;
00180
00181 User::Heap().Compress();
00182
00183 // did the player complete the level or die
00184 if(iData.iLevelCompleted==EFalse) {
00185 return EDied;
00186 } else {
00187 return ELevelCompleted;
00188 }
00189 }
00190 };
|
|
||||||||||||||||
|
Load level and map files. This loads the level and map files setting the iData.iLevel members to the information in the files. It also creates the game thread but doesn't resume it.
Definition at line 289 of file CGameFramework.cpp. References TGamePanics::ELoadLevelWithLevelLoaded, GameThread(), TLevelData::iBackgrounds, TLevelData::iBadGuyDeathEndSprite, TLevelData::iBadGuyDeathStartSprite, TLevelData::iBulletPower1_StartSprite, TLevelData::iBulletPower2_StartSprite, TLevelData::iBulletPower3_StartSprite, TLevelData::iBulletPower4_StartSprite, iData, iGameThread, TGameData::iKeys, TGameData::iLevel, iLevel, TGameData::iLevelCompleted, iMap, TLevelData::iMapData, TLevelData::iPaths, TLevelData::iShipDeathEndSprite, TLevelData::iShipDeathStartSprite, TLevelData::iShipPowerups, TLevelData::iShipSprite, TLevelData::iShipStartHealth, TLevelData::iShipStartXPos, TLevelData::iShipStartYPos, TLevelData::iSprites, TLevelData::iStatus, and TGamePanics::Panic(). Referenced by CGameAppUi::LoadLevelL().
00289 {
00290 __ASSERT_ALWAYS(iLevel==NULL && iMap==NULL,TGamePanics::Panic(TGamePanics::ELoadLevelWithLevelLoaded));
00291
00292 RFs fs;
00293 User::LeaveIfError(fs.Connect());
00294 CleanupClosePushL(fs);
00295
00296
00297 // load level file
00298 RFile levelFile;
00299 User::LeaveIfError(levelFile.Open(fs,aLevelName,EFileRead));
00300 CleanupClosePushL(levelFile);
00301
00302 TInt size;
00303 User::LeaveIfError(levelFile.Size(size));
00304 size-=16; //skip uids on front of file
00305 HBufC8 *levelDes= HBufC8::NewLC(size);
00306 TPtr8 levelPtr=levelDes->Des();
00307 User::LeaveIfError(levelFile.Read(16,levelPtr,size));
00308
00309
00310 // load map file
00311 RFile mapFile;
00312 User::LeaveIfError(mapFile.Open(fs,aMapName,EFileRead));
00313 CleanupClosePushL(mapFile);
00314
00315 User::LeaveIfError(mapFile.Size(size));
00316 size-=16; //skip uids on front of file
00317 HBufC8 *mapDes= HBufC8::NewLC(size);
00318 TPtr8 mapPtr=mapDes->Des();
00319 User::LeaveIfError(mapFile.Read(16,mapPtr,size));
00320
00321
00322
00323
00324 // create a thread within which to run the game,
00325 _LIT(KGameThread,"RealGame");
00326 // 4k stack,
00327 const TInt KStackSize=4*1024;
00328
00329 // create but don't resume as the iData isn't set up yet.
00330 User::LeaveIfError(iGameThread.Create(KGameThread,GameThread,KStackSize,NULL,&iData));
00331 // as we want to respond to key presses the game thread
00332 // has a lower priority than getting events
00333 iGameThread.SetPriority(EPriorityLess);
00334
00335
00336
00337
00338
00339 CleanupStack::Pop(mapDes);
00340 iMap=mapDes;
00341 CleanupStack::PopAndDestroy(&mapFile);
00342 CleanupStack::Pop(levelDes);
00343 iLevel=levelDes;
00344 CleanupStack::PopAndDestroy(2,&fs); // levelFile
00345
00346
00347 // setup level data
00348 TInt32* level= (TInt32*) (iLevel->Ptr());
00349 TInt32* map= (TInt32*) (iMap->Ptr());
00350
00351 iData.iKeys=0;
00352 iData.iLevelCompleted=EFalse;
00353
00354 iData.iLevel.iMapData=(TInt16*) (iMap->Ptr()+map[0]);
00355 iData.iLevel.iPaths=(TInt16*) (iMap->Ptr()+map[1]);
00356
00357 iData.iLevel.iBackgrounds=(TUint16*) (iLevel->Ptr()+level[0]);
00358 iData.iLevel.iSprites=(TUint16*) (iLevel->Ptr()+level[1]);
00359 iData.iLevel.iStatus=(TUint16*) (iLevel->Ptr()+level[2]);
00360
00361 iData.iLevel.iShipSprite=(TInt16) map[2];
00362 iData.iLevel.iShipDeathStartSprite=(TInt16) map[3];
00363 iData.iLevel.iShipDeathEndSprite=(TInt16) map[4];
00364 iData.iLevel.iBadGuyDeathStartSprite=(TInt16) map[5];
00365 iData.iLevel.iBadGuyDeathEndSprite=(TInt16) map[6];
00366 iData.iLevel.iBulletPower1_StartSprite=(TInt16) map[7];
00367 iData.iLevel.iBulletPower2_StartSprite=(TInt16) map[8];
00368 iData.iLevel.iBulletPower3_StartSprite=(TInt16) map[9];
00369 iData.iLevel.iBulletPower4_StartSprite=(TInt16) map[10];
00370 iData.iLevel.iShipStartXPos=(TInt16) map[11];
00371 iData.iLevel.iShipStartYPos=(TInt16) map[12];
00372 iData.iLevel.iShipStartHealth=(TInt16) map[13];
00373 if(aResetShip!=EFalse) {
00374 iData.iLevel.iShipPowerups=(TInt16) map[14];
00375 }
00376 }
|
|
|
Allow the ui access to the players score.
Definition at line 88 of file CGameFramework.cpp. References iData, and TGameData::iScore. Referenced by CGameAppUi::HandleCommandL().
|
|
|
Cancel paused game. Simulates a quit key press then starts the game running. The game thread has to run so it can delete the CGame object. Definition at line 41 of file CGameFramework.cpp. References TGameData::EQuit, iData, TGameData::iKeys, and RunL(). Referenced by CGameAppUi::HandleCommandL().
00041 {
00042 iData.iKeys |= TGameData::EQuit;
00043 RunL(EFalse);
00044 }
|
|
|
Game thread start point. This creates a CGame object and keeps calling Play on it while the player has lives, hasn't finished the level and hasn't quit. The TGameData comunicates the level information and key presses to this thread and comunicates the score, lives left and outcome of the level back to the ui thread.
Definition at line 61 of file CGameFramework.cpp. References TGameData::EQuit, TGameData::iKeys, TGameData::iLevelCompleted, TGameData::iLives, CGame::NewL(), and CGame::Play(). Referenced by LoadLevelL().
00061 {
00062 // create a cleanup stack
00063 CTrapCleanup* cleanup=CTrapCleanup::New();
00064 if(cleanup==NULL)
00065 return KErrNoMemory;
00066
00067 TInt error=KErrNone;
00068
00069 TGameData& data= (*STATIC_CAST(TGameData*,aGameData));
00070
00071 // look while we have lives, haven't got to the end of the level,
00072 // 'Q' hasn't been pressed, and haven't got an error creating the game.
00073 while(data.iLives!=0 && !(data.iKeys & TGameData::EQuit) &&
00074 data.iLevelCompleted==EFalse && error==KErrNone) {
00075 // create a game and call play on it.
00076 CGame *game=NULL;
00077 TRAPD(error,game=CGame::NewL(data));
00078 if(error==KErrNone) {
00079 game->Play();
00080 delete game;
00081 }
00082 }
00083 delete cleanup;
00084 return error;
00085 };
|
|
|
Loop getting window server events. This class loops waiting for requests. If it is a window server key event we update the iData.iKeys bitmask to tell the game thread that a key was pressed. If it is a window server key event 'P' or a focus lost event we suspend the game thread and return. If it is the game thread exiting we return. Otherwise we allow the active scheduler to handle it.
Definition at line 210 of file CGameFramework.cpp. References TGameData::EAction1, TGameData::EAction2, TGameData::EAction3, TGameData::EAction4, TGameData::EDown, TGameData::ELeft, TGameData::EQuit, TGameData::ERight, TGameData::EUp, iData, iGameStatus, iGameThread, and TGameData::iKeys. Referenced by RunL().
00210 {
00211 TRequestStatus normalEvent;
00212
00213 // listen for key strokes/focus changes etc.
00214 aWindSession.EventReady(&normalEvent);
00215
00216 for(;;) {
00217 User::WaitForAnyRequest();
00218 if(normalEvent!=KRequestPending) {
00219 TWsEvent event;
00220 aWindSession.GetEvent(event);
00221 aWindSession.EventReady(&normalEvent);
00222 switch(event.Type()) {
00223 case EEventKeyDown: {
00224 TKeyEvent *key=event.Key();
00225 switch(key->iScanCode) {
00226 case EStdKeyLeftArrow: iData.iKeys |= TGameData::ELeft; break;
00227 case EStdKeyRightArrow: iData.iKeys |= TGameData::ERight; break;
00228 case EStdKeyUpArrow: iData.iKeys |= TGameData::EUp; break;
00229 case EStdKeyDownArrow: iData.iKeys |= TGameData::EDown; break;
00230 case 'Q': iData.iKeys |= TGameData::EQuit; break;
00231 case 'A': iData.iKeys |= TGameData::EAction1; break;
00232 case EStdKeySpace: iData.iKeys |= TGameData::EAction2; break;
00233 case EStdKeyLeftShift: iData.iKeys |= TGameData::EAction3; break;
00234 case EStdKeyEnter: iData.iKeys |= TGameData::EAction4; break;
00235 case 'P': {
00236 iGameThread.Suspend();
00237 return EFalse;
00238 }
00239 }
00240 }
00241 break;
00242 case EEventKeyUp: {
00243 TKeyEvent *key=event.Key();
00244 switch(key->iScanCode) {
00245 case EStdKeyLeftArrow: iData.iKeys &= ~TGameData::ELeft; break;
00246 case EStdKeyRightArrow: iData.iKeys &= ~TGameData::ERight; break;
00247 case EStdKeyUpArrow: iData.iKeys &= ~TGameData::EUp; break;
00248 case EStdKeyDownArrow: iData.iKeys &= ~TGameData::EDown; break;
00249 case 'A': iData.iKeys &= ~TGameData::EAction1; break;
00250 case EStdKeySpace: iData.iKeys &= ~TGameData::EAction2; break;
00251 case EStdKeyLeftShift: iData.iKeys &= ~TGameData::EAction3; break;
00252 case EStdKeyEnter: iData.iKeys &= ~TGameData::EAction4; break;
00253 }
00254 }
00255 break;
00256 case EEventFocusLost:
00257 // pause game if we go into the background
00258 iGameThread.Suspend();
00259 return EFalse;
00260 break;
00261 }
00262 } else if(iGameStatus!=KRequestPending) {
00263 // thread ended
00264 return ETrue;
00265 } else {
00266 // event meant for active scheduler if there is one
00267 // I don't think it should never get here
00268 CActiveScheduler *sched=CActiveScheduler::Current();
00269 if(sched!=NULL) {
00270 TInt error;
00271 sched->RunIfReady(error,0);
00272 }
00273 }
00274 }
00275 }
|
|
|
Game data, key presses level information etc.
Definition at line 53 of file CGameFramework.h. Referenced by CancelL(), LoadLevelL(), Play(), RunL(), and Score(). |
|
|
Thread within which the CGame object runs.
Definition at line 54 of file CGameFramework.h. Referenced by LoadLevelL(), Play(), and RunL(). |
|
|
Status of game thread.
Definition at line 55 of file CGameFramework.h. |
|
|
Sprite, background and status sprites for level.
Definition at line 57 of file CGameFramework.h. Referenced by LoadLevelL(), RunL(), and ~CGameFramework(). |
|
|
Map and path data for game.
Definition at line 58 of file CGameFramework.h. Referenced by LoadLevelL(), RunL(), and ~CGameFramework(). |