Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

CGame.cpp

Go to the documentation of this file.
00001 // Copyright 2002 Kenneth Guy,
00002 // 
00003 // You are free to take the source and do as you wish with it.
00004 // However it would be nice if you let me know if the code was useful
00005 // to you and give me an acknowledgement if you use a significant portion
00006 // of the code in an application.
00007 // 
00008 // CGame.cpp
00009 
00014 #include <e32std.h>
00015 #include <e32base.h>
00016 
00017 #include "CMap.h"
00018 #include "CGame.h"
00019 #include "TBadGuy.h"
00020 #include "TPlayersShip.h"
00021 #include "TBullet.h"
00022 #include "TGameData.h"
00023 
00029 const TInt KMaxBadGuys=125;
00030 
00036 const TInt KMaxBullets=8;
00037 
00038 
00041 CGame* CGame::NewL(TGameData &aData) {
00042   CGame *self= new (ELeave) CGame(aData);
00043   CleanupStack::PushL(self);
00044   self->ConstructL();
00045   CleanupStack::Pop(self);
00046   return(self);
00047 }
00048 
00051 CGame::CGame(TGameData& aData) : iData(aData), iLastFired(0) {
00052 
00053 };
00054 
00056 CGame::~CGame() {
00057   iStatus.Close();
00058   delete iMap;
00059   delete [] iBadGuys;
00060   delete [] iBullets;
00061   delete iPlayersShip;
00062 };
00063 
00064 
00072 void CGame::ConstructL() {
00073   // create the status screen area
00074   User::LeaveIfError(iStatus.Open(iData.iLevel.iStatus));
00075 
00076   // create the players ship as defined by the level data
00077   iPlayersShip = new (ELeave) TPlayersShip(iData.iLevel.iShipStartXPos,
00078                                            iData.iLevel.iShipStartYPos,
00079                                            iData.iLevel.iShipStartHealth,
00080                                            iData.iLevel.iShipSprite,
00081                                            iData.iLevel.iShipDeathStartSprite,
00082                                            iData.iLevel.iShipDeathEndSprite);  
00083 
00084   // create slots for KMaxBadGuy bad guys
00085   // (TBadGuy is used for bonuses and sheilds as well as bad guys)
00086   iBadGuys= new (ELeave) TBadGuy[KMaxBadGuys];
00087 
00088   // set up players bullets at power one
00089   iBullets= new (ELeave) TBullet[KMaxBullets];
00090   for(TInt i=0;i<KMaxBullets;i++) {
00091     iBullets[i].Set(iData.iLevel.iBulletPower1_StartSprite+i,1);
00092   }
00093 
00094   TInt16 count=iData.iLevel.iShipPowerups;
00095   while(count--) {
00096     Bonus(EBonusPowerup);
00097   }
00098 
00099   // create the offscreen buffer, and plot the first screen full of
00100   // the map
00101   iMap=CMap::NewL(*this,iData.iLevel.iBackgrounds,iData.iLevel.iMapData);
00102   // CMap may calls back into CGame to add bad guys, if there
00103   // are any bad guys in the first 11 lines of the map this will
00104   // happen during construction, so CGame should be valid when
00105   // constructing iMap,
00106 };
00107 
00108 
00140 void CGame::Play() {
00141   TUint lasttick=0;
00142 
00143   while(!(iData.iKeys & TGameData::EQuit)) {
00144     // handle key presses
00145     HandleKeys();
00146 
00147     // move bullets and bad guys
00148     MoveThings();
00149     // plot the ship/bullets & badguys into offscreen buffer
00150     DrawEveryThing();
00151     
00152     // make sure each loop takes at least 2 ticks
00153     TUint tick = User::TickCount();
00154     while((tick-lasttick)<2)
00155       tick = User::TickCount();
00156     lasttick=tick;   
00157 
00158     // copy the offscreen buffer to the screen
00159     iMap->BlitAsm();
00160 
00161     // remove all the sprites we ploted in reverse order
00162     RemoveEveryThing();
00163     
00164     // handle bad guy collisions
00165     Collisions();
00166     
00167     // crash if player hit the landscape
00168     if(iPlayersShip->Hit()==TSprite32x24::EHitLandScape)
00169       iPlayersShip->SetHealth(0);
00170 
00171     
00172     // Handle crashing ship
00173     if(iPlayersShip->Dead()!=EFalse) {
00174       iData.iLives--;
00175       return;
00176     }
00177 
00178     // handle end of level (when map has finished, and player flies
00179     // off the right hand side of the screen)
00180     if(iMap->Finished()!=EFalse && iPlayersShip->iX==304 &&
00181        iPlayersShip->Dieing()==EFalse) {
00182       iData.iLevelCompleted=ETrue;
00183       // update level data so that next level can start with same
00184       // health / powerups
00185       iData.iLevel.iShipPowerups=iPowerups;
00186       iData.iLevel.iShipStartHealth=iPlayersShip->Health();
00187       return;
00188     }
00189 
00190     
00191     // plot status window
00192     if(iData.iForceRedraw==EFalse) {
00193       iStatus.Update(iData.iScore,iData.iLives,iPlayersShip->Health());
00194     } else {
00195       iStatus.Draw(iData.iScore,iData.iLives,iPlayersShip->Health());
00196       iData.iForceRedraw=EFalse;
00197     }
00198     
00199     // scroll the offset screen map, plot another line of map sprites
00200     // if nessesary.
00201     iMap->ScrollMap();
00202   }
00203 };
00204 
00205 
00213 void CGame::Bonus(TGameBonus aBonus) {
00214   switch(aBonus) {
00215   case EBonusLife:
00216     iData.iLives++;
00217     break;
00218 
00219   case EBonusPowerup: {    
00220     // remember the number of these so that if the player completes
00221     // the level they can be carried to the next level
00222     iPowerups++;
00223     // find the bullet with the least power and increase
00224     // its power by one, changing its sprite at the same time.
00225     // if all bullets are at full strength nothing happens.
00226     TInt16 minPower=iBullets[0].Strength();
00227     TInt powerUp=0;
00228     for(TInt i=1;i<KMaxBullets;i++) {
00229       const TInt16 strength=iBullets[i].Strength();
00230       if(strength < minPower) {
00231         powerUp=i;
00232         minPower = strength;
00233         }
00234     }
00235     switch(minPower) {
00236     case 0:
00237        iBullets[powerUp].Set(powerUp+iData.iLevel.iBulletPower1_StartSprite,1);
00238        break;
00239     case 1:
00240        iBullets[powerUp].Set(powerUp+iData.iLevel.iBulletPower2_StartSprite,2);
00241        break;
00242     case 2:
00243        iBullets[powerUp].Set(powerUp+iData.iLevel.iBulletPower3_StartSprite,3);
00244        break;
00245     case 3:
00246        iBullets[powerUp].Set(powerUp+iData.iLevel.iBulletPower4_StartSprite,4);
00247        break;
00248     }
00249   }
00250   break;  
00251 
00252   }
00253 }
00254 
00261 TInt16 CGame::FirstExplosionSprite() {
00262   return iData.iLevel.iBadGuyDeathStartSprite;
00263 }
00264 
00270 TInt16 CGame::LastExplosionSprite() {
00271   return iData.iLevel.iBadGuyDeathEndSprite;
00272 }
00273 
00275 void CGame::AddScore(TInt aScore) {
00276   iData.iScore+=aScore;
00277 }
00278 
00285 void CGame::DamageBadGuys(TInt16 aId,TInt16 aHealth) {
00286   for(TInt i=0;i<KMaxBadGuys;i++) {
00287     if(iBadGuys[i].Used()!= EFalse && aId == iBadGuys[i].Id()) {
00288       iBadGuys[i].Damage(aHealth,*this);
00289     }
00290   }      
00291 }
00292 
00293 
00300 void CGame::Collisions() {
00301   for(TInt i=KMaxBadGuys-1;i>=0;--i) {
00302     if(iBadGuys[i].Used()!=EFalse) {
00303       TSprite32x24::THit what=iBadGuys[i].Hit();
00304       
00305       if(what==TSprite32x24::EHitShip) {
00306         // badguy has hit player
00307         iBadGuys[i].HitShip(*iPlayersShip,*this);
00308 
00309       } else if(what >=TSprite32x24::EHitBullet1 &&
00310                 what <=TSprite32x24::EHitBullet8) {
00311         // badguy has hit a bullet
00312         
00313         TInt bulletNo = what - TSprite32x24::EHitBullet1;
00314         iBadGuys[i].HitBullet(iBullets[bulletNo],*this);
00315       }
00316     }
00317   }
00318 }
00319 
00326 void CGame::RemoveEveryThing() {
00327   TInt i;
00328   for(i=KMaxBadGuys-1;i>=0;--i) {
00329     if(iBadGuys[i].Used()!=EFalse)
00330       iBadGuys[i].Remove();
00331   }
00332   for(i=KMaxBullets-1;i>=0;--i) {
00333     if(iBullets[i].Used()!=EFalse)
00334       iBullets[i].Remove();
00335   }
00336   iPlayersShip->Remove();
00337 }
00338 
00339 
00349 void CGame::DrawEveryThing() {
00350   const TUint16 *sprites=iData.iLevel.iSprites;
00351 
00352   iPlayersShip->Plot(*iMap,sprites);
00353   
00354   TInt i;
00355   for(i=0;i<KMaxBullets;++i) {
00356     if(iBullets[i].Used()!=EFalse)
00357       iBullets[i].Plot(*iMap,sprites);
00358   }
00359   
00360   for(i=0;i<KMaxBadGuys;++i) {
00361     if(iBadGuys[i].Used()!=EFalse)
00362       iBadGuys[i].Plot(*iMap,sprites);
00363   }
00364 }
00365 
00368 void CGame::MoveThings() {
00369   for(TInt k=0;k<KMaxBullets;k++) {
00370     if(iBullets[k].Used()!=EFalse) {
00371       iBullets[k].Move();
00372     }
00373   }
00374   
00375   for(TInt i=0;i<KMaxBadGuys;++i) {
00376     if(iBadGuys[i].Used()!=EFalse) {
00377       iBadGuys[i].Move(iPlayersShip->iX,iPlayersShip->iY,iData.iLevel.iPaths,*this);
00378     }
00379   }
00380 };
00381 
00382 
00390 void CGame::AddBadGuy(const TBadGuy &aBadGuy) {
00391   TInt empty=0;
00392   for(;empty<KMaxBadGuys && iBadGuys[empty].Used()!=EFalse;empty++) {};
00393   if(empty>=KMaxBadGuys) return;
00394   iBadGuys[empty]=aBadGuy;
00395 }
00396 
00406 void CGame::AddBadGuy(TInt16 aType,const  TInt16 aArgs[]) {
00407   TInt empty=0;
00408   for(;empty<KMaxBadGuys && iBadGuys[empty].Used()!=EFalse;empty++) {};
00409   if(empty>=KMaxBadGuys) return;
00410   iBadGuys[empty].Init(aType,aArgs);
00411 };
00412 
00421 void CGame::HandleKeys() {
00422   //movement
00423   TInt x=0;
00424   TInt y=0;
00425   if(iData.iKeys & TGameData::EUp)    y-=6;
00426   if(iData.iKeys & TGameData::EDown)  y+=6;
00427   if(iData.iKeys & TGameData::ELeft)  x-=6;
00428   if(iData.iKeys & TGameData::ERight) x+=6;
00429   iPlayersShip->MoveBy(x,y,iMap->Finished());
00430 
00431 
00432   // shooting  
00433   // can't shoot while dieing,
00434   if(iData.iKeys & TGameData::EAction3 && iPlayersShip->Dieing()==EFalse) {    
00435     // de-bounce fire key
00436     iData.iKeys = iData.iKeys & ~TGameData::EAction3;
00437     Shoot();
00438   }        
00439 }
00440 
00448 void CGame::Shoot() {
00449   // add another bullet if there is a free slot
00450   // try and rotate bullet slots,
00451   TInt i;
00452   for(i=iLastFired+1;i<KMaxBullets;i++) {
00453     if(iBullets[i].Used()==EFalse) {
00454       iLastFired=i;
00455       iBullets[i].Shoot(iPlayersShip->iX+12,iPlayersShip->iY);
00456       return;
00457     }
00458   }
00459   for(i=0;i<=iLastFired && i<KMaxBullets;i++) {
00460     if(iBullets[i].Used()==EFalse) {
00461       iLastFired=i;
00462       iBullets[i].Shoot(iPlayersShip->iX+12,iPlayersShip->iY);
00463       return;
00464     } 
00465   } 
00466 }
00467 
00475 TInt16 CGame::MapSpeed() {
00476   if(iMap->Finished()==EFalse) {
00477     return -2;
00478   } else {
00479     return 0;
00480   }
00481 }

Documentation for Game (Beta) version 1.44.