void ChoosePath(Unit &ghost) { int choices = CanMoveTo(ghost, Right) + CanMoveTo(ghost, Left) + CanMoveTo(ghost, Up) + CanMoveTo(ghost, Down); if(ghost.Rotating == false && choices >= 3) { Direction backwards = Invert(ghost.Face); do { ghost.Face = (Direction) (rand() % 4); } while(CanMove(ghost) == false || ghost.Face == backwards); ghost.Rotating = true; } }
shared_ptr<ZombieInstanceBase> ZombieInstance::Spawn(PlayerInstance& targetPlayer, const vector<shared_ptr<ZombieInstanceBase>>& zombies) { ModelParameters zombieParameters; do { zombieParameters = GetRandomZombieParameters(targetPlayer); } while (!CanMoveTo(DirectX::XMFLOAT2(zombieParameters.position.x, zombieParameters.position.z), zombies, nullptr)); return shared_ptr<ZombieInstanceBase>(new ZombieInstance(zombieParameters, targetPlayer, zombies)); }
std::vector<AStarDungeon::Node> AStarDungeon::GetSuccessors(const AStarDungeon::Node &node) const { Node up = node; ++up.y; Node right = node; ++right.x; Node down = node; --down.y; Node left = node; --left.x; std::vector<Node> successors = { up, right, down, left }; // get rid of untraversable tiles auto canMoveToLambda = [this](Node &n) { return !CanMoveTo(n); }; successors.erase(std::remove_if(successors.begin(), successors.end(), canMoveToLambda), successors.end()); return successors; }
void ZombieInstance::Update(const RenderParameters& renderParameters) { ZombieStates targetState; auto emitterPosition = m_Parameters.position; emitterPosition.y += 1.6f; m_AudioEmitter.SetPosition(m_Parameters.position, DirectX::XMFLOAT3(0.0f, 0.0f, 0.0f)); float distanceToPlayerSqr; if (!m_IsDead) { auto playerPosition = m_TargetPlayer.GetPosition(); auto angleY = -atan2(m_Parameters.position.z - playerPosition.z, m_Parameters.position.x - playerPosition.x) - DirectX::XM_PI / 2.0f; if (m_TargetPlayer.GetGameState() == GameState::Playing) { DirectX::XMFLOAT2 vectorToPlayer(playerPosition.x - m_Parameters.position.x, playerPosition.z - m_Parameters.position.z); distanceToPlayerSqr = vectorToPlayer.x * vectorToPlayer.x + vectorToPlayer.y * vectorToPlayer.y; if (distanceToPlayerSqr > 1.5f) { if (distanceToPlayerSqr > 100.0f * 100.0f) { m_IsDead = true; System::GetInstance().RemoveModel(this); return; } else { auto vectorMultiplier = m_Speed * renderParameters.frameTime / sqrt(distanceToPlayerSqr); DirectX::XMFLOAT2 newPosition(m_Parameters.position.x + vectorMultiplier * vectorToPlayer.x, m_Parameters.position.z + vectorMultiplier * vectorToPlayer.y); if (CanMoveTo(newPosition, m_Zombies, this)) { targetState = ZombieStates::Running; m_Parameters.position.x = newPosition.x; m_Parameters.position.z = newPosition.y; } else { targetState = ZombieStates::Idle; } } } else { targetState = ZombieStates::Hitting; if (renderParameters.time - m_LastMadeNearPlayerSound >= kNearPlayerSoundInterval) { m_LastMadeNearPlayerSound = renderParameters.time; m_NearPlayerSound.Play3D(m_AudioEmitter); } } } else { targetState = ZombieStates::Idle; } SetRotation(DirectX::XMFLOAT3(0.0f, angleY, 0.0f)); } else { targetState = ZombieStates::Death; if (renderParameters.time - m_DeathTime > kZombieBodyLastingTime) { System::GetInstance().RemoveModel(this); } } Assert(targetState >= 0 && targetState < ZombieStates::StateCount); m_AnimationStateMachine.Update(renderParameters, targetState); if (m_AnimationStateMachine.GetCurrentAnimationState() == ZombieStates::Hitting && !m_AnimationStateMachine.IsTransitioningAnimationStates() && m_AnimationStateMachine.GetCurrentStateAnimationProgress() > 0.1f && m_AnimationStateMachine.GetCurrentStateAnimationProgress() < 0.2f && renderParameters.time - m_LastHitPlayerAt >= kZombieHitInterval) { m_LastHitPlayerAt = renderParameters.time; m_TargetPlayer.TakeDamage(Tools::Random::GetNextReal<float>(0.03f, 0.1f)); m_PunchSound.Play3D(m_AudioEmitter); } else if (renderParameters.time - m_LastFootStep >= kFootStepInterval && m_AnimationStateMachine.GetCurrentAnimationState() == ZombieStates::Running && !m_AnimationStateMachine.IsTransitioningAnimationStates() && distanceToPlayerSqr < 100.0f) { m_LastFootStep = renderParameters.time; m_FootStepSound.Play3D(m_AudioEmitter, 8.0f); } }
//***************************************************************************** void CSerpent::GetNormalMovement( // Figures out the normal movement of the serpent when not affected by a brain. // //Params: int &dx, //(out) Horizontal delta (-1, 0, or 1) for where monster // can go, taking into account obstacles. int &dy) //(out) Vertical delta (-1, 0, or 1) for same. const { // If swordsman is ahead or behind the serpent, keep moving toward him. // Otherwise, switch between favoring horizonal or vertical movement // every five turns. const bool horizontal = ((this->pCurrentGame->wSpawnCycleCount % 10) < 5); const int oX = nGetOX(wO); const int oY = nGetOY(wO); if (CanFindSwordsman()) { //Is swordsman in front of or behind serpent? if (!oX) { //serpent is moving vertically if (this->pCurrentGame->swordsman.wX == this->wX) { //Yes. Keep moving this direction. dy = oY; dx = 0; if (CanMoveTo(this->wX + dx, this->wY + dy)) return; } } else { //serpent moving horizontally if (this->pCurrentGame->swordsman.wY == this->wY) { dx = oX; dy = 0; if (CanMoveTo(this->wX + dx, this->wY + dy)) return; } } // Move towards swordsman. if (horizontal) { dx = sgn(this->pCurrentGame->swordsman.wX - this->wX); if (dx == 0) dy = sgn(this->pCurrentGame->swordsman.wY - this->wY); else dy = 0; } else { dy = sgn(this->pCurrentGame->swordsman.wY - this->wY); if (dy == 0) dx = sgn(this->pCurrentGame->swordsman.wX - this->wX); else dx = 0; } // Check the coordinates if (CanMoveTo(this->wX + dx, this->wY + dy)) return; //move here } // We can't move towards the swordsman in the desired manner. // Try the four cardinal directions static const int directions[] = {N, E, S, W}; bool found = false; for (int i = 0; !found && i < 4; i++) { dx = nGetOX(directions[i]); dy = nGetOY(directions[i]); // Don't backtrack if (dx == -oX && dy == -oY) continue; if (CanMoveTo(this->wX + dx, this->wY + dy)) found = true; } if (!found) dx = dy = 0; //stuck }