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.
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++){
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){
player.Spin(Player::GROUND_SLAM_SPIN_TIME,14*PI);
}
if(RightHeld()){
if(player.GetPos().x+12+fElapsedTime*100*player.GetMoveSpdMult()<WORLD_SIZE.x*24){
player.SetX(player.GetX()+fElapsedTime*100*player.GetMoveSpdMult());
} else {
player.SetX(WORLD_SIZE.x*24-12);
}
player.SetFacingDirection(RIGHT);
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(player.GetVelocity()==vf2d{0,0}){
if(RightHeld()){
if(player.GetPos().x+12*player.GetSizeMult()+fElapsedTime*100*player.GetMoveSpdMult()<WORLD_SIZE.x*24){
player.SetX(player.GetX()+fElapsedTime*100*player.GetMoveSpdMult());
} else {
player.SetX(WORLD_SIZE.x*24-12);
}
player.SetFacingDirection(RIGHT);
player.UpdateAnimation(AnimationState::WALK_E);
setIdleAnimation=false;
}
if(setIdleAnimation){
player.SetFacingDirection(UP);
player.UpdateAnimation(AnimationState::WALK_N);
if(LeftHeld()){
if(player.GetPos().x-12*player.GetSizeMult()+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;
}
setIdleAnimation=false;
}
if(DownHeld()){
if(player.GetPos().y+12+fElapsedTime*100*player.GetMoveSpdMult()<WORLD_SIZE.y*24){
player.SetY(player.GetY()+fElapsedTime*100*player.GetMoveSpdMult());
} else {
player.SetY(WORLD_SIZE.y*24-12);
if(UpHeld()){
if(player.GetPos().y-12*player.GetSizeMult()+fElapsedTime*100*player.GetMoveSpdMult()>0){
player.SetY(player.GetY()-fElapsedTime*100*player.GetMoveSpdMult());
} else {
player.SetY(12);
}
if(setIdleAnimation){
player.SetFacingDirection(UP);
player.UpdateAnimation(AnimationState::WALK_N);
}
setIdleAnimation=false;
}
if(setIdleAnimation){
player.SetFacingDirection(DOWN);
player.UpdateAnimation(AnimationState::WALK_S);
if(DownHeld()){
if(player.GetPos().y+12*player.GetSizeMult()+fElapsedTime*100*player.GetMoveSpdMult()<WORLD_SIZE.y*24){
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()){
player.SetLastReleasedMovementKey(UP);
if(RightHeld()){
@ -347,11 +351,11 @@ void Crawler::RenderWorld(float fElapsedTime){
e.Draw();
}
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()));
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){
e.Draw();
@ -374,6 +378,10 @@ void Crawler::RenderWorld(float fElapsedTime){
}
}
Player&Crawler::GetPlayer(){
return player;
}
void Crawler::RenderHud(){
if(player.GetGroundSlamCooldown()>0){
FillRectDecal({10,ScreenHeight()-22.f},{64,6},BLACK);

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

@ -1,11 +1,13 @@
#include "Monster.h"
#include "DamageNumber.h"
#include "Crawler.h"
#include "DEFINES.h"
INCLUDE_ANIMATION_DATA
INCLUDE_MONSTER_DATA
INCLUDE_MONSTER_LIST
INCLUDE_DAMAGENUMBER_LIST
INCLUDE_game
MonsterData::MonsterData(){}
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);
}
bool Monster::Update(float fElapsedTime){
switch(strategy){
RUN_TOWARDS:{
}break;
SHOOT_AFAR:{
if(IsAlive()){
for(Monster&m:MONSTER_LIST){
if(&m==this)continue;
if(geom2d::overlaps(geom2d::circle(pos,12*size/2),geom2d::circle(m.GetPos(),12*m.GetSizeMult()/2))){
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){
deathTimer+=fElapsedTime;
@ -83,6 +150,37 @@ bool Monster::Update(float fElapsedTime){
randomFrameOffset=0;
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(){
switch(type){
case SLIME_GREEN:{
@ -112,6 +210,9 @@ bool Monster::Hurt(int damage){
bool Monster::IsAlive(){
return hp>0;
}
vf2d&Monster::GetTargetPos(){
return target;
}
MonsterSpawner::MonsterSpawner(){}
MonsterSpawner::MonsterSpawner(vf2d pos,int range,std::vector<std::pair<MonsterName,vf2d>>monsters):

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

@ -131,6 +131,37 @@ void Player::Update(float fElapsedTime){
}
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;
@ -149,6 +180,10 @@ void Player::Update(float fElapsedTime){
}
}
vf2d Player::GetVelocity(){
return vel;
}
void Player::Hurt(int damage){
if(hp<=0) return;
hp=std::max(0,hp-damage);

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

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