Adjusted shoot afar AI to account for collision tiles.

pull/28/head
sigonasr2 1 year ago
parent 46a16b8ae2
commit 9a8859ffe8
  1. 2
      Crawler/Animation.h
  2. 4
      Crawler/Bullet.cpp
  3. 70
      Crawler/Crawler.cpp
  4. 3
      Crawler/Crawler.h
  5. 42
      Crawler/Monster.cpp
  6. 10
      Crawler/Monster.h
  7. 2
      Crawler/Player.cpp
  8. 1
      Crawler/Player.h
  9. 2
      Crawler/Version.h
  10. 6
      Crawler/assets/Campaigns/1_1_test.tmx
  11. BIN
      Crawler/assets/circle.png
  12. BIN
      Crawler/assets/circle_outline.png
  13. BIN
      Crawler/assets/nico-wizard.png
  14. BIN
      Crawler/assets/nico-wizard.xcf

@ -15,4 +15,6 @@ enum AnimationState{
WIZARD_IDLE_S,WIZARD_IDLE_E,WIZARD_IDLE_N,WIZARD_IDLE_W, WIZARD_IDLE_S,WIZARD_IDLE_E,WIZARD_IDLE_N,WIZARD_IDLE_W,
BATTLECRY_EFFECT,SONICSLASH, BATTLECRY_EFFECT,SONICSLASH,
WARRIOR_SWINGSONICSWORD_S,WARRIOR_SWINGSONICSWORD_E,WARRIOR_SWINGSONICSWORD_N,WARRIOR_SWINGSONICSWORD_W, WARRIOR_SWINGSONICSWORD_S,WARRIOR_SWINGSONICSWORD_E,WARRIOR_SWINGSONICSWORD_N,WARRIOR_SWINGSONICSWORD_W,
WIZARD_IDLE_ATTACK_S,WIZARD_IDLE_ATTACK_E,WIZARD_IDLE_ATTACK_N,WIZARD_IDLE_ATTACK_W,
WIZARD_ATTACK_S,WIZARD_ATTACK_E,WIZARD_ATTACK_N,WIZARD_ATTACK_W,
}; };

@ -22,7 +22,7 @@ void Bullet::Draw(){
if(animated){ if(animated){
game->view.DrawPartialRotatedDecal(pos,GetFrame().GetSourceImage()->Decal(),rotates?atan2(vel.y,vel.x)-PI/2:0,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,{1,1},col); game->view.DrawPartialRotatedDecal(pos,GetFrame().GetSourceImage()->Decal(),rotates?atan2(vel.y,vel.x)-PI/2:0,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,{1,1},col);
} else { } else {
game->view.FillCircle(pos,radius,col); game->view.DrawDecal(pos,game->GFX_BulletCircle.Decal(),{radius,radius},col);
game->view.DrawCircle(pos,radius,WHITE,0xAA); game->view.DrawDecal(pos,game->GFX_BulletCircleOutline.Decal(),{radius,radius},WHITE);
} }
} }

@ -52,6 +52,8 @@ bool Crawler::OnUserCreate(){
GFX_Battlecry_Effect.Load("assets/battlecry_effect.png"); GFX_Battlecry_Effect.Load("assets/battlecry_effect.png");
GFX_Mana.Load("assets/mana.png"); GFX_Mana.Load("assets/mana.png");
GFX_SonicSlash.Load("assets/sonicslash.png"); GFX_SonicSlash.Load("assets/sonicslash.png");
GFX_BulletCircle.Load("assets/circle.png");
GFX_BulletCircleOutline.Load("assets/circle_outline.png");
//Animations //Animations
InitializeAnimations(); InitializeAnimations();
@ -88,6 +90,14 @@ bool Crawler::OnUserCreate(){
player.AddAnimation(AnimationState::WIZARD_IDLE_E); player.AddAnimation(AnimationState::WIZARD_IDLE_E);
player.AddAnimation(AnimationState::WIZARD_IDLE_S); player.AddAnimation(AnimationState::WIZARD_IDLE_S);
player.AddAnimation(AnimationState::WIZARD_IDLE_W); player.AddAnimation(AnimationState::WIZARD_IDLE_W);
player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_N);
player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_E);
player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_S);
player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_W);
player.AddAnimation(AnimationState::WIZARD_ATTACK_N);
player.AddAnimation(AnimationState::WIZARD_ATTACK_E);
player.AddAnimation(AnimationState::WIZARD_ATTACK_S);
player.AddAnimation(AnimationState::WIZARD_ATTACK_W);
view=TileTransformedView{GetScreenSize(),{1,1}}; view=TileTransformedView{GetScreenSize(),{1,1}};
player.SetClass(WARRIOR); player.SetClass(WARRIOR);
@ -252,6 +262,50 @@ void Crawler::InitializeAnimations(){
Animate2D::FrameSequence pl_wizard_idle_n; Animate2D::FrameSequence pl_wizard_idle_n;
pl_wizard_idle_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,1}*24,{24,24}}}); pl_wizard_idle_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,1}*24,{24,24}}});
ANIMATION_DATA[AnimationState::WIZARD_IDLE_N]=pl_wizard_idle_n; ANIMATION_DATA[AnimationState::WIZARD_IDLE_N]=pl_wizard_idle_n;
Animate2D::FrameSequence pl_wizard_idle_attack_s;
pl_wizard_idle_attack_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,0}*24,{24,24}}});
ANIMATION_DATA[AnimationState::WIZARD_IDLE_ATTACK_S]=pl_wizard_idle_attack_s;
Animate2D::FrameSequence pl_wizard_idle_attack_e;
pl_wizard_idle_attack_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,3}*24,{24,24}}});
ANIMATION_DATA[AnimationState::WIZARD_IDLE_ATTACK_E]=pl_wizard_idle_attack_e;
Animate2D::FrameSequence pl_wizard_idle_attack_w;
pl_wizard_idle_attack_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,2}*24,{24,24}}});
ANIMATION_DATA[AnimationState::WIZARD_IDLE_ATTACK_W]=pl_wizard_idle_attack_w;
Animate2D::FrameSequence pl_wizard_idle_attack_n;
pl_wizard_idle_attack_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,1}*24,{24,24}}});
ANIMATION_DATA[AnimationState::WIZARD_IDLE_ATTACK_N]=pl_wizard_idle_attack_n;
Animate2D::FrameSequence pl_wizard_attack_s(0.2);
for(int i=0;i<3;i++){
pl_wizard_attack_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{4+i,0}*24,{24,24}}});
if(i==1){
pl_wizard_attack_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,0}*24,{24,24}}});
}
}
ANIMATION_DATA[AnimationState::WIZARD_ATTACK_S]=pl_wizard_attack_s;
Animate2D::FrameSequence pl_wizard_attack_e(0.2);
for(int i=0;i<3;i++){
pl_wizard_attack_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,3}*24,{24,24}}});
if(i==1){
pl_wizard_attack_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,3}*24,{24,24}}});
}
}
ANIMATION_DATA[AnimationState::WIZARD_ATTACK_E]=pl_wizard_attack_e;
Animate2D::FrameSequence pl_wizard_attack_w(0.2);
for(int i=0;i<3;i++){
pl_wizard_attack_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,2}*24,{24,24}}});
if(i==1){
pl_wizard_attack_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,2}*24,{24,24}}});
}
}
ANIMATION_DATA[AnimationState::WIZARD_ATTACK_W]=pl_wizard_attack_w;
Animate2D::FrameSequence pl_wizard_attack_n(0.2);
for(int i=0;i<3;i++){
pl_wizard_attack_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,1}*24,{24,24}}});
if(i==1){
pl_wizard_attack_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,1}*24,{24,24}}});
}
}
ANIMATION_DATA[AnimationState::WIZARD_ATTACK_N]=pl_wizard_attack_n;
//Load slime animations. //Load slime animations.
for(int slime=0;slime<4;slime++){ for(int slime=0;slime<4;slime++){
@ -289,28 +343,28 @@ void Crawler::InitializeAnimations(){
} }
bool Crawler::LeftHeld(){ bool Crawler::LeftHeld(){
return GetKey(LEFT).bHeld|GetKey(A).bHeld; return GetKey(LEFT).bHeld||GetKey(A).bHeld;
} }
bool Crawler::RightHeld(){ bool Crawler::RightHeld(){
return GetKey(RIGHT).bHeld|GetKey(D).bHeld; return GetKey(RIGHT).bHeld||GetKey(D).bHeld;
} }
bool Crawler::UpHeld(){ bool Crawler::UpHeld(){
return GetKey(UP).bHeld|GetKey(W).bHeld; return GetKey(UP).bHeld||GetKey(W).bHeld;
} }
bool Crawler::DownHeld(){ bool Crawler::DownHeld(){
return GetKey(DOWN).bHeld|GetKey(S).bHeld; return GetKey(DOWN).bHeld||GetKey(S).bHeld;
} }
bool Crawler::LeftReleased(){ bool Crawler::LeftReleased(){
return GetKey(LEFT).bReleased|GetKey(A).bReleased; return GetKey(LEFT).bReleased||GetKey(A).bReleased;
} }
bool Crawler::RightReleased(){ bool Crawler::RightReleased(){
return GetKey(RIGHT).bReleased|GetKey(D).bReleased; return GetKey(RIGHT).bReleased||GetKey(D).bReleased;
} }
bool Crawler::UpReleased(){ bool Crawler::UpReleased(){
return GetKey(UP).bReleased|GetKey(W).bReleased; return GetKey(UP).bReleased||GetKey(W).bReleased;
} }
bool Crawler::DownReleased(){ bool Crawler::DownReleased(){
return GetKey(DOWN).bReleased|GetKey(S).bReleased; return GetKey(DOWN).bReleased||GetKey(S).bReleased;
} }
void Crawler::HandleUserInput(float fElapsedTime){ void Crawler::HandleUserInput(float fElapsedTime){

@ -23,6 +23,9 @@ class Crawler : public olc::PixelGameEngine
GFX_Effect_GroundSlam_Back,GFX_Effect_GroundSlam_Front, GFX_Effect_GroundSlam_Back,GFX_Effect_GroundSlam_Front,
GFX_Heart,GFX_BLOCK_BUBBLE,GFX_Ranger_Sheet,GFX_Wizard_Sheet, GFX_Heart,GFX_BLOCK_BUBBLE,GFX_Ranger_Sheet,GFX_Wizard_Sheet,
GFX_Battlecry_Effect,GFX_Mana,GFX_SonicSlash; GFX_Battlecry_Effect,GFX_Mana,GFX_SonicSlash;
public:
Renderable GFX_BulletCircle,GFX_BulletCircleOutline;
private:
std::vector<Effect>foregroundEffects,backgroundEffects; std::vector<Effect>foregroundEffects,backgroundEffects;
std::map<MapName,Map>MAP_DATA; std::map<MapName,Map>MAP_DATA;
std::map<std::string,TilesetData>MAP_TILESETS; std::map<std::string,TilesetData>MAP_TILESETS;

@ -111,33 +111,39 @@ void Monster::PerformShootAnimation(){
}break; }break;
} }
} }
void Monster::SetX(float x){ bool Monster::SetX(float x){
vf2d newPos={x,pos.y}; vf2d newPos={x,pos.y};
vi2d tilePos=vi2d(newPos/24)*24; vi2d tilePos=vi2d(newPos/24)*24;
geom2d::rect<int>collisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos); geom2d::rect<int>collisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos);
if(collisionRect.pos==vi2d{0,0}&&collisionRect.size==vi2d{1,1}){ if(collisionRect.pos==vi2d{0,0}&&collisionRect.size==vi2d{1,1}){
pos.x=std::clamp(x,12.f*GetSizeMult(),float(game->WORLD_SIZE.x*24-12*GetSizeMult())); pos.x=std::clamp(x,12.f*GetSizeMult(),float(game->WORLD_SIZE.x*24-12*GetSizeMult()));
return true;
} else { } else {
geom2d::rect<float>collision={collisionRect.pos,collisionRect.size}; geom2d::rect<float>collision={collisionRect.pos,collisionRect.size};
collision.pos+=tilePos; collision.pos+=tilePos;
if(!geom2d::overlaps(newPos,collision)){ if(!geom2d::overlaps(newPos,collision)){
pos.x=std::clamp(x,12.f*GetSizeMult(),float(game->WORLD_SIZE.x*24-12*GetSizeMult())); pos.x=std::clamp(x,12.f*GetSizeMult(),float(game->WORLD_SIZE.x*24-12*GetSizeMult()));
return true;
} }
} }
return false;
} }
void Monster::SetY(float y){ bool Monster::SetY(float y){
vf2d newPos={pos.x,y}; vf2d newPos={pos.x,y};
vi2d tilePos=vi2d(newPos/24)*24; vi2d tilePos=vi2d(newPos/24)*24;
geom2d::rect<int>collisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos); geom2d::rect<int>collisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos);
if(collisionRect.pos==vi2d{0,0}&&collisionRect.size==vi2d{1,1}){ if(collisionRect.pos==vi2d{0,0}&&collisionRect.size==vi2d{1,1}){
pos.y=std::clamp(y,12.f*GetSizeMult(),float(game->WORLD_SIZE.y*24-12*GetSizeMult())); pos.y=std::clamp(y,12.f*GetSizeMult(),float(game->WORLD_SIZE.y*24-12*GetSizeMult()));
return true;
} else { } else {
geom2d::rect<float>collision={collisionRect.pos,collisionRect.size}; geom2d::rect<float>collision={collisionRect.pos,collisionRect.size};
collision.pos+=tilePos; collision.pos+=tilePos;
if(!geom2d::overlaps(newPos,collision)){ if(!geom2d::overlaps(newPos,collision)){
pos.y=std::clamp(y,12.f*GetSizeMult(),float(game->WORLD_SIZE.y*24-12*GetSizeMult())); pos.y=std::clamp(y,12.f*GetSizeMult(),float(game->WORLD_SIZE.y*24-12*GetSizeMult()));
return true;
} }
} }
return false;
} }
bool Monster::Update(float fElapsedTime){ bool Monster::Update(float fElapsedTime){
if(IsAlive()){ if(IsAlive()){
@ -208,25 +214,11 @@ bool Monster::Update(float fElapsedTime){
targetAcquireTimer=1; targetAcquireTimer=1;
if(line.length()<24*6){ if(line.length()<24*6){
target=line.upoint(-1.2); target=line.upoint(-1.2);
if(pos.x-12*size>1&&pos.x+12*size<game->GetWorldSize().x*24-1&& geom2d::line moveTowardsLine=geom2d::line(pos,target);
pos.y-12*size>1&&pos.y+12*size<game->GetWorldSize().y*24-1){ if(canMove&&abs(moveTowardsLine.vector().norm().x)>=0.5){
state=MOVE_AWAY; state=MOVE_AWAY;
} else } else {
if(pos.x-12*size<=1||pos.x+12*size>=game->GetWorldSize().x*24-1){ state=NORMAL;
geom2d::line moveTowardsLine=geom2d::line(pos,target);
if(abs(moveTowardsLine.vector().norm().y)>=0.5){
state=MOVE_AWAY;
} else {
state=NORMAL;
}
} else
if(pos.y-12*size<=1||pos.y+12*size>=game->GetWorldSize().y*24-1){
geom2d::line moveTowardsLine=geom2d::line(pos,target);
if(abs(moveTowardsLine.vector().norm().x)>=0.5){
state=MOVE_AWAY;
} else {
state=NORMAL;
}
} }
} else } else
if(line.length()>24*7){ if(line.length()>24*7){
@ -236,11 +228,12 @@ bool Monster::Update(float fElapsedTime){
state=NORMAL; state=NORMAL;
} }
} }
canMove=true;
geom2d::line moveTowardsLine=geom2d::line(pos,target); geom2d::line moveTowardsLine=geom2d::line(pos,target);
switch(state){ switch(state){
case MOVE_TOWARDS:{ case MOVE_TOWARDS:{
if(moveTowardsLine.length()>1){ if(moveTowardsLine.length()>1){
SetPosition(pos+moveTowardsLine.vector().norm()*100*fElapsedTime*GetMoveSpdMult()); canMove=SetPosition(pos+moveTowardsLine.vector().norm()*100*fElapsedTime*GetMoveSpdMult());
} }
if(line.length()<=24*7){ if(line.length()<=24*7){
state=NORMAL; state=NORMAL;
@ -254,7 +247,7 @@ bool Monster::Update(float fElapsedTime){
}break; }break;
case MOVE_AWAY:{ case MOVE_AWAY:{
if(moveTowardsLine.length()>1){ if(moveTowardsLine.length()>1){
SetPosition(pos+moveTowardsLine.vector().norm()*100*fElapsedTime*GetMoveSpdMult()); canMove=SetPosition(pos+moveTowardsLine.vector().norm()*100*fElapsedTime*GetMoveSpdMult());
} }
if(line.length()>=24*6){ if(line.length()>=24*6){
state=NORMAL; state=NORMAL;
@ -329,9 +322,8 @@ void Monster::Collision(){
void Monster::SetVelocity(vf2d vel){ void Monster::SetVelocity(vf2d vel){
this->vel=vel; this->vel=vel;
} }
void Monster::SetPosition(vf2d pos){ bool Monster::SetPosition(vf2d pos){
SetX(pos.x); return SetX(pos.x)|SetY(pos.y);
SetY(pos.y);
} }
AnimationState Monster::GetDeathAnimationName(){ AnimationState Monster::GetDeathAnimationName(){
switch(type){ switch(type){

@ -72,6 +72,7 @@ struct Monster{
std::vector<Buff>buffList; std::vector<Buff>buffList;
AnimationState GetDeathAnimationName(); AnimationState GetDeathAnimationName();
bool hasHitPlayer=false; bool hasHitPlayer=false;
bool canMove=true; //Set to false when stuck due to collisions.
public: public:
Monster(); Monster();
Monster(vf2d pos,MonsterData data); Monster(vf2d pos,MonsterData data);
@ -93,9 +94,12 @@ struct Monster{
void Collision(Monster&p); void Collision(Monster&p);
void Collision(); void Collision();
void SetVelocity(vf2d vel); void SetVelocity(vf2d vel);
void SetPosition(vf2d pos); //Returns false if the monster could not be moved to the requested location due to collision.
void SetX(float x); bool SetPosition(vf2d pos);
void SetY(float y); //Returns false if the monster could not be moved to the requested location due to collision.
bool SetX(float x);
//Returns false if the monster could not be moved to the requested location due to collision.
bool SetY(float y);
void PerformJumpAnimation(); void PerformJumpAnimation();
void PerformShootAnimation(); void PerformShootAnimation();

@ -291,6 +291,8 @@ void Player::Update(float fElapsedTime){
case BARD: { case BARD: {
}break; }break;
case WIZARD: { case WIZARD: {
attack_cooldown_timer=MAGIC_ATTACK_COOLDOWN;
//PLAYER_BULLET_LIST.push_back(Bullet();
}break; }break;
case WITCH: { case WITCH: {
}break; }break;

@ -23,6 +23,7 @@ struct Player{
float attack_range=1.5f; float attack_range=1.5f;
Ability rightClickAbility,ability1,ability2,ability3; Ability rightClickAbility,ability1,ability2,ability3;
const float ATTACK_COOLDOWN=0.35f; const float ATTACK_COOLDOWN=0.35f;
const float MAGIC_ATTACK_COOLDOWN=0.85f;
float attack_cooldown_timer=0; float attack_cooldown_timer=0;
float spin_attack_timer=0; float spin_attack_timer=0;
float spin_spd=0; float spin_spd=0;

@ -2,7 +2,7 @@
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 2 #define VERSION_MINOR 2
#define VERSION_PATCH 0 #define VERSION_PATCH 0
#define VERSION_BUILD 295 #define VERSION_BUILD 301
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

@ -492,16 +492,16 @@
</layer> </layer>
<objectgroup id="4" name="Object Layer 1"> <objectgroup id="4" name="Object Layer 1">
<object id="1" name="Player Spawn" type="PlayerSpawnLocation" x="288" y="2160" width="24" height="24"/> <object id="1" name="Player Spawn" type="PlayerSpawnLocation" x="288" y="2160" width="24" height="24"/>
<object id="2" name="2x Green Slime" type="SpawnGroup" x="480" y="2064" width="384" height="408"> <object id="2" name="2x Blue Slime" type="SpawnGroup" x="480" y="2064" width="384" height="408">
<properties> <properties>
<property name="Monster1" type="class" propertytype="Monster"> <property name="Monster1" type="class" propertytype="Monster">
<properties> <properties>
<property name="Type" type="int" propertytype="MonsterName" value="1"/> <property name="Type" type="int" propertytype="MonsterName" value="2"/>
</properties> </properties>
</property> </property>
<property name="Monster2" type="class" propertytype="Monster"> <property name="Monster2" type="class" propertytype="Monster">
<properties> <properties>
<property name="Type" type="int" propertytype="MonsterName" value="1"/> <property name="Type" type="int" propertytype="MonsterName" value="2"/>
</properties> </properties>
</property> </property>
</properties> </properties>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 B

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.
Loading…
Cancel
Save