|
|
|
#include "Monster.h"
|
|
|
|
#include "Player.h"
|
|
|
|
#include "Crawler.h"
|
|
|
|
#include "DamageNumber.h"
|
|
|
|
#include "DEFINES.h"
|
|
|
|
|
|
|
|
INCLUDE_MONSTER_DATA
|
|
|
|
INCLUDE_MONSTER_LIST
|
|
|
|
INCLUDE_ANIMATION_DATA
|
|
|
|
INCLUDE_SPAWNER_LIST
|
|
|
|
INCLUDE_DAMAGENUMBER_LIST
|
|
|
|
INCLUDE_game
|
|
|
|
|
|
|
|
const float Player::GROUND_SLAM_SPIN_TIME=0.6f;
|
|
|
|
const float Player::GROUND_SLAM_COOLDOWN=20;
|
|
|
|
|
|
|
|
Player::Player(){
|
|
|
|
}
|
|
|
|
|
|
|
|
Player::Player(vf2d pos):
|
|
|
|
pos(pos){
|
|
|
|
}
|
|
|
|
|
|
|
|
void Player::SetX(float x){
|
|
|
|
pos.x=x;
|
|
|
|
};
|
|
|
|
|
|
|
|
void Player::SetY(float y){
|
|
|
|
pos.y=y;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Player::SetZ(float z){
|
|
|
|
this->z=z;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Player::SetPos(vf2d pos){
|
|
|
|
this->pos=pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
vf2d&Player::GetPos(){
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
float Player::GetX(){
|
|
|
|
return pos.x;
|
|
|
|
}
|
|
|
|
|
|
|
|
float Player::GetY(){
|
|
|
|
return pos.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
float Player::GetZ(){
|
|
|
|
return z;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Player::GetHealth(){
|
|
|
|
return hp;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Player::GetMaxHealth(){
|
|
|
|
return maxhp;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Player::GetAttack(){
|
|
|
|
return atk;
|
|
|
|
}
|
|
|
|
|
|
|
|
float Player::GetMoveSpdMult(){
|
|
|
|
return moveSpd;
|
|
|
|
}
|
|
|
|
|
|
|
|
float Player::GetSizeMult(){
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
float Player::GetAttackRangeMult(){
|
|
|
|
return attack_range;
|
|
|
|
}
|
|
|
|
|
|
|
|
float Player::GetSpinAngle(){
|
|
|
|
return spin_angle;
|
|
|
|
}
|
|
|
|
|
|
|
|
State Player::GetState(){
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Player::Update(float fElapsedTime){
|
|
|
|
attack_cooldown_timer=std::max(0.f,attack_cooldown_timer-fElapsedTime);
|
|
|
|
switch(state){
|
|
|
|
case SPIN:{
|
|
|
|
switch(facingDirection){
|
|
|
|
case UP:{
|
|
|
|
if(lastAnimationFlip==0){
|
|
|
|
lastAnimationFlip=0.03;
|
|
|
|
facingDirection=DOWN;
|
|
|
|
animation.ChangeState(internal_animState,AnimationState::WALK_S);
|
|
|
|
}
|
|
|
|
}break;
|
|
|
|
case DOWN:{
|
|
|
|
if(lastAnimationFlip==0){
|
|
|
|
lastAnimationFlip=0.03;
|
|
|
|
facingDirection=UP;
|
|
|
|
animation.ChangeState(internal_animState,AnimationState::WALK_N);
|
|
|
|
}
|
|
|
|
}break;
|
|
|
|
}
|
|
|
|
if(facingDirection==RIGHT){
|
|
|
|
spin_angle+=spin_spd*fElapsedTime;
|
|
|
|
} else {
|
|
|
|
spin_angle-=spin_spd*fElapsedTime;
|
|
|
|
}
|
|
|
|
if(spin_attack_timer>0){
|
|
|
|
z=50*sin(3.3*(GROUND_SLAM_SPIN_TIME-spin_attack_timer)/GROUND_SLAM_SPIN_TIME);
|
|
|
|
spin_attack_timer=std::max(0.f,spin_attack_timer-fElapsedTime);
|
|
|
|
} else {
|
|
|
|
state=NORMAL;
|
|
|
|
spin_angle=0;
|
|
|
|
z=0;
|
|
|
|
game->HurtEnemies(pos,3*12,atk*2.5);
|
|
|
|
game->AddEffect(Effect{GetPos(),0.5,AnimationState::GROUND_SLAM_ATTACK_FRONT,1.33f,0.6f},Effect{GetPos(),0.5,AnimationState::GROUND_SLAM_ATTACK_BACK,1.33f,0.6f});
|
|
|
|
}
|
|
|
|
if(lastAnimationFlip>0){
|
|
|
|
lastAnimationFlip=std::max(0.f,lastAnimationFlip-fElapsedTime);
|
|
|
|
}
|
|
|
|
}break;
|
|
|
|
default:{
|
|
|
|
//Update animations normally.
|
|
|
|
}
|
|
|
|
[[fallthrough]];
|
|
|
|
}
|
|
|
|
animation.UpdateState(internal_animState,fElapsedTime);
|
|
|
|
groundSlamCooldown=std::max(0.f,groundSlamCooldown-fElapsedTime);
|
|
|
|
for(Monster&m:MONSTER_LIST){
|
|
|
|
if(geom2d::overlaps(geom2d::circle(pos,12*size/2),geom2d::circle(m.GetPos(),12*m.GetSizeMult()/2))){
|
|
|
|
if(m.IsAlive()){
|
|
|
|
m.Collision(*this);
|
|
|
|
}
|
|
|
|
geom2d::line line(pos,m.GetPos());
|
|
|
|
float dist = line.length();
|
|
|
|
m.SetPosition(line.rpoint(dist*1.1));
|
|
|
|
if(m.IsAlive()){
|
|
|
|
vel=line.vector().norm()*-128;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(vel.x>0){
|
|
|
|
vel.x=std::max(0.f,vel.x-friction*fElapsedTime);
|
|
|
|
} else {
|
|
|
|
vel.x=std::min(0.f,vel.x+friction*fElapsedTime);
|
|
|
|
}
|
|
|
|
if(vel.y>0){
|
|
|
|
vel.y=std::max(0.f,vel.y-friction*fElapsedTime);
|
|
|
|
} else {
|
|
|
|
vel.y=std::min(0.f,vel.y+friction*fElapsedTime);
|
|
|
|
}
|
|
|
|
float newX=pos.x+vel.x*fElapsedTime;
|
|
|
|
if(newX-12*size>0&&newX+12*size<game->WORLD_SIZE.x*24){
|
|
|
|
pos.x=newX;
|
|
|
|
}
|
|
|
|
float newY=pos.y+vel.y*fElapsedTime;
|
|
|
|
if(newY-12*size>0&&newY+12*size<game->WORLD_SIZE.y*24){
|
|
|
|
pos.y=newY;
|
|
|
|
}
|
|
|
|
if(attack_cooldown_timer==0&&game->GetMouse(0).bHeld){
|
|
|
|
bool attack=false;
|
|
|
|
Monster*closest=nullptr;
|
|
|
|
float closest_dist=999999;
|
|
|
|
for(Monster&m:MONSTER_LIST){
|
|
|
|
if(m.IsAlive()
|
|
|
|
&&geom2d::overlaps(geom2d::circle<float>(pos-vf2d{size*12,size*12},attack_range*size*12),geom2d::circle<float>(m.GetPos()-vf2d{m.GetSizeMult()*12,m.GetSizeMult()*12},m.GetSizeMult()*12))
|
|
|
|
&&geom2d::line<float>(game->GetWorldMousePos(),m.GetPos()).length()<closest_dist){
|
|
|
|
closest_dist=geom2d::line<float>(game->GetWorldMousePos(),m.GetPos()).length();
|
|
|
|
closest=&m;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(closest!=nullptr&&closest->Hurt(atk)){
|
|
|
|
attack_cooldown_timer=ATTACK_COOLDOWN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vf2d Player::GetVelocity(){
|
|
|
|
return vel;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Player::Hurt(int damage){
|
|
|
|
if(hp<=0) return;
|
|
|
|
hp=std::max(0,hp-damage);
|
|
|
|
DAMAGENUMBER_LIST.push_back(DamageNumber(pos,damage));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Player::AddAnimation(AnimationState state){
|
|
|
|
animation.AddState(state,ANIMATION_DATA[state]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Player::UpdateAnimation(AnimationState animState){
|
|
|
|
animation.ChangeState(internal_animState,animState);
|
|
|
|
}
|
|
|
|
|
|
|
|
Animate2D::Frame Player::GetFrame(){
|
|
|
|
return animation.GetFrame(internal_animState);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Player::SetLastReleasedMovementKey(Key k){
|
|
|
|
lastReleasedMovementKey=k;
|
|
|
|
}
|
|
|
|
|
|
|
|
Key Player::GetLastReleasedMovementKey(){
|
|
|
|
return lastReleasedMovementKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Player::SetFacingDirection(Key direction){
|
|
|
|
facingDirection=direction;
|
|
|
|
}
|
|
|
|
|
|
|
|
Key Player::GetFacingDirection(){
|
|
|
|
return facingDirection;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Player::Moved(){
|
|
|
|
for(MonsterSpawner&spawner:SPAWNER_LIST){
|
|
|
|
if(!spawner.SpawnTriggered()&&geom2d::overlaps(geom2d::circle<float>(pos-vf2d{size*12,size*12},size*12),geom2d::circle<float>(spawner.GetPos(),spawner.GetRange()))){
|
|
|
|
spawner.SetTriggered(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float Player::GetGroundSlamCooldown(){
|
|
|
|
return groundSlamCooldown;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Player::Spin(float duration,float spinSpd){
|
|
|
|
state=State::SPIN;
|
|
|
|
spin_attack_timer=duration;
|
|
|
|
spin_spd=spinSpd;
|
|
|
|
spin_angle=0;
|
|
|
|
groundSlamCooldown=GROUND_SLAM_COOLDOWN;
|
|
|
|
}
|