⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tbadguy.cpp

📁 symbian 的一个 二维飞行游戏 源码 及相关技术文章
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Copyright 2002 Kenneth Guy,
// 
// TBadGuy.cpp

/** \file TBadGuy.cpp

    implementation of class TBadGuy */

#include "TBadGuy.h"
#include "TPlayersShip.h"
#include "TBullet.h"
#include "CGame.h"
#include "TGamePanics.h"

#include "TMapLineType.h"
#include "TPathLineType.h"

/** Constructor */
TBadGuy::TBadGuy() {

}

/** Initialize a new bad guy from map data
    
    \param aType type of map line data, see #TMapLineType
    \param aArgs[0] sprite number of bad guy
    \param aArgs[1] initial X position of bad guy
    \param aArgs[2] initial Y position of bad guy
    \param aArgs[3] Health of bad guy
    \param aArgs[4] XVel or first path command for EPathMove bad guys
    \param aArgs[5] YVel
    \param aArgs[6] BonusType for collectable bad guys or iId for multi part bad guys

 */
void TBadGuy::Init(TInt16 aType,const  TInt16 aArgs[]) {
  SetSpriteNo(aArgs[0]);
  iX=aArgs[1];
  iY=aArgs[2];
  iHealth=aArgs[3];
  iXVel=0;
  iYVel=aArgs[5];
  iFlags=0;
  iPath=0;
  iId=0;
  iCounter=0;

  if(aType & EMapLineObjectMovementMapRelative) {
    iFlags |= TBadGuyFlags::EMapRelative;
  }

  if(aType & EMapLineObjectMovementSimple) {
    iXVel=aArgs[4];
    iFlags |= TBadGuyFlags::ESimpleMoves;
    if(aType & EMapLineObjectMovementBounceTop)
      iFlags |= TBadGuyFlags::EBounceTop;
    if(aType & EMapLineObjectMovementBounceBottom)
      iFlags |= TBadGuyFlags::EBounceBottom;
    if(aType & EMapLineObjectMovementBounceLeft)
      iFlags |= TBadGuyFlags::EBounceLeft;
    if(aType & EMapLineObjectMovementBounceRight)
      iFlags |= TBadGuyFlags::EBounceRight;

  } else if(aType & EMapLineObjectMovementHoming) {
    iXVel=aArgs[4];
    iFlags |= TBadGuyFlags::ESimpleMoves;
    if(aType & EMapLineObjectMovementHomingX)
      iFlags |= TBadGuyFlags::EHomingX;
    if(aType & EMapLineObjectMovementHomingY)
      iFlags |= TBadGuyFlags::EHomingY;

  } else if(aType & EMapLineObjectMovementPath) {
    iPath=aArgs[4];
    iXVel=0;
    iFlags |= TBadGuyFlags::EPathMove;
  }
  

  if(aType & EMapLineObjectBadGuy) {
    iScore=20;
    iFlags |= TBadGuyFlags::EKillsPlayer;
    iId=aArgs[6];
    // negative health means that this item can't be destroyed
    // (or is destroyed by shooting something else)
    if(iHealth < 0) {
      iHealth=-iHealth;
      iFlags |= TBadGuyFlags::EInvunerable;
    }
  } else if(aType & EMapLineObjectCollectable) {
    iFlags |= TBadGuyFlags::ETransparent;
    // gives player health, bullets don't effect it,
    // simple movement,
    if(aArgs[6]==0)
      iFlags |= TBadGuyFlags::EHealthBonus;
    else if(aArgs[6]==1)
      iFlags |= TBadGuyFlags::ELifeBonus;
    else if(aArgs[6]==2)
      iFlags |= TBadGuyFlags::EWeaponBonus;
  }
}


/** Move a bad guy.

    This either moves the bad guy, or animates the explosion if the
    bad guy is dieing.

    \param aPlayerX X position of player for homing bad guys
    \param aPlayerY Y position of player for homing bad guys
    \param aPaths path data for path following bad guys
    \param aGame used to add new lives/ bad guys etc

    If the bad guy ends up outside the screen area the bad guy
    is cleared.

    For simple bad guys this just works out the new position
    from the current X,Y, velocitys and for homing the players position.

    For path following bad guys is executes all the path commands from
    iPath that are settings type commands (set health/ set sprite no etc.)
    then executes one movement type command (move to X,Y etc).

    A simple path would be:
\verbatim
  EPathLineMoveTo,1,270,0,            // move to 270,0
  EPathLineSetVelocity,1,2,2,         // iXVel=2 iYVel=2
  EPathLineMoveStepTo,1,30,0,         // move to 30,0 in steps of iXVel
  EPathLineMoveStepTo,1,30,90,        // move to 30,90 in steps of iYVel
  EPathLineSetClearFlags,1,  TBadGuyFlags::EHomingX    | // set homing flags
                             TBadGuyFlags::EHomingY, 0,
  EPathLineMoveSimple,0,0,0, // repeat homing forever (next offset=0)
\endverbatim

    An animated bouncing bad guy would be:
\verbatim
  // path offset 64
  // set up velocity and bouncing
  EPathLineSetVelocity,1,1,1, 
  EPathLineSetClearFlags,1,  TBadGuyFlags::EBounceTop    |
                             TBadGuyFlags::EBounceBottom |
                             TBadGuyFlags::EBounceLeft   |
                             TBadGuyFlags::EBounceRight, 0,
  // loop bouncing and changing sprites
  EPathLineSetSprite,1,16,0, // set sprite to 16
  EPathLineMoveSimple,1,0,0, // move a bit
  EPathLineMoveSimple,1,0,0, 
  EPathLineSetSprite,1,31,0, // set sprite to 31
  EPathLineMoveSimple,1,0,0, // move a bit
  EPathLineMoveSimple,1,0,0,
  EPathLineSetSprite,1,32,0, // etc.
  EPathLineMoveSimple,1,0,0,
  EPathLineMoveSimple,1,0,0,
  EPathLineSetSprite,1,33,0,
  EPathLineMoveSimple,1,0,0,
  EPathLineMoveSimple,1,0,0,
  EPathLineMoveSimple,1,0,0, // etc.
  EPathLineSetSprite,1,32,0,
  EPathLineMoveSimple,1,0,0,
  EPathLineSetSprite,1,31,0,
  EPathLineMoveSimple,1,0,0,
  EPathLineMoveSimple,-17,0,0, // move and jump back to set sprite to 16 line
\endverbatim
    
*/

void TBadGuy::Move(TInt aPlayerX, TInt aPlayerY,
                   const TInt16 *aPaths,CGame &aGame) {
  // something that is dieing no movement just an explosion
  if(iHealth <= 0) {
    iHealth--;
    TInt16 spriteno= -(iHealth/2);
    spriteno+= aGame.FirstExplosionSprite();
    if(spriteno>aGame.LastExplosionSprite())
      ClearSprite();
    else 
      SetSpriteNo(spriteno);

  // things that just keep going in one direction, maybe bounce and maybe home
  }  else if(iFlags & TBadGuyFlags::ESimpleMoves) {
    SimpleMove(aPlayerX,aPlayerY);

    // things that follow a path
  } else if(iFlags & TBadGuyFlags::EPathMove) {
    PathMove(aPlayerX,aPlayerY,aPaths,aGame);
  }

  // if moving relative to the map then add the map velocity
  if(iFlags & TBadGuyFlags::EMapRelative) {
    iX+=aGame.MapSpeed();
  }

  // if the bad guy ends up off the sides of the offscreen map
  if(iY<-24 || iY>200 || iX<0 || iX>336) {
    ClearSprite();
  }
  
}


/** Bad Guys that follow paths.

    \param aPlayerX players position for homing bad commands
    \param aPlayerY players position for homing bad commands
    \param aPaths path commands
    \param aGame for adding bad guys and points

    see Move() and #TPathLineType for details of path commands.
*/

void TBadGuy::PathMove(TInt16 aPlayerX, TInt16 aPlayerY,
                       const TInt16 *aPaths, CGame &aGame) {
                   
  TBool foundMove=EFalse;

  // continue processing path commands until we hit a move command
  while(foundMove==EFalse) {
    // casting it to TPathLineType enum means we get warnings if
    // the switch statement doesn't handle one of the enum values.
    switch((TPathLineType) (aPaths[iPath*4])) {
    case EPathLineEnd:
      // do nothing except exit, really only a marker for level generation tool
      foundMove=ETrue;
      break;
    case EPathLineStart: //  really only a marker for level generation tool
      iPath+=aPaths[(iPath*4)+1];
      break;
      
    case EPathLineClone:
      {
        // other bad guy continues on path from arg 2
        // this bad guy continues on path from arg 1
        TInt oldpath=iPath+aPaths[(iPath*4)+1];
        // set iPath for cloned bad guy
        iPath+=aPaths[(iPath*4)+2];
        aGame.AddBadGuy(*this);
        // now set iPath back for this bad guy
        iPath=oldpath;
      }
      break;

      //movement
    case EPathLineMoveBy:
      iX+=aPaths[(iPath*4)+2];
      iY+=aPaths[(iPath*4)+3];
      iPath+=aPaths[(iPath*4)+1];
      foundMove=ETrue;
      break;
    case EPathLineMoveTo:
      iX=aPaths[(iPath*4)+2];
      iY=aPaths[(iPath*4)+3];
      iPath+=aPaths[(iPath*4)+1];
      foundMove=ETrue;
      break;
    case EPathLineMoveStepTo: {
      if(iX < aPaths[(iPath*4)+2]) {        
        iX += iXVel;
        // check we don't overshoot
        if(iX > aPaths[(iPath*4)+2])
          iX=aPaths[(iPath*4)+2];
      } else if(iX > aPaths[(iPath*4)+2]) {
        iX -= iXVel;
        // check we don't overshoot
        if(iX < aPaths[(iPath*4)+2])
          iX=aPaths[(iPath*4)+2];
      }

      if(iY < aPaths[(iPath*4)+3]) {        
        iY += iYVel;
        // check we don't overshoot
        if(iY > aPaths[(iPath*4)+3])
          iY=aPaths[(iPath*4)+3];
      } else if(iY > aPaths[(iPath*4)+3]) {
        iY -= iYVel;
        // check we don't overshoot
        if(iY < aPaths[(iPath*4)+3])
          iY=aPaths[(iPath*4)+3];
      }

      // stay on this command until we get to where we are going
      if(iX == aPaths[(iPath*4)+2] &&
         iY == aPaths[(iPath*4)+3]) {
        iPath+=aPaths[(iPath*4)+1];
      }
      foundMove=ETrue;
      break;
    }
    case EPathLineMoveSimple:
      SimpleMove(aPlayerX,aPlayerY);
      iPath+=aPaths[(iPath*4)+1];
      foundMove=ETrue;
      break;



      // conditionals
      
    case EPathLineIfXVelLess:
      if(iXVel < aPaths[(iPath*4)+3]) {
        iPath+=aPaths[(iPath*4)+2];
      } else {
        iPath+=aPaths[(iPath*4)+1];
      }
      break;
    case EPathLineIfXVelGreater:
      if(iXVel > aPaths[(iPath*4)+3]) {
        iPath+=aPaths[(iPath*4)+2];
      } else {
        iPath+=aPaths[(iPath*4)+1];
      }
      break;
    case EPathLineIfXVelEqual:
      if(iXVel == aPaths[(iPath*4)+3]) {
        iPath+=aPaths[(iPath*4)+2];
      } else {
        iPath+=aPaths[(iPath*4)+1];
      }
      break;
    case EPathLineIfYVelLess:
      if(iYVel < aPaths[(iPath*4)+3]) {
        iPath+=aPaths[(iPath*4)+2];
      } else {
        iPath+=aPaths[(iPath*4)+1];
      }
      break;
    case EPathLineIfYVelGreater:
      if(iYVel > aPaths[(iPath*4)+3]) {
        iPath+=aPaths[(iPath*4)+2];
      } else {
        iPath+=aPaths[(iPath*4)+1];
      }
      break;
    case EPathLineIfYVelEqual:
      if(iYVel == aPaths[(iPath*4)+3]) {
        iPath+=aPaths[(iPath*4)+2];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -