Bounce collisions occur between units.

pull/28/head
sigonasr2 1 year ago
parent b5b7097418
commit df1681b051
  1. 96
      Crawler/Crawler.cpp
  2. 3
      Crawler/Crawler.h
  3. 113
      Crawler/Monster.cpp
  4. 16
      Crawler/Monster.h
  5. 35
      Crawler/Player.cpp
  6. 3
      Crawler/Player.h
  7. 3
      Crawler/State.h

@ -128,6 +128,9 @@ void Crawler::InitializeAnimations(){
if(state==4){//These are death animations. if(state==4){//These are death animations.
anim=Animate2D::FrameSequence(0.1f,Animate2D::Style::OneShot); anim=Animate2D::FrameSequence(0.1f,Animate2D::Style::OneShot);
} }
if(state==2){//These are death animations.
anim=Animate2D::FrameSequence(0.06f);
}
for (int frame=0;frame<10;frame++){ for (int frame=0;frame<10;frame++){
anim.AddFrame({&GFX_Slime_Sheet,{vi2d{frame,state+5*slime}*24,{24,24}}}); anim.AddFrame({&GFX_Slime_Sheet,{vi2d{frame,state+5*slime}*24,{24,24}}});
} }
@ -173,53 +176,54 @@ void Crawler::HandleUserInput(float fElapsedTime){
if(GetKey(SPACE).bPressed&&player.GetState()==State::NORMAL&&player.GetGroundSlamCooldown()==0){ if(GetKey(SPACE).bPressed&&player.GetState()==State::NORMAL&&player.GetGroundSlamCooldown()==0){
player.Spin(Player::GROUND_SLAM_SPIN_TIME,14*PI); player.Spin(Player::GROUND_SLAM_SPIN_TIME,14*PI);
} }
if(RightHeld()){ if(player.GetVelocity()==vf2d{0,0}){
if(player.GetPos().x+12+fElapsedTime*100*player.GetMoveSpdMult()<WORLD_SIZE.x*24){ if(RightHeld()){
player.SetX(player.GetX()+fElapsedTime*100*player.GetMoveSpdMult()); if(player.GetPos().x+12*player.GetSizeMult()+fElapsedTime*100*player.GetMoveSpdMult()<WORLD_SIZE.x*24){
} else { player.SetX(player.GetX()+fElapsedTime*100*player.GetMoveSpdMult());
player.SetX(WORLD_SIZE.x*24-12); } else {
} player.SetX(WORLD_SIZE.x*24-12);
player.SetFacingDirection(RIGHT); }
player.UpdateAnimation(AnimationState::WALK_E); player.SetFacingDirection(RIGHT);
setIdleAnimation=false; player.UpdateAnimation(AnimationState::WALK_E);
} setIdleAnimation=false;
if(LeftHeld()){
if(player.GetPos().x-12+fElapsedTime*100*player.GetMoveSpdMult()>0){
player.SetX(player.GetX()-fElapsedTime*100*player.GetMoveSpdMult());
} else {
player.SetX(12);
}
if(setIdleAnimation){
player.SetFacingDirection(LEFT);
player.UpdateAnimation(AnimationState::WALK_W);
}
setIdleAnimation=false;
}
if(UpHeld()){
if(player.GetPos().y-12+fElapsedTime*100*player.GetMoveSpdMult()>0){
player.SetY(player.GetY()-fElapsedTime*100*player.GetMoveSpdMult());
} else {
player.SetY(12);
} }
if(setIdleAnimation){ if(LeftHeld()){
player.SetFacingDirection(UP); if(player.GetPos().x-12*player.GetSizeMult()+fElapsedTime*100*player.GetMoveSpdMult()>0){
player.UpdateAnimation(AnimationState::WALK_N); player.SetX(player.GetX()-fElapsedTime*100*player.GetMoveSpdMult());
} else {
player.SetX(12);
}
if(setIdleAnimation){
player.SetFacingDirection(LEFT);
player.UpdateAnimation(AnimationState::WALK_W);
}
setIdleAnimation=false;
} }
setIdleAnimation=false; if(UpHeld()){
} if(player.GetPos().y-12*player.GetSizeMult()+fElapsedTime*100*player.GetMoveSpdMult()>0){
if(DownHeld()){ player.SetY(player.GetY()-fElapsedTime*100*player.GetMoveSpdMult());
if(player.GetPos().y+12+fElapsedTime*100*player.GetMoveSpdMult()<WORLD_SIZE.y*24){ } else {
player.SetY(player.GetY()+fElapsedTime*100*player.GetMoveSpdMult()); player.SetY(12);
} else { }
player.SetY(WORLD_SIZE.y*24-12); if(setIdleAnimation){
player.SetFacingDirection(UP);
player.UpdateAnimation(AnimationState::WALK_N);
}
setIdleAnimation=false;
} }
if(setIdleAnimation){ if(DownHeld()){
player.SetFacingDirection(DOWN); if(player.GetPos().y+12*player.GetSizeMult()+fElapsedTime*100*player.GetMoveSpdMult()<WORLD_SIZE.y*24){
player.UpdateAnimation(AnimationState::WALK_S); player.SetY(player.GetY()+fElapsedTime*100*player.GetMoveSpdMult());
} else {
player.SetY(WORLD_SIZE.y*24-12);
}
if(setIdleAnimation){
player.SetFacingDirection(DOWN);
player.UpdateAnimation(AnimationState::WALK_S);
}
setIdleAnimation=false;
} }
setIdleAnimation=false;
} }
if(UpReleased()){ if(UpReleased()){
player.SetLastReleasedMovementKey(UP); player.SetLastReleasedMovementKey(UP);
if(RightHeld()){ if(RightHeld()){
@ -347,11 +351,11 @@ void Crawler::RenderWorld(float fElapsedTime){
e.Draw(); e.Draw();
} }
for(Monster&m:monstersBefore){ for(Monster&m:monstersBefore){
view.DrawPartialDecal(m.GetPos()-vf2d{12,12}*m.GetSizeMult(),m.GetFrame().GetSourceImage()->Decal(),m.GetFrame().GetSourceRect().pos,m.GetFrame().GetSourceRect().size,vf2d(m.GetSizeMult(),m.GetSizeMult())); m.Draw();
} }
view.DrawPartialRotatedDecal(player.GetPos()+vf2d{0,-player.GetZ()},player.GetFrame().GetSourceImage()->Decal(),player.GetSpinAngle(),{12,12},player.GetFrame().GetSourceRect().pos,player.GetFrame().GetSourceRect().size,vf2d(player.GetSizeMult(),player.GetSizeMult())); view.DrawPartialRotatedDecal(player.GetPos()+vf2d{0,-player.GetZ()},player.GetFrame().GetSourceImage()->Decal(),player.GetSpinAngle(),{12,12},player.GetFrame().GetSourceRect().pos,player.GetFrame().GetSourceRect().size,vf2d(player.GetSizeMult(),player.GetSizeMult()));
for(Monster&m:monstersAfter){ for(Monster&m:monstersAfter){
view.DrawPartialDecal(m.GetPos()-vf2d{12,12}*m.GetSizeMult(),m.GetFrame().GetSourceImage()->Decal(),m.GetFrame().GetSourceRect().pos,m.GetFrame().GetSourceRect().size,vf2d(m.GetSizeMult(),m.GetSizeMult())); m.Draw();
} }
for(Effect&e:foregroundEffects){ for(Effect&e:foregroundEffects){
e.Draw(); e.Draw();
@ -374,6 +378,10 @@ void Crawler::RenderWorld(float fElapsedTime){
} }
} }
Player&Crawler::GetPlayer(){
return player;
}
void Crawler::RenderHud(){ void Crawler::RenderHud(){
if(player.GetGroundSlamCooldown()>0){ if(player.GetGroundSlamCooldown()>0){
FillRectDecal({10,ScreenHeight()-22.f},{64,6},BLACK); FillRectDecal({10,ScreenHeight()-22.f},{64,6},BLACK);

@ -10,7 +10,6 @@
class Crawler : public olc::PixelGameEngine class Crawler : public olc::PixelGameEngine
{ {
const vi2d WORLD_SIZE={64,8};
Camera2D camera; Camera2D camera;
Player player; Player player;
Renderable GFX_Pl_Sheet,GFX_Slime_Sheet,GFX_Circle, Renderable GFX_Pl_Sheet,GFX_Slime_Sheet,GFX_Circle,
@ -21,6 +20,7 @@ public:
Crawler(); Crawler();
public: public:
const vi2d WORLD_SIZE={64,8};
TileTransformedView view; TileTransformedView view;
bool OnUserCreate() override; bool OnUserCreate() override;
bool OnUserUpdate(float fElapsedTime) override; bool OnUserUpdate(float fElapsedTime) override;
@ -41,4 +41,5 @@ public:
bool RightReleased(); bool RightReleased();
bool UpReleased(); bool UpReleased();
bool DownReleased(); bool DownReleased();
Player&GetPlayer();
}; };

@ -1,11 +1,13 @@
#include "Monster.h" #include "Monster.h"
#include "DamageNumber.h" #include "DamageNumber.h"
#include "Crawler.h"
#include "DEFINES.h" #include "DEFINES.h"
INCLUDE_ANIMATION_DATA INCLUDE_ANIMATION_DATA
INCLUDE_MONSTER_DATA INCLUDE_MONSTER_DATA
INCLUDE_MONSTER_LIST INCLUDE_MONSTER_LIST
INCLUDE_DAMAGENUMBER_LIST INCLUDE_DAMAGENUMBER_LIST
INCLUDE_game
MonsterData::MonsterData(){} MonsterData::MonsterData(){}
MonsterData::MonsterData(MonsterName type,int hp,int atk,std::vector<AnimationState>animations,float moveSpd,float size,MonsterStrategy strategy): MonsterData::MonsterData(MonsterName type,int hp,int atk,std::vector<AnimationState>animations,float moveSpd,float size,MonsterStrategy strategy):
@ -65,13 +67,78 @@ void Monster::UpdateAnimation(AnimationState state){
animation.ChangeState(internal_animState,state); animation.ChangeState(internal_animState,state);
} }
bool Monster::Update(float fElapsedTime){ bool Monster::Update(float fElapsedTime){
switch(strategy){ if(IsAlive()){
RUN_TOWARDS:{ for(Monster&m:MONSTER_LIST){
if(&m==this)continue;
}break; if(geom2d::overlaps(geom2d::circle(pos,12*size/2),geom2d::circle(m.GetPos(),12*m.GetSizeMult()/2))){
SHOOT_AFAR:{ 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(geom2d::overlaps(geom2d::circle(pos,12*size/2),geom2d::circle(game->GetPlayer().GetPos(),12*game->GetPlayer().GetSizeMult()/2))){
geom2d::line line(pos,game->GetPlayer().GetPos());
float dist = line.length();
SetPosition(line.rpoint(-0.1));
vel=line.vector().norm()*-128;
}
if(state==NORMAL){
if(game->GetPlayer().GetX()>pos.x){
facingDirection=RIGHT;
} else {
facingDirection=LEFT;
}
}
switch(strategy){
case RUN_TOWARDS:{
targetAcquireTimer=std::max(0.f,targetAcquireTimer-fElapsedTime);
if(targetAcquireTimer==0){
targetAcquireTimer=3;
target=geom2d::line(pos,game->GetPlayer().GetPos()).upoint(1.2);
state=MOVE_TOWARDS;
}
if(state==MOVE_TOWARDS&&geom2d::line(pos,target).length()>100*fElapsedTime*moveSpd){
pos+=geom2d::line(pos,target).vector().norm()*100*fElapsedTime*moveSpd;
switch(type){
case SLIME_GREEN:{
animation.ChangeState(internal_animState,AnimationState::GREEN_SLIME_JUMP);
}break;
case SLIME_RED:{
animation.ChangeState(internal_animState,AnimationState::RED_SLIME_JUMP);
}break;
}
} else {
if(state==MOVE_TOWARDS){
state=NORMAL;//Revert state once we've finished moving towards target.
}
}
}break;
case SHOOT_AFAR:{
}break; }break;
}
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(hp<=0){ if(hp<=0){
deathTimer+=fElapsedTime; deathTimer+=fElapsedTime;
@ -83,6 +150,37 @@ bool Monster::Update(float fElapsedTime){
randomFrameOffset=0; randomFrameOffset=0;
return true; return true;
} }
Key Monster::GetFacingDirection(){
return facingDirection;
}
void Monster::Draw(){
if(GetFacingDirection()==RIGHT){
game->view.DrawPartialDecal((GetPos()+vf2d{float(GetFrame().GetSourceRect().size.x),0}*GetSizeMult())-vf2d{12,12}*GetSizeMult(),GetFrame().GetSourceImage()->Decal(),GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,vf2d(GetSizeMult()*-1,GetSizeMult()));
} else {
game->view.DrawPartialDecal(GetPos()-vf2d{12,12}*GetSizeMult(),GetFrame().GetSourceImage()->Decal(),GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,vf2d(GetSizeMult(),GetSizeMult()));
}
if(GetTargetPos()!=vf2d{0,0}){
game->view.DrawLine(GetPos(),GetTargetPos(),RED,0xF4F4F4F4);
game->view.DrawCircle(GetTargetPos(),6,RED);
}
}
void Monster::Collision(Player&p){
Collision();
}
void Monster::Collision(Monster&m){
Collision();
}
void Monster::Collision(){
if(strategy==RUN_TOWARDS&&state==MOVE_TOWARDS){
state=NORMAL;
}
}
void Monster::SetVelocity(vf2d vel){
this->vel=vel;
}
void Monster::SetPosition(vf2d pos){
this->pos=pos;
}
AnimationState Monster::GetDeathAnimationName(){ AnimationState Monster::GetDeathAnimationName(){
switch(type){ switch(type){
case SLIME_GREEN:{ case SLIME_GREEN:{
@ -112,6 +210,9 @@ bool Monster::Hurt(int damage){
bool Monster::IsAlive(){ bool Monster::IsAlive(){
return hp>0; return hp>0;
} }
vf2d&Monster::GetTargetPos(){
return target;
}
MonsterSpawner::MonsterSpawner(){} MonsterSpawner::MonsterSpawner(){}
MonsterSpawner::MonsterSpawner(vf2d pos,int range,std::vector<std::pair<MonsterName,vf2d>>monsters): MonsterSpawner::MonsterSpawner(vf2d pos,int range,std::vector<std::pair<MonsterName,vf2d>>monsters):

@ -1,6 +1,8 @@
#pragma once #pragma once
#include "olcPixelGameEngine.h" #include "olcPixelGameEngine.h"
#include "Animation.h" #include "Animation.h"
#include "State.h"
#include "Player.h"
#include "olcUTIL_Animate2D.h" #include "olcUTIL_Animate2D.h"
enum MonsterStrategy{ enum MonsterStrategy{
@ -42,11 +44,17 @@ struct MonsterData{
struct Monster{ struct Monster{
private: private:
vf2d pos; vf2d pos;
vf2d vel={0,0};
float friction=400;
vf2d target={0,0};
float targetAcquireTimer=0;
int hp,maxhp; int hp,maxhp;
int atk; int atk;
float moveSpd; float moveSpd;
float size; float size;
Key facingDirection;
MonsterStrategy strategy; MonsterStrategy strategy;
State state=State::NORMAL;
Animate2D::Animation<AnimationState>animation; Animate2D::Animation<AnimationState>animation;
Animate2D::AnimationState internal_animState; Animate2D::AnimationState internal_animState;
float randomFrameOffset=0.f; float randomFrameOffset=0.f;
@ -67,6 +75,14 @@ struct Monster{
//Returns true when damage is actually dealt (there is a death check here.) //Returns true when damage is actually dealt (there is a death check here.)
bool Hurt(int damage); bool Hurt(int damage);
bool IsAlive(); bool IsAlive();
vf2d&GetTargetPos();
Key GetFacingDirection();
void Draw();
void Collision(Player&p);
void Collision(Monster&p);
void Collision();
void SetVelocity(vf2d vel);
void SetPosition(vf2d pos);
}; };
struct MonsterSpawner{ struct MonsterSpawner{

@ -131,6 +131,37 @@ void Player::Update(float fElapsedTime){
} }
animation.UpdateState(internal_animState,fElapsedTime); animation.UpdateState(internal_animState,fElapsedTime);
groundSlamCooldown=std::max(0.f,groundSlamCooldown-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){ if(attack_cooldown_timer==0&&game->GetMouse(0).bHeld){
bool attack=false; bool attack=false;
Monster*closest=nullptr; Monster*closest=nullptr;
@ -149,6 +180,10 @@ void Player::Update(float fElapsedTime){
} }
} }
vf2d Player::GetVelocity(){
return vel;
}
void Player::Hurt(int damage){ void Player::Hurt(int damage){
if(hp<=0) return; if(hp<=0) return;
hp=std::max(0,hp-damage); hp=std::max(0,hp-damage);

@ -9,6 +9,8 @@ private:
int hp=100,maxhp=hp; int hp=100,maxhp=hp;
int atk=10; int atk=10;
vf2d pos; vf2d pos;
vf2d vel={0,0};
float friction=400;
float z=0; float z=0;
float moveSpd=1.0f; float moveSpd=1.0f;
float size=1.0f; float size=1.0f;
@ -48,6 +50,7 @@ public:
State GetState(); State GetState();
void SetFacingDirection(Key direction); void SetFacingDirection(Key direction);
Key GetFacingDirection(); Key GetFacingDirection();
vf2d GetVelocity();
void Hurt(int damage); void Hurt(int damage);

@ -2,5 +2,6 @@
enum State{ enum State{
NORMAL, NORMAL,
SPIN SPIN,
MOVE_TOWARDS,
}; };
Loading…
Cancel
Save