#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(): state(State::NORMAL),lastReleasedMovementKey(DOWN),facingDirection(DOWN){ } Player::Player(vf2d pos): pos(pos),state(State::NORMAL),lastReleasedMovementKey(DOWN),facingDirection(DOWN){ } 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. } } 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*sizeWORLD_SIZE.x*24){ pos.x=newX; } float newY=pos.y+vel.y*fElapsedTime; if(newY-12*size>0&&newY+12*sizeWORLD_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(pos-vf2d{size*12,size*12},attack_range*size*12),geom2d::circle(m.GetPos()-vf2d{m.GetSizeMult()*12,m.GetSizeMult()*12},m.GetSizeMult()*12)) &&geom2d::line(game->GetWorldMousePos(),m.GetPos()).length()(game->GetWorldMousePos(),m.GetPos()).length(); closest=&m; } } if(closest!=nullptr&&closest->Hurt(atk)){ attack_cooldown_timer=ATTACK_COOLDOWN; swordSwingTimer=0.2; SetState(State::SWING_SWORD); switch(facingDirection){ case DOWN:{ UpdateAnimation(AnimationState::SWINGSWORD_S); }break; case RIGHT:{ UpdateAnimation(AnimationState::SWINGSWORD_E); }break; case LEFT:{ UpdateAnimation(AnimationState::SWINGSWORD_W); }break; case UP:{ UpdateAnimation(AnimationState::SWINGSWORD_N); }break; } } } } float Player::GetSwordSwingTimer(){ return swordSwingTimer; } void Player::SetSwordSwingTimer(float val){ swordSwingTimer=val; } void Player::SetState(State newState){ state=newState; } 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(pos-vf2d{size*12,size*12},size*12),geom2d::circle(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; }