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

TBadGuy.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 // TBadGuy.cpp
00009 
00014 #include "TBadGuy.h"
00015 #include "TPlayersShip.h"
00016 #include "TBullet.h"
00017 #include "CGame.h"
00018 #include "TGamePanics.h"
00019 
00020 #include "TMapLineType.h"
00021 #include "TPathLineType.h"
00022 
00024 TBadGuy::TBadGuy() {
00025 
00026 }
00027 
00040 void TBadGuy::Init(TInt16 aType,const  TInt16 aArgs[]) {
00041   SetSpriteNo(aArgs[0]);
00042   iX=aArgs[1];
00043   iY=aArgs[2];
00044   iHealth=aArgs[3];
00045   iXVel=0;
00046   iYVel=aArgs[5];
00047   iFlags=0;
00048   iPath=0;
00049   iId=0;
00050   iCounter=0;
00051 
00052   if(aType & EMapLineObjectMovementMapRelative) {
00053     iFlags |= TBadGuyFlags::EMapRelative;
00054   }
00055 
00056   if(aType & EMapLineObjectMovementSimple) {
00057     iXVel=aArgs[4];
00058     iFlags |= TBadGuyFlags::ESimpleMoves;
00059     if(aType & EMapLineObjectMovementBounceTop)
00060       iFlags |= TBadGuyFlags::EBounceTop;
00061     if(aType & EMapLineObjectMovementBounceBottom)
00062       iFlags |= TBadGuyFlags::EBounceBottom;
00063     if(aType & EMapLineObjectMovementBounceLeft)
00064       iFlags |= TBadGuyFlags::EBounceLeft;
00065     if(aType & EMapLineObjectMovementBounceRight)
00066       iFlags |= TBadGuyFlags::EBounceRight;
00067 
00068   } else if(aType & EMapLineObjectMovementHoming) {
00069     iXVel=aArgs[4];
00070     iFlags |= TBadGuyFlags::ESimpleMoves;
00071     if(aType & EMapLineObjectMovementHomingX)
00072       iFlags |= TBadGuyFlags::EHomingX;
00073     if(aType & EMapLineObjectMovementHomingY)
00074       iFlags |= TBadGuyFlags::EHomingY;
00075 
00076   } else if(aType & EMapLineObjectMovementPath) {
00077     iPath=aArgs[4];
00078     iXVel=0;
00079     iFlags |= TBadGuyFlags::EPathMove;
00080   }
00081   
00082 
00083   if(aType & EMapLineObjectBadGuy) {
00084     iScore=20;
00085     iFlags |= TBadGuyFlags::EKillsPlayer;
00086     iId=aArgs[6];
00087     // negative health means that this item can't be destroyed
00088     // (or is destroyed by shooting something else)
00089     if(iHealth < 0) {
00090       iHealth=-iHealth;
00091       iFlags |= TBadGuyFlags::EInvunerable;
00092     }
00093   } else if(aType & EMapLineObjectCollectable) {
00094     iFlags |= TBadGuyFlags::ETransparent;
00095     // gives player health, bullets don't effect it,
00096     // simple movement,
00097     if(aArgs[6]==0)
00098       iFlags |= TBadGuyFlags::EHealthBonus;
00099     else if(aArgs[6]==1)
00100       iFlags |= TBadGuyFlags::ELifeBonus;
00101     else if(aArgs[6]==2)
00102       iFlags |= TBadGuyFlags::EWeaponBonus;
00103   }
00104 }
00105 
00106 
00170 void TBadGuy::Move(TInt aPlayerX, TInt aPlayerY,
00171                    const TInt16 *aPaths,CGame &aGame) {
00172   // something that is dieing no movement just an explosion
00173   if(iHealth <= 0) {
00174     iHealth--;
00175     TInt16 spriteno= -(iHealth/2);
00176     spriteno+= aGame.FirstExplosionSprite();
00177     if(spriteno>aGame.LastExplosionSprite())
00178       ClearSprite();
00179     else 
00180       SetSpriteNo(spriteno);
00181 
00182   // things that just keep going in one direction, maybe bounce and maybe home
00183   }  else if(iFlags & TBadGuyFlags::ESimpleMoves) {
00184     SimpleMove(aPlayerX,aPlayerY);
00185 
00186     // things that follow a path
00187   } else if(iFlags & TBadGuyFlags::EPathMove) {
00188     PathMove(aPlayerX,aPlayerY,aPaths,aGame);
00189   }
00190 
00191   // if moving relative to the map then add the map velocity
00192   if(iFlags & TBadGuyFlags::EMapRelative) {
00193     iX+=aGame.MapSpeed();
00194   }
00195 
00196   // if the bad guy ends up off the sides of the offscreen map
00197   if(iY<-24 || iY>200 || iX<0 || iX>336) {
00198     ClearSprite();
00199   }
00200   
00201 }
00202 
00203 
00214 void TBadGuy::PathMove(TInt16 aPlayerX, TInt16 aPlayerY,
00215                        const TInt16 *aPaths, CGame &aGame) {
00216                    
00217   TBool foundMove=EFalse;
00218 
00219   // continue processing path commands until we hit a move command
00220   while(foundMove==EFalse) {
00221     // casting it to TPathLineType enum means we get warnings if
00222     // the switch statement doesn't handle one of the enum values.
00223     switch((TPathLineType) (aPaths[iPath*4])) {
00224     case EPathLineEnd:
00225       // do nothing except exit, really only a marker for level generation tool
00226       foundMove=ETrue;
00227       break;
00228     case EPathLineStart: //  really only a marker for level generation tool
00229       iPath+=aPaths[(iPath*4)+1];
00230       break;
00231       
00232     case EPathLineClone:
00233       {
00234         // other bad guy continues on path from arg 2
00235         // this bad guy continues on path from arg 1
00236         TInt oldpath=iPath+aPaths[(iPath*4)+1];
00237         // set iPath for cloned bad guy
00238         iPath+=aPaths[(iPath*4)+2];
00239         aGame.AddBadGuy(*this);
00240         // now set iPath back for this bad guy
00241         iPath=oldpath;
00242       }
00243       break;
00244 
00245       //movement
00246     case EPathLineMoveBy:
00247       iX+=aPaths[(iPath*4)+2];
00248       iY+=aPaths[(iPath*4)+3];
00249       iPath+=aPaths[(iPath*4)+1];
00250       foundMove=ETrue;
00251       break;
00252     case EPathLineMoveTo:
00253       iX=aPaths[(iPath*4)+2];
00254       iY=aPaths[(iPath*4)+3];
00255       iPath+=aPaths[(iPath*4)+1];
00256       foundMove=ETrue;
00257       break;
00258     case EPathLineMoveStepTo: {
00259       if(iX < aPaths[(iPath*4)+2]) {        
00260         iX += iXVel;
00261         // check we don't overshoot
00262         if(iX > aPaths[(iPath*4)+2])
00263           iX=aPaths[(iPath*4)+2];
00264       } else if(iX > aPaths[(iPath*4)+2]) {
00265         iX -= iXVel;
00266         // check we don't overshoot
00267         if(iX < aPaths[(iPath*4)+2])
00268           iX=aPaths[(iPath*4)+2];
00269       }
00270 
00271       if(iY < aPaths[(iPath*4)+3]) {        
00272         iY += iYVel;
00273         // check we don't overshoot
00274         if(iY > aPaths[(iPath*4)+3])
00275           iY=aPaths[(iPath*4)+3];
00276       } else if(iY > aPaths[(iPath*4)+3]) {
00277         iY -= iYVel;
00278         // check we don't overshoot
00279         if(iY < aPaths[(iPath*4)+3])
00280           iY=aPaths[(iPath*4)+3];
00281       }
00282 
00283       // stay on this command until we get to where we are going
00284       if(iX == aPaths[(iPath*4)+2] &&
00285          iY == aPaths[(iPath*4)+3]) {
00286         iPath+=aPaths[(iPath*4)+1];
00287       }
00288       foundMove=ETrue;
00289       break;
00290     }
00291     case EPathLineMoveSimple:
00292       SimpleMove(aPlayerX,aPlayerY);
00293       iPath+=aPaths[(iPath*4)+1];
00294       foundMove=ETrue;
00295       break;
00296 
00297 
00298 
00299       // conditionals
00300       
00301     case EPathLineIfXVelLess:
00302       if(iXVel < aPaths[(iPath*4)+3]) {
00303         iPath+=aPaths[(iPath*4)+2];
00304       } else {
00305         iPath+=aPaths[(iPath*4)+1];
00306       }
00307       break;
00308     case EPathLineIfXVelGreater:
00309       if(iXVel > aPaths[(iPath*4)+3]) {
00310         iPath+=aPaths[(iPath*4)+2];
00311       } else {
00312         iPath+=aPaths[(iPath*4)+1];
00313       }
00314       break;
00315     case EPathLineIfXVelEqual:
00316       if(iXVel == aPaths[(iPath*4)+3]) {
00317         iPath+=aPaths[(iPath*4)+2];
00318       } else {
00319         iPath+=aPaths[(iPath*4)+1];
00320       }
00321       break;
00322     case EPathLineIfYVelLess:
00323       if(iYVel < aPaths[(iPath*4)+3]) {
00324         iPath+=aPaths[(iPath*4)+2];
00325       } else {
00326         iPath+=aPaths[(iPath*4)+1];
00327       }
00328       break;
00329     case EPathLineIfYVelGreater:
00330       if(iYVel > aPaths[(iPath*4)+3]) {
00331         iPath+=aPaths[(iPath*4)+2];
00332       } else {
00333         iPath+=aPaths[(iPath*4)+1];
00334       }
00335       break;
00336     case EPathLineIfYVelEqual:
00337       if(iYVel == aPaths[(iPath*4)+3]) {
00338         iPath+=aPaths[(iPath*4)+2];
00339       } else {
00340         iPath+=aPaths[(iPath*4)+1];
00341       }
00342       break;
00343       
00344     case EPathLineIfXLess:
00345       if(iX < aPaths[(iPath*4)+3]) {
00346         iPath+=aPaths[(iPath*4)+2];
00347       } else {
00348         iPath+=aPaths[(iPath*4)+1];
00349       }
00350       break;
00351     case EPathLineIfXGreater:
00352       if(iX > aPaths[(iPath*4)+3]) {
00353         iPath+=aPaths[(iPath*4)+2];
00354       } else {
00355         iPath+=aPaths[(iPath*4)+1];
00356       }
00357       break;
00358     case EPathLineIfXEqual:
00359       if(iX == aPaths[(iPath*4)+3]) {
00360         iPath+=aPaths[(iPath*4)+2];
00361       } else {
00362         iPath+=aPaths[(iPath*4)+1];
00363       }
00364       break;
00365     case EPathLineIfYLess:
00366       if(iY < aPaths[(iPath*4)+3]) {
00367         iPath+=aPaths[(iPath*4)+2];
00368       } else {
00369         iPath+=aPaths[(iPath*4)+1];
00370       }
00371       break;
00372     case EPathLineIfYGreater:
00373       if(iY > aPaths[(iPath*4)+3]) {
00374         iPath+=aPaths[(iPath*4)+2];
00375       } else {
00376         iPath+=aPaths[(iPath*4)+1];
00377       }
00378       break;
00379     case EPathLineIfYEqual:
00380       if(iY == aPaths[(iPath*4)+3]) {
00381         iPath+=aPaths[(iPath*4)+2];
00382       } else {
00383         iPath+=aPaths[(iPath*4)+1];
00384       }
00385       break;
00386       
00387     case EPathLineIfHealthLess:
00388       if(iHealth < aPaths[(iPath*4)+3]) {
00389         iPath+=aPaths[(iPath*4)+2];
00390       } else {
00391         iPath+=aPaths[(iPath*4)+1];
00392       }
00393       break;
00394     case EPathLineIfHealthGreater:
00395       if(iHealth > aPaths[(iPath*4)+3]) {
00396         iPath+=aPaths[(iPath*4)+2];
00397       } else {
00398         iPath+=aPaths[(iPath*4)+1];
00399       }
00400       break;
00401     case EPathLineIfHealthEqual:
00402       if(iHealth == aPaths[(iPath*4)+3]) {
00403         iPath+=aPaths[(iPath*4)+2];
00404       } else {
00405         iPath+=aPaths[(iPath*4)+1];
00406       }
00407       break;
00408     case EPathLineIfCounterLess:
00409       if(iCounter < aPaths[(iPath*4)+3]) {
00410         iPath+=aPaths[(iPath*4)+2];
00411       } else {
00412         iPath+=aPaths[(iPath*4)+1];
00413       }
00414       break;
00415     case EPathLineIfCounterGreater:
00416       if(iCounter > aPaths[(iPath*4)+3]) {
00417         iPath+=aPaths[(iPath*4)+2];
00418       } else {
00419         iPath+=aPaths[(iPath*4)+1];
00420       }
00421       break;
00422     case EPathLineIfCounterEqual:
00423       if(iCounter == aPaths[(iPath*4)+3]) {
00424         iPath+=aPaths[(iPath*4)+2];
00425       } else {
00426         iPath+=aPaths[(iPath*4)+1];
00427       } 
00428      break;
00429       // setting
00430       
00431     case EPathLineSetPoints:
00432       iScore = aPaths[(iPath*4)+2];
00433       iPath+=aPaths[(iPath*4)+1];
00434       break;
00435     case EPathLineSetId:
00436       iId = aPaths[(iPath*4)+2];
00437       iPath+=aPaths[(iPath*4)+1];
00438       break;
00439     case EPathLineSetHealth:
00440       iHealth = aPaths[(iPath*4)+2];
00441       // if health has got to zero die
00442       if(iHealth <= 0) {
00443         Die(aGame);
00444         // dead so end of path,
00445         foundMove=ETrue;
00446       }      
00447       iPath+=aPaths[(iPath*4)+1];
00448       break;
00449     case EPathLineAddHealth:
00450       iHealth += aPaths[(iPath*4)+2];
00451       // if health has got to zero die
00452       if(iHealth <= 0) {
00453         Die(aGame);
00454         // dead so end of path,
00455         foundMove=ETrue;
00456       }      
00457       iPath+=aPaths[(iPath*4)+1];
00458       break;
00459     case EPathLineSetVelocity:
00460       iXVel=aPaths[(iPath*4)+2];
00461       iYVel=aPaths[(iPath*4)+3];      
00462       iPath+=aPaths[(iPath*4)+1];
00463       break;
00464     case EPathLineAddVelocity:
00465       iXVel+=aPaths[(iPath*4)+2];
00466       iYVel+=aPaths[(iPath*4)+3];      
00467       iPath+=aPaths[(iPath*4)+1];
00468       break;
00469     case EPathLineSetSprite:
00470       SetSpriteNo(aPaths[(iPath*4)+2]);
00471       iPath+=aPaths[(iPath*4)+1];
00472       break;
00473     case EPathLineSetClearFlags:
00474       iFlags |= aPaths[(iPath*4)+2];
00475       iFlags &= ~(aPaths[(iPath*4)+3]);
00476       iPath+=aPaths[(iPath*4)+1];
00477       break;
00478     case EPathLineSetCounter:
00479       iCounter = aPaths[(iPath*4)+2];
00480       iPath+=aPaths[(iPath*4)+1];
00481       break;
00482     case EPathLineAddCounter:
00483       iCounter += aPaths[(iPath*4)+2];
00484       iPath+=aPaths[(iPath*4)+1];
00485       break;
00486 
00487     }
00488   }
00489 }
00490 
00500 void TBadGuy::SimpleMove(TInt16 aPlayerX, TInt16 aPlayerY) {
00501   if(iFlags & TBadGuyFlags::EHomingX) {
00502     if(iX < aPlayerX) {        
00503       iX += iXVel;
00504       if(iX > aPlayerX)
00505         iX=aPlayerX;
00506     } else if(iX > aPlayerX) {
00507       iX -= iXVel;
00508       if(iX < aPlayerX)
00509         iX=aPlayerX;
00510       }
00511   } else {
00512     iX+=iXVel;
00513     if(  (iX>303 && (iFlags & TBadGuyFlags::EBounceRight)) ||
00514          (iX<16 && (iFlags & TBadGuyFlags::EBounceLeft))) {
00515       iXVel= -iXVel;
00516       iX+= iXVel;
00517     }  
00518   }
00519 
00520   if(iFlags & TBadGuyFlags::EHomingY) {
00521     if(iY < aPlayerY) {        
00522       iY += iYVel;
00523       if(iY > aPlayerY)
00524           iY=aPlayerY;
00525     } else if(iY > aPlayerY) {
00526       iY -= iYVel;
00527       if(iY < aPlayerY)
00528         iY=aPlayerY;
00529     }
00530   } else {
00531     iY+=iYVel;
00532     if((iY<0 && (iFlags & TBadGuyFlags::EBounceTop)) ||
00533        (iY>176 && (iFlags & TBadGuyFlags::EBounceBottom))) {
00534       iYVel= -iYVel;
00535       iY+= iYVel;
00536     }            
00537   }
00538 }
00539 
00549 void TBadGuy::HitBullet(TBullet& aBullet, CGame &aGame) {
00550   if(iHealth<=0)
00551      return;
00552 
00553   if(iFlags & TBadGuyFlags::EInvunerable) {
00554     // these just absord bullets
00555     aBullet.ClearSprite();
00556   } else if(iFlags & TBadGuyFlags::ETransparent) {
00557     // has no effect on bullets and vice versa
00558   } else {
00559     // damage done can't be more than bad guys health,
00560     // damage done is subtracted from bad guys health and bullets health
00561     TInt damageTaken=aBullet.Health();
00562     if(damageTaken > iHealth)
00563       damageTaken=iHealth;
00564 
00565     if(damageTaken<0) {
00566       TGamePanics::Panic(TGamePanics::ENegativeDamage);
00567     }
00568     
00569     aBullet.AddHealth(-damageTaken);
00570 
00571     if(iId > 0) {
00572       aGame.DamageBadGuys(iId,damageTaken);
00573     } else if(iId < 0) {
00574       // negative ids don't get damaged when other parts get hit
00575       // so damage this one directly,
00576       aGame.DamageBadGuys(-iId,damageTaken);
00577       Damage(damageTaken,aGame);
00578     } else {
00579       Damage(damageTaken,aGame);
00580     }
00581   }
00582 }
00583 
00593 void TBadGuy::HitShip(TPlayersShip &aShip, CGame &aGame) {
00594   if(iHealth<=0)
00595      return;
00596 
00597   if(iFlags & TBadGuyFlags::EKillsPlayer) {
00598     if(iFlags & TBadGuyFlags::EInvunerable) {
00599       aShip.SetHealth(0);
00600     } else {
00601       aShip.AddHealth(-iHealth);
00602     }
00603 
00604     // if this is a multi part bad guy we need to damage the other
00605     // parts.
00606     if(iId > 0) {
00607       aGame.DamageBadGuys(iId,iHealth);
00608     } else if(iId < 0) {
00609       // negative ids don't get damaged when other parts get hit
00610       // so damage this one directly,
00611       aGame.DamageBadGuys(-iId,iHealth);
00612       Damage(iHealth,aGame);
00613     } else {
00614       Damage(iHealth,aGame);
00615     }
00616 
00617     
00618   } else {
00619     if(iFlags & TBadGuyFlags::EHealthBonus) {
00620       aShip.AddHealth(iHealth);
00621     }
00622     if(iFlags & TBadGuyFlags::ELifeBonus) {
00623       aGame.Bonus(CGame::EBonusLife);
00624     }
00625     if(iFlags & TBadGuyFlags::EWeaponBonus) {
00626       aGame.Bonus(CGame::EBonusPowerup);
00627     }
00628     Die(aGame);
00629   }
00630 }
00631 
00638 void TBadGuy::Damage(TInt aHealth, CGame &aGame) {
00639   iHealth-= aHealth;
00640   if(iHealth <=0) {
00641     Die(aGame);
00642   }  
00643 }
00644 
00653 void TBadGuy::Die(CGame &aGame) {
00654   iHealth=0;
00655   if(iFlags & TBadGuyFlags::EKillsPlayer) {
00656     aGame.AddScore(iScore);
00657   } else {
00658     ClearSprite();
00659   }
00660 }
00661 
00667 TInt16 TBadGuy::Id() {
00668   return iId;
00669 }
00670 

Documentation for Game (Beta) version 1.44.