Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "Base\stdafx.h"
- #include "Enemy.h"
- #include "Components\Components.h"
- #include "Prefabs\Prefabs.h"
- #include "Scenegraph\GameScene.h"
- #include "Physx/PhysxManager.h"
- #include "Physx/PhysxProxy.h"
- #include "Diagnostics/Logger.h"
- #include "Components\ModelComponent.h"
- #include "Components\ParticleEmitterComponent.h"
- #include "Graphics\ModelAnimator.h"
- #include "LevelScene.h"
- #include "Character.h"
- static const XMFLOAT3 MATERIAL(0.5f, 0.5f, 0.2f);
- static const XMFLOAT3 GUNROTATE(0.f,180.f,0.f);
- static const XMFLOAT3 GUNTRANSLATE(12.f,6.f,-12.f);
- static const float HEIGHT=0.8f;
- static const float GUNSCALE=0.075f;
- static const float MODELSCALE=0.25f;
- static const float HEIGHTHEAD=0.60f;
- static const float SHOOTDISTANCE=20.f;
- static const float SPRINTING=4.f;
- static const float LOOKALARMLEVEL=0.25f;
- static const float SHOOTALARMLEVEL=0.75f;
- static const float FLARETIMER=0.03f;
- static const float SHOOTTIMER=0.75f;
- static const float ALARMLEVELSTARTINPACT=1.f;
- static const float ALARMLEVELSPEEDCAP=3.f;
- static const float ALARMLEVELRANDOMROTATION=2.f;
- static const float ALARMLEVELRANDOMROTATIONCAP=1.5f;
- static const float ANIMATIONSPEED=0.02f;
- static const float OTHERENEMYDISTANCE=250.f;
- static const int ASTANDING=0;
- static const int ARUNNING=1;
- static const int AROTATING=2;
- Enemy::Enemy(LevelScene* levelScene,float* alarmLevel, bool doesLoop,float radius, float height, float moveSpeed) :
- m_Velocity(0,0,0),
- m_pController(nullptr),
- m_pModel(nullptr),
- m_pLevelScene(levelScene),
- m_pEmitter(nullptr),
- m_pAlarmLevel(alarmLevel),
- m_TotalYaw(0),
- m_RotationSpeed(90.f),
- m_MoveSpeed(moveSpeed),
- m_Radius(radius),
- m_Height(height),
- m_WatchAngle(45.f),
- m_RotateAngle(0.f),
- m_RandomTurningMeter(0),
- m_ShootTimer(0),
- m_FlareTimer(0),
- m_MaxRunVelocity(55.0f),
- m_TerminalVelocity(50),
- m_Gravity(100.f),
- m_RunAccelerationTime(0.3f),
- m_JumpAccelerationTime(0.8f),
- m_RunAcceleration(m_MaxRunVelocity/m_RunAccelerationTime),
- m_JumpAcceleration(m_Gravity/m_JumpAccelerationTime),
- m_RunVelocity(0),
- m_JumpVelocity(0),
- m_CurrentGoal(0),
- m_GotCollisionWithOther(false),
- m_PositiveDirection(true),
- m_Detected(false),
- m_GotTarget(false),
- m_DoesLoop(doesLoop),
- m_RunIntoOtherEnemy(false),
- m_AlignedWithCheckPoint(true),
- m_SetToBeDeleted(false)
- {
- }
- Enemy::~Enemy(void)
- {
- }
- void Enemy::Initialize(const GameContext& gameContext)
- {
- UNREFERENCED_PARAMETER(gameContext);
- auto physX = PhysxManager::GetInstance()->GetPhysics();
- auto bouncyMaterial = physX->createMaterial(MATERIAL.x,MATERIAL.y,MATERIAL.z);
- // Create controller
- m_pController = new ControllerComponent(bouncyMaterial,m_Radius,m_Height);
- AddComponent(m_pController);
- auto modelObject= new GameObject();
- m_pModel = new ModelComponent(L"./Resources/Meshes/EnemyAnimated.ovm");
- m_pModel->SetMaterial(LevelScene::Materials::ENEMY);
- modelObject->AddComponent(m_pModel);
- modelObject->GetTransform()->Translate(0,-m_Height*HEIGHT,0);
- modelObject->GetTransform()->Rotate(0,-90,0);
- AddChild(modelObject);
- auto gunObject = new GameObject();
- auto gunModel= new ModelComponent(L"./Resources/Meshes/GunEnemy.ovm");
- gunModel->SetMaterial(LevelScene::Materials::ENEMYGUN);
- gunObject->AddComponent(gunModel);
- gunModel->GetTransform()->Scale(GUNSCALE,GUNSCALE,GUNSCALE);
- gunModel->GetTransform()->Rotate(GUNROTATE);
- gunModel->GetTransform()->Translate(GUNTRANSLATE);
- AddChild(gunObject);
- //Setting direction right
- XMFLOAT3 direction(m_CheckPoints[m_CurrentGoal].Point.x,0.f,m_CheckPoints[m_CurrentGoal].Point.y);
- direction.x-=this->GetTransform()->GetPosition().x;
- direction.z-=this->GetTransform()->GetPosition().z;
- m_TotalYaw=-90;
- GetTransform()->Rotate(0,m_TotalYaw,0,true);
- m_pModel->GetTransform()->Scale(MODELSCALE,MODELSCALE,MODELSCALE);
- auto emiterObject= new GameObject();
- m_pEmitter= new ParticleEmitterComponent(L"./Resources/Textures/Flare.png",5);
- m_pEmitter->SetVelocity(XMFLOAT3(0.f,0.f,0.f));
- m_pEmitter->SetMinSize(0.5f);
- m_pEmitter->SetMaxSize(1.f);
- m_pEmitter->SetMinEnergy(0.05f);
- m_pEmitter->SetMaxEnergy(0.1f);
- m_pEmitter->SetMinSizeGrow(-0.5f);
- m_pEmitter->SetMaxSizeGrow(-0.1f);
- m_pEmitter->SetMinEmitterRange(0.1f);
- m_pEmitter->SetMaxEmitterRange(0.2f);
- m_pEmitter->SetColor(XMFLOAT4(1.f, 1.f, 1.f, 0.1f));
- m_pEmitter->CanEmitParticles(false);
- emiterObject->AddComponent(m_pEmitter);
- gunObject->AddChild(emiterObject);
- emiterObject->GetTransform()->Translate(-120.f,50.f,0);
- }
- void Enemy::PostInitialize(const GameContext& gameContext)
- {
- UNREFERENCED_PARAMETER(gameContext);
- m_pModel->GetAnimator()->SetAnimation(AROTATING);
- }
- void Enemy::Update(const GameContext& gameContext)
- {
- //Check if needs to update
- if(m_pLevelScene->IsPaused())return;
- if(m_pLevelScene->IsGameOver())
- {
- m_pModel->GetAnimator()->Pause();
- return;
- }
- if(m_SetToBeDeleted)
- {
- return;
- }
- float dTime = gameContext.pGameTime->GetElapsed();
- //Fire particles
- if(m_FlareTimer>0)
- {
- m_FlareTimer-=dTime;
- if(m_FlareTimer<=0)
- {
- m_pEmitter->CanEmitParticles(false);
- m_FlareTimer=0;
- }
- }
- //Set rotationspeed
- float rotateSpeed = m_RotationSpeed;
- //Check if player is in visible range
- XMFLOAT3 forward=GetTransform()->GetForward();
- XMFLOAT3 vectorToPlayer=m_pLevelScene->GetHero()->GetTransform()->GetPosition();
- vectorToPlayer.x-=GetTransform()->GetPosition().x;
- vectorToPlayer.y-=GetTransform()->GetPosition().y;
- vectorToPlayer.z-=GetTransform()->GetPosition().z;
- float angleX=(atan2(vectorToPlayer.y, sqrt((vectorToPlayer.x * vectorToPlayer.x) + (vectorToPlayer.z * vectorToPlayer.z)))-atan2(forward.y, sqrt((forward.x * forward.x) + (forward.z * forward.z))))/XM_PI*180;
- float angleY=(atan2(vectorToPlayer.x,vectorToPlayer.z)-atan2(forward.x,forward.z)-XM_PIDIV2)/XM_PI*180;
- while(angleY<-180.f)angleY+=360;
- while(angleY>180.f)angleY-=360;
- while(angleX<-180.f)angleX+=360;
- while(angleX>180.f)angleX-=360;
- bool playerDetected=false;
- float watchAngle=m_WatchAngle;
- float alarmLevel=*m_pAlarmLevel;
- watchAngle+=5.f*(alarmLevel);
- //If player is in visible range do raycast to detect if player isn't hidden behind object
- if(abs(angleX)<=watchAngle&&abs(angleY)<=watchAngle)
- {
- PxVec3 rayDirection=PxVec3(vectorToPlayer.x,vectorToPlayer.y,vectorToPlayer.z);
- PxVec3 rayOrigin=PxVec3(GetTransform()->GetPosition().x,GetTransform()->GetPosition().y+(m_Height*HEIGHTHEAD),GetTransform()->GetPosition().z);
- rayDirection.normalize();
- rayOrigin+=rayDirection*SHOOTDISTANCE;
- PxRaycastBuffer buf;
- if(GetScene()->GetPhysxProxy()->Raycast(rayOrigin, rayDirection, PX_MAX_F32, buf))
- {
- if(buf.block.actor!=nullptr)
- {
- if(buf.block.actor->userData!=nullptr)
- {
- BaseComponent* component=static_cast<BaseComponent*>(buf.block.actor->userData);
- //Check if player is seen
- if(component->GetGameObject()->WhatKindOfObject()==L"Character")
- {
- playerDetected=true;
- m_RotateAngle=angleY;
- rotateSpeed*=SPRINTING;
- m_pLevelScene->RaiseAlarmLevel(dTime*LOOKALARMLEVEL);
- }
- }
- }
- if(playerDetected)
- {
- //Shoot and reload
- if(!m_Detected)
- {
- m_pModel->GetAnimator()->SetAnimation(ASTANDING);
- m_ShootTimer=SHOOTALARMLEVEL;
- m_Detected=true;
- }
- else
- {
- m_ShootTimer-=dTime;
- if(m_ShootTimer<=0)
- {
- m_ShootTimer=SHOOTTIMER;
- PxVec3 aimVector(forward.x,rayDirection.y,forward.z);
- aimVector.normalize();
- XMFLOAT3 directionFlare=GetTransform()->GetRight();
- directionFlare.x*=20;
- directionFlare.y*=20;
- directionFlare.z*=20;
- m_FlareTimer=FLARETIMER;
- m_pEmitter->SetVelocity(directionFlare);
- m_pEmitter->CanEmitParticles(true);
- if(GetScene()->GetPhysxProxy()->Raycast(rayOrigin, rayDirection, PX_MAX_F32, buf))
- {
- if(buf.block.actor!=nullptr)
- {
- if(buf.block.actor->userData!=nullptr)
- {
- BaseComponent* component=static_cast<BaseComponent*>(buf.block.actor->userData);
- if(component->GetGameObject()->WhatKindOfObject()==L"Character")
- {
- wcout<<"Hit"<<endl;
- m_pLevelScene->GetHero()->GetsShot();
- }
- else wcout<<"Miss"<<endl;
- }
- }
- m_pLevelScene->RaiseAlarmLevel(SHOOTALARMLEVEL);
- }
- }
- }
- }
- }
- }
- if(!playerDetected)
- {
- if(m_Detected)m_pModel->GetAnimator()->SetAnimation(ARUNNING);
- m_Detected=false;
- float curVelY = m_Velocity.y;
- m_Velocity.y = 0;
- float maxRunVelocity=m_MaxRunVelocity;
- float runAcceleration=m_RunAcceleration;
- //Alarmlevel behaviour
- if(alarmLevel>=ALARMLEVELSTARTINPACT)
- {
- //Higher speed
- float value(alarmLevel);
- if(value>ALARMLEVELSPEEDCAP)value=ALARMLEVELSPEEDCAP;
- maxRunVelocity*=value;
- runAcceleration*=value;
- rotateSpeed*=value;
- //Randomly rotate
- if(alarmLevel>=2&&m_AlignedWithCheckPoint)
- {
- value=alarmLevel-ALARMLEVELRANDOMROTATION;
- if(value>ALARMLEVELRANDOMROTATIONCAP)value=ALARMLEVELRANDOMROTATIONCAP;
- value=(float)(rand()%(((UINT)((value)*100)/25)+1));
- m_RandomTurningMeter+=value*dTime;
- if(m_RandomTurningMeter>=1)
- {
- m_RandomTurningMeter--;
- m_AlignedWithCheckPoint=false;
- if(rand()%2==0)m_RotateAngle=-360.f;
- else m_RotateAngle=360.f;
- }
- }
- }
- //Movement
- if(!m_GotTarget&&m_AlignedWithCheckPoint)
- {
- m_RunVelocity+=runAcceleration*dTime;
- if(m_RunVelocity > maxRunVelocity) m_RunVelocity = maxRunVelocity;
- m_pModel->GetAnimator()->SetAnimationSpeed(m_RunVelocity*ANIMATIONSPEED);
- XMFLOAT3 direction(m_CheckPoints[m_CurrentGoal].Point.x,0.f,m_CheckPoints[m_CurrentGoal].Point.y);
- direction.x-=this->GetTransform()->GetPosition().x;
- direction.z-=this->GetTransform()->GetPosition().z;
- XMVECTOR tempVec = XMLoadFloat3(&direction);
- float angleA = (float)atan2(1,0);
- float angleB = (float)atan2(direction.x,direction.z);
- float angle= angleB - angleA;
- m_TotalYaw=angle/XM_PI*180;
- this->GetTransform()->Rotate(0,m_TotalYaw,0,true);
- //check if a direction is pressed
- XMVECTOR velVec = XMLoadFloat3(&m_Velocity);
- tempVec = XMVector3Normalize(tempVec);
- //apply scale
- tempVec = XMVectorScale(tempVec,m_RunVelocity);
- //smooth out by adding current velocity and normalizing
- tempVec = XMVectorAdd(tempVec,velVec);
- tempVec = XMVector3Normalize(tempVec);
- //scaling again since we normalized the velocity
- tempVec = XMVectorScale(tempVec,m_RunVelocity);
- //THIS WILL ONLY STORE X AND Z, Y APPLIED AFTERWARDS IN THE JUMP FUNC;
- XMStoreFloat3(&m_Velocity, tempVec);
- //restore Y velocity
- m_Velocity.y = curVelY;
- //Gravity
- //*******
- if(!m_pController->GetCollisionFlags().isSet(PxControllerCollisionFlag::eCOLLISION_DOWN))
- {
- m_Velocity.y -= m_JumpAcceleration*dTime;
- if(m_Velocity.y < -m_TerminalVelocity)
- {
- m_Velocity.y = -m_TerminalVelocity;
- }
- }
- else
- {
- m_Velocity.y = 0;
- }
- tempVec = XMLoadFloat3(&m_Velocity);
- tempVec = XMVectorScale(tempVec, dTime);
- XMFLOAT3 distanceToMove;
- //Check if it doesn't go over the point
- XMStoreFloat3(&distanceToMove,tempVec);
- if((direction.x*direction.x)+(direction.z*direction.z)<=(distanceToMove.x*distanceToMove.x)+(distanceToMove.z*distanceToMove.z))
- {
- distanceToMove.x=direction.x;
- distanceToMove.z=direction.z;
- m_GotTarget=true;
- }
- m_pController->Move(distanceToMove);
- //Check if sees other enemy and change direction if so
- PxVec3 rayDirection=PxVec3(GetTransform()->GetRight().x,GetTransform()->GetRight().y,GetTransform()->GetRight().z);
- PxVec3 rayOrigin=PxVec3(GetTransform()->GetPosition().x,GetTransform()->GetPosition().y,GetTransform()->GetPosition().z);
- rayDirection.normalize();
- rayOrigin+=rayDirection*20;
- rayOrigin.y-=25;
- PxRaycastBuffer buf;
- if(GetScene()->GetPhysxProxy()->Raycast(rayOrigin, rayDirection, OTHERENEMYDISTANCE, buf,PxHitFlags(PxHitFlag::eDEFAULT)))
- {
- if(buf.block.actor!=nullptr)
- {
- if(buf.block.actor->userData!=nullptr)
- {
- BaseComponent* component=static_cast<BaseComponent*>(buf.block.actor->userData);
- if(component->GetGameObject()->WhatKindOfObject()==WhatKindOfObject())
- {
- m_GotTarget=true;
- m_PositiveDirection=!m_PositiveDirection;
- m_RunIntoOtherEnemy=true;
- }
- }
- }
- }
- }
- else
- {
- if(!m_pController->GetCollisionFlags().isSet(PxControllerCollisionFlag::eCOLLISION_DOWN))
- {
- m_Velocity.y -= m_JumpAcceleration*dTime;
- if(m_Velocity.y < -m_TerminalVelocity)
- {
- m_Velocity.y = -m_TerminalVelocity;
- }
- }
- else
- {
- m_Velocity.y = 0;
- }
- m_Velocity.x=0;
- m_Velocity.z=0;
- auto tempVec = XMLoadFloat3(&m_Velocity);
- tempVec = XMVectorScale(tempVec, dTime);
- XMFLOAT3 distanceToMove;
- //Check if it doesn't go over the point
- XMStoreFloat3(&distanceToMove,tempVec);
- m_pController->Move(distanceToMove);
- }
- }
- if(!m_AlignedWithCheckPoint||playerDetected)
- {
- //Rotate to wanted direction
- float rotateAngle=rotateSpeed*dTime;
- if(abs(m_RotateAngle)<=rotateAngle)
- {
- m_TotalYaw+=m_RotateAngle;
- GetTransform()->Rotate(0,m_TotalYaw,0);
- m_AlignedWithCheckPoint=true;
- m_RotateAngle=0;
- m_pModel->GetAnimator()->SetAnimation(1);
- }
- else
- {
- if(m_RotateAngle<0)rotateAngle*=-1;
- m_TotalYaw+=rotateAngle;
- GetTransform()->Rotate(0,m_TotalYaw,0);
- m_RotateAngle-=rotateAngle;
- }
- }
- if(m_GotTarget)
- {
- //Reached checkpoint and need to go to next point
- ChooseCheckPoint();
- }
- }
- void Enemy::AddingCheckPoint(const XMFLOAT2 point,const bool turnPoint)
- {
- m_CheckPoints.push_back(CheckPoint(point,turnPoint));
- }
- wstring Enemy::WhatKindOfObject()
- {
- return L"enemy";
- }
- float Enemy::GetYaw()
- {
- return m_TotalYaw+90.f;
- }
- void Enemy::PauseAnimations(bool pause)
- {
- if(pause)m_pModel->GetAnimator()->Pause();
- else m_pModel->GetAnimator()->Play();
- }
- void Enemy::StopParticles()
- {
- m_pEmitter->CanEmitParticles(false);
- }
- void Enemy::GetsKilled()
- {
- m_SetToBeDeleted=true;
- m_pLevelScene->RequestObjectForDeletion(this);
- }
- bool Enemy::WillBeDeleted()
- {
- return m_SetToBeDeleted;
- }
- //Choose next checkpoint, based on path behaviour and direction
- void Enemy::ChooseCheckPoint()
- {
- m_pModel->GetAnimator()->SetAnimation(AROTATING);
- if(m_PositiveDirection)
- {
- if((UINT)m_CurrentGoal+1>=m_CheckPoints.size())
- {
- if(m_DoesLoop)
- {
- m_CurrentGoal=0;
- }
- else
- {
- m_PositiveDirection=false;
- m_CurrentGoal--;
- if(m_CurrentGoal>=m_CheckPoints.size())m_CurrentGoal=0;
- }
- }
- else m_CurrentGoal++;
- }
- else
- {
- if((int)m_CurrentGoal-1<0)
- {
- if(m_DoesLoop)
- {
- m_CurrentGoal=m_CheckPoints.size()-1;
- }
- else
- {
- m_PositiveDirection=true;
- m_CurrentGoal++;
- if(m_CurrentGoal>=m_CheckPoints.size())m_CurrentGoal=0;
- }
- }
- else m_CurrentGoal--;
- }
- m_GotTarget=false;
- m_AlignedWithCheckPoint=false;
- XMFLOAT3 direction(m_CheckPoints[m_CurrentGoal].Point.x,0.f,m_CheckPoints[m_CurrentGoal].Point.y);
- direction.x-=this->GetTransform()->GetPosition().x;
- direction.z-=this->GetTransform()->GetPosition().z;
- XMFLOAT3 forward(GetTransform()->GetForward());
- float angleA = (float)atan2(forward.x,forward.z);
- float angleB = (float)(atan2(direction.x,direction.z)-XM_PIDIV2);
- float angle= angleB - angleA;
- if(angle<0)angle+=XM_2PI;
- if(angle<=XM_PI)
- {
- if(m_CheckPoints[m_CurrentGoal].TurnPoint&&!m_RunIntoOtherEnemy)angle+=XM_2PI;
- }
- else
- {
- angle-=XM_2PI;
- if(m_CheckPoints[m_CurrentGoal].TurnPoint&&!m_RunIntoOtherEnemy)angle-=XM_2PI;
- }
- m_RunIntoOtherEnemy=false;
- m_RotateAngle=angle/XM_PI*180;
- }
Advertisement
Add Comment
Please, Sign In to add comment