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

📄 chars.cpp

📁 [游戏开发参考书-用DirectX编写RPG游戏]这是一个系列的丛书如果你都看并且懂的话你就可以你工作啦!
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                            Character->TargetChar->ZPos);
        Dist = XDiff*XDiff + YDiff*YDiff + ZDiff*ZDiff;

        // Update if closer then distance
        if(Dist < (Character->Distance*Character->Distance)) {

          // Setup movement away from target
          Dist = (float)sqrt(Dist);
          if(Speed > Dist)
            Speed = Dist;
          MoveX = -(Character->TargetChar->XPos -             \
                 Character->XPos) / Dist * Speed;
          MoveZ = -(Character->TargetChar->ZPos -             \
                 Character->ZPos) / Dist * Speed;

          // Set new direction
          Character->Direction = (float)atan2(MoveX, MoveZ);

          // Set new action
          Character->Action = CHAR_MOVE;
        }
      }

      break;
  }

  // Process monster actions if at full charge
  if(Character->Type == CHAR_MONSTER &&                       \
                                Character->Charge >= 100.0f) {

    // Determine chance of attacking
    if((rand() % 100) <= Character->Def.ToAttack) {
      // Scan through list and pick a character
      CharPtr = m_CharacterParent;
      while(CharPtr != NULL) {
        // Randomly pick enabled target (a PC),
        // and make sure the target is not hurt or dead.
        if(CharPtr != Character && CharPtr->Type==CHAR_PC &&  \
           (rand() % 100) < 50 &&                             \
           CharPtr->Enabled == TRUE &&                        \
           CharPtr->Action != CHAR_DIE &&                     \
           CharPtr->Action != CHAR_HURT) {

          // Get distance to target
          XDiff = (float)fabs(Character->XPos - CharPtr->XPos);
          YDiff = (float)fabs(Character->YPos - CharPtr->YPos);
          ZDiff = (float)fabs(Character->ZPos - CharPtr->ZPos);
          Dist  = XDiff * XDiff + YDiff * YDiff + ZDiff * ZDiff;

          // Make sure in range to attack
          Radius = GetXZRadius(Character);
          Radius += Character->Def.Range;

          // Attack if in range
          if((Radius*Radius) >= Dist) {
            // Set attack data
            Character->Victim = CharPtr;
            CharPtr->Attacker = Character;

            // Clear movement
            MoveX = MoveY = MoveZ = 0.0f;

            // Point towards target character
            XDiff = CharPtr->XPos - Character->XPos;
            ZDiff = CharPtr->ZPos - Character->ZPos;
            Character->Direction = (float)atan2(XDiff, ZDiff);

            // Perform attack action
            SetAction(Character, CHAR_ATTACK);

            break;
          }
        }

        // Go to next character
        CharPtr = CharPtr->Next;
      }
    } else

    // Determine chance of spell casting
    if((rand() % 100) <= Character->Def.ToMagic &&            \
                 m_MSL != NULL && m_SpellController != NULL) {

      // Flag no spells cast
      SpellCast = FALSE;

      // If health is less then half, then there's a 50% chance
      // of healing (if the monster knows any heal spells)
      if(Character->HealthPoints <=                           \
                          (Character->Def.HealthPoints / 2)) {

        // Search for a known heal spell
        for(i=0;i<64;i++) {
          if(m_MSL[i].Name[0] &&                              \
             m_MSL[i].Effect == ALTER_HEALTH &&               \
             m_MSL[i].Value[0] > 0.0f &&                      \
             Character->ManaPoints >= m_MSL[i].Cost &&        \
             Character->Def.MagicSpells[i/32] & (1<<(i&31))) {

            // This is the spell, determine chance to heal
            if((rand() % 100) < 50) {
              // Set spell data
              Character->Victim      = Character;
              Character->Attacker    = Character;
              Character->SpellNum    = i;
              Character->SpellTarget = CHAR_MONSTER;
              
              // Store target coordinates
              Character->TargetX = Character->XPos;
              Character->TargetY = Character->YPos;
              Character->TargetZ = Character->ZPos;

              // Clear movement
              MoveX = MoveY = MoveZ = 0.0f;

              // Perform spell action
              SetAction(Character, CHAR_SPELL);

              // Flag spell as cast
              SpellCast = TRUE;

              break;
            }
          }
        }
      }

      // If there are bad status ailments, then there's a 
      // 50% chance of dispeling magic.
      if(Character->Ailments & AILMENT_POISON ||              \
         Character->Ailments & AILMENT_SLEEP ||               \
         Character->Ailments & AILMENT_PARALYZE ||            \
         Character->Ailments & AILMENT_ENCHANTED ||           \
         Character->Ailments & AILMENT_DUMBFOUNDED ||         \
         Character->Ailments & AILMENT_SLOW ||                \
         Character->Ailments & AILMENT_BLIND ||               \
         Character->Ailments & AILMENT_SILENCED &&            \
         SpellCast == FALSE) {
        
        // Search for a known dispel spell
        for(i=0;i<64;i++) {
          if(m_MSL[i].Name[0] &&                              \
             m_MSL[i].Effect == DISPEL_MAGIC &&               \
             Character->ManaPoints >= m_MSL[i].Cost &&        \
             Character->Def.MagicSpells[i/32] & (1<<(i&31))) {

            // This is the spell, determine chance to dispel
            if((rand() % 100) < 50) {
              // Set spell data
              Character->Victim      = Character;
              Character->Attacker    = Character;
              Character->SpellNum    = i;
              Character->SpellTarget = CHAR_MONSTER;
              
              // Store target coordinates
              Character->TargetX = Character->XPos;
              Character->TargetY = Character->YPos;
              Character->TargetZ = Character->ZPos;

              // Clear movement
              MoveX = MoveY = MoveZ = 0.0f;

              // Perform spell action
              SetAction(Character, CHAR_SPELL);

              // Flag spell as cast
              SpellCast = TRUE;

              break;
            }
          }
        }
      } 

      // If now spells already cast, then pick a random one
      if(SpellCast == FALSE) {

        // Pick a random spell to attack with
        SpellNum = rand() % 64;

        // Scan through list until a spell is found the
        // monster can cast.
        for(i=0;i<64;i++) {
          if(m_MSL[SpellNum].Name[0] &&                       \
             Character->Def.MagicSpells[SpellNum / 32] &      \
                                   (1 << (SpellNum & 31)) &&  \
             Character->ManaPoints >= m_MSL[SpellNum].Cost && \
             (rand() % 100) < 50) {

            // Scan through list and pick a character
            CharPtr = m_CharacterParent;
            while(CharPtr != NULL) {

              // Randomly pick an enabled target (a PC), 
              // and make sure the target is not hurt or dead.
              // Also, don't cast self-targeting spells here.
              if(CharPtr != Character &&                      \
                 CharPtr->Type == CHAR_PC &&                  \
                 m_MSL[SpellNum].Target != TARGET_SELF &&     \
                 (rand() % 100) < 50 &&                       \
                 CharPtr->Enabled == TRUE &&                  \
                 CharPtr->Action != CHAR_DIE &&               \
                 CharPtr->Action != CHAR_HURT) {

                // Get heights of attacker and target
                // for line of sight checking
                Character->Object.GetBounds(NULL,NULL,NULL,   \
                                            NULL,&y1,NULL,NULL);
                y1 = (y1 * 0.5f) + Character->YPos;

                CharPtr->Object.GetBounds(NULL,NULL,NULL,     \
                                          NULL,&y2,NULL,NULL);
                y2 = (y2 * 0.5f) + CharPtr->YPos;

                // Get distance to target
                XDiff = (float)fabs(Character->XPos -         \
                                    CharPtr->XPos);
                YDiff = (float)fabs(Character->YPos -         \
                                    CharPtr->YPos);
                ZDiff = (float)fabs(Character->ZPos -         \
                                    CharPtr->ZPos);
                Dist  = XDiff*XDiff+YDiff*YDiff+ZDiff*ZDiff;

                // Reduce distance by character's radius
                Radius = GetXZRadius(CharPtr);
                Dist -= (Radius*Radius);

                // Get spell radius
                Radius = m_MSL[SpellNum].Distance;

                // Make sure target is in range and in sight
                if(LineOfSight(Character, CharPtr,            \
                               Character->XPos, y1,           \
                               Character->ZPos,               \
                               CharPtr->XPos, y2,             \
                               CharPtr->ZPos) &&              \
                   Dist <= (Radius * Radius)) {

                  // Set the spell data
                  Character->Victim      = CharPtr;
                  CharPtr->Attacker      = Character;
                  Character->SpellNum    = SpellNum;
                  Character->SpellTarget = CHAR_PC;

                  // Store target coordinates
                  Character->TargetX = CharPtr->XPos;
                  Character->TargetY = CharPtr->YPos;
                  Character->TargetZ = CharPtr->ZPos;

                  // Face toward target (only if not self)
                  if(m_MSL[SpellNum].Target != TARGET_SELF) {
                    XDiff = CharPtr->XPos - Character->XPos;
                    ZDiff = CharPtr->ZPos - Character->ZPos;
                    Character->Direction =                    \
                                 (float)atan2(XDiff, ZDiff);
                  }

                  // Clear movement
                  MoveX = MoveY = MoveZ = 0.0f;

                  // Set the spell action
                  SetAction(Character, CHAR_SPELL);

                  // Flag spell as cast
                  SpellCast = TRUE;

                  break;
                }
              }

              // Go to next character
              CharPtr = CharPtr->Next;
            }
            break;
          }

          // Go to next spell
          SpellNum = (SpellNum + 1) % 64;
        }
      }

      // If still no spell cast, try casting a known
      // self-enhancing ailment-effecting spell.
      if(SpellCast == FALSE) {
        for(i=0;i<64;i++) {
          if(m_MSL[i].Name[0] &&                              \
             m_MSL[i].Effect == CAUSE_AILMENT &&              \
             Character->ManaPoints >= m_MSL[i].Cost &&        \
             Character->Def.MagicSpells[i/32]&(1<<(i&31)) &&  \
             (rand()%100) < 10) {

            // Make sure it's self-enhancing
            if((long)m_MSL[i].Value[0]&AILMENT_STRONG ||      \
               (long)m_MSL[i].Value[0]&AILMENT_BARRIER ||     \
               (long)m_MSL[i].Value[0]&AILMENT_SUREFOOTED ||  \
               (long)m_MSL[i].Value[0]&AILMENT_FAST ||        \
               (long)m_MSL[i].Value[0]&AILMENT_HAWKEYE) {

              // Make sure ailment not already set
              if(!(Character->Ailments &                      \
                                   (long)m_MSL[i].Value[0])) {

                // Set spell data
                Character->Victim      = Character;
                Character->Attacker    = Character;
                Character->SpellNum    = i;
                Character->SpellTarget = CHAR_MONSTER;
              
                // Store target coordinates
                Character->TargetX = Character->XPos;
                Character->TargetY = Character->YPos;
                Character->TargetZ = Character->ZPos;

                // Clear movement
                MoveX = MoveY = MoveZ = 0.0f;

                // Perform spell action
                SetAction(Character, CHAR_SPELL);

                break;
              }
            }
          }
        }
      }
    }
  }

  // Store movement and return
  *XMove = MoveX;
  *YMove = MoveY;
  *ZMove = MoveZ;

  return TRUE;
}

BOOL cCharacterController::CheckMove(sCharacter *Character,   \
               float *XMove, float *YMove, float *ZMove)
{
  sCharacter *CharPtr;
  float XDiff, YDiff, ZDiff, Dist;
  float Radius1, Radius2;
  float XPos, YPos, ZPos;
  float MinX, MaxX, MinZ, MaxZ;

  // Error checking
  if(Character == NULL)
    return FALSE;  // Don't allow movement

  XPos = Character->XPos + (*XMove);
  YPos = Character->YPos + (*YMove);
  ZPos = Character->ZPos + (*ZMove);

  // Get character's X/Z radius
  Character->Object.GetBounds(&MinX, NULL, &MinZ,             \
                              &MaxX, NULL, &MaxZ, NULL);
  Radius1 = max(MaxX-MinX, MaxZ-MinZ) * 0.5f;

  // Check movement against other characters
  if((CharPtr = m_CharacterParent) != NULL) {
    while(CharPtr != NULL) {

      // Don't check against self or disabled characters
      if(Character != CharPtr && CharPtr->Enabled == TRUE) {
        // Don't check against other PC characters
        if(Character->Type == CHAR_PC &&                      \
           CharPtr->Type == CHAR_PC)
          break;
        
        // Get distance between characters
        XDiff = (float)fabs(XPos - CharPtr->XPos);
        YDiff = (float)fabs(YPos - CharPtr->YPos);
        ZDiff = (float)fabs(ZPos - CharPtr->ZPos);
        Dist = XDiff*XDiff + YDiff*YDiff + ZDiff*ZDiff;

        // Get checking character's X/Z bounding radius
        CharPtr->Object.GetBounds(&MinX, NULL, &MinZ,         \
                                  &MaxX, NULL, &MaxZ, NULL);
        Radius2 = max(MaxX-MinX, MaxZ-MinZ) * 0.5f;

        // Don't allow movement if intersecting
        if(Dist <= (Radius1*Radius1 + Radius2*Radius2))
          return FALSE;
      }

      CharPtr = CharPtr->Next;
    }
  }

  // Bounds check movement if MinX != MaxX
  if(Character->MinX != Character->MaxX) {
    if(XPos < Character->MinX || XPos > Character->MaxX)
      *XMove = 0.0f;
    if(YPos < Character->MinY || YPos > Character->MaxY)
      *YMove = 0.0f;
    if(ZPos < Character->MinZ || ZPos > Character->MaxZ)
      *ZMove = 0.0f;

    // Return no movement at all
    if(!(*XMove) && !(*YMove) && !(*ZMove))
      return FALSE;
  }

  // Call overloaded check custom collisions (maps, etc)
  if(ValidateMove(Character, XMove, YMove, ZMove) == FALSE)
    return FALSE;  // Don't allow movement

  return TRUE;
}

BOOL cCharacterController::ProcessUpdate(                     \
                      sCharacter *Character,
                      float XMove, float YMove, float ZMove)
{
  // Move character
  Character->XPos += XMove;
  Character->YPos += YMove;
  Character->ZPos += ZMove;

  // Move object and point in direction
  Character->Object.Move(Character->XPos,                     \
                         Character->YPos,                     \
                         Character->ZPos);                    \
  Character->Object.Rotate(0.0f, Character->Direction, 0.0f);

  // Set new animation
  if(Character->LastAnim != Character->Action) {
    Character->LastAnim = Character->Action;

    if(m_NumAnimations && m_Animations != NULL) {
      Character->LastAnimTime = timeGetTime() / 30;
      Character->Object.SetAnimation(                         \
                 &m_Meshes[Character->Def.MeshNum].Animation, \
                 m_Animations[Character->Action].Name,        \
                 Character->LastAnimTime);
    }
  }

⌨️ 快捷键说明

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