From db9c35f813a0aad90e7b74136b61426a32a14494 Mon Sep 17 00:00:00 2001 From: sigonasr2 Date: Sun, 14 Jan 2024 16:23:31 -0600 Subject: [PATCH] Wolf behavior implemented. Fixed facing direction behavior for AI scripts. --- .../AdventuresInLestoria.cpp | 2 +- Adventures in Lestoria/Attributable.h | 6 ++ Adventures in Lestoria/DEFINES.h | 2 +- Adventures in Lestoria/Monster.cpp | 23 ++++-- Adventures in Lestoria/Monster.h | 4 ++ Adventures in Lestoria/MonsterAttribute.h | 6 ++ Adventures in Lestoria/Pathfinding.cpp | 4 +- Adventures in Lestoria/Player.cpp | 4 +- Adventures in Lestoria/Player.h | 10 ++- Adventures in Lestoria/RunTowards.cpp | 3 + Adventures in Lestoria/ShootAfar.cpp | 12 +--- Adventures in Lestoria/TODO.txt | 2 + Adventures in Lestoria/Version.h | 2 +- Adventures in Lestoria/Wizard.cpp | 2 +- Adventures in Lestoria/Wolf.cpp | 70 ++++++++++++++++--- .../assets/Campaigns/1_1_v2.tmx | 6 +- .../assets/config/MonsterStrategies.txt | 6 ++ .../assets/config/Monsters.txt | 2 +- Adventures in Lestoria/olcUTIL_Geometry2D.h | 5 ++ 19 files changed, 131 insertions(+), 40 deletions(-) diff --git a/Adventures in Lestoria/AdventuresInLestoria.cpp b/Adventures in Lestoria/AdventuresInLestoria.cpp index 42a16a0a..89aeb197 100644 --- a/Adventures in Lestoria/AdventuresInLestoria.cpp +++ b/Adventures in Lestoria/AdventuresInLestoria.cpp @@ -1983,7 +1983,7 @@ geom2d::rectAiL::GetTileCollision(MapName map,vf2d pos,bool upperLevel){ int tileID=layer.tiles[int(pos.y)/GetCurrentMapData().tilewidth][int(pos.x)/GetCurrentMapData().tilewidth]-1; if(tileID!=-1&&GetTileSheet(map,tileID%1000000).tileset->collision.find(tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1)!=GetTileSheet(map,tileID%1000000).tileset->collision.end()){ geom2d::rectcollisionRect=GetTileSheet(map,tileID%1000000).tileset->collision[tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1].collision; - if(foundRect.pos==NO_COLLISION.pos&&foundRect.size==NO_COLLISION.size){ + if(foundRect==NO_COLLISION){ foundRect=collisionRect; }else{ //When we find another rectangle in the same square, we expand it to consume the area, whichever tile creates a larger surface or the combination of the two. diff --git a/Adventures in Lestoria/Attributable.h b/Adventures in Lestoria/Attributable.h index 8e989892..f97e0190 100644 --- a/Adventures in Lestoria/Attributable.h +++ b/Adventures in Lestoria/Attributable.h @@ -74,4 +74,10 @@ public: } return std::get(attributes[a]); }; + inline std::vector&GetVec(Attribute a){ + if(attributes.count(a)==0){ + attributes[a]=std::vector{}; + } + return std::get>(attributes[a]); + }; }; \ No newline at end of file diff --git a/Adventures in Lestoria/DEFINES.h b/Adventures in Lestoria/DEFINES.h index 154b3cdc..d5e67cb3 100644 --- a/Adventures in Lestoria/DEFINES.h +++ b/Adventures in Lestoria/DEFINES.h @@ -65,7 +65,7 @@ using BackdropName=std::string; #define ACCESS_PLAYER Player*p=game->GetPlayer(); -#define VARIANTS float,int,std::string,bool,vf2d +#define VARIANTS float,int,std::string,bool,vf2d,std::vector #undef INFINITE #define INFINITE 999999 diff --git a/Adventures in Lestoria/Monster.cpp b/Adventures in Lestoria/Monster.cpp index e550f147..841b84f5 100644 --- a/Adventures in Lestoria/Monster.cpp +++ b/Adventures in Lestoria/Monster.cpp @@ -125,7 +125,7 @@ bool Monster::_SetX(float x,const bool monsterInvoked){ vf2d newPos={x,pos.y}; vi2d tilePos=vi2d(newPos/float(game->GetCurrentMapData().tilewidth))*game->GetCurrentMapData().tilewidth; geom2d::rectcollisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos,upperLevel); - if(collisionRect.pos==game->NO_COLLISION.pos&&collisionRect.size==game->NO_COLLISION.size){ + if(collisionRect==game->NO_COLLISION){ pos.x=std::clamp(x,game->GetCurrentMapData().tilewidth/2.f*GetSizeMult(),float(game->GetCurrentMapData().width*game->GetCurrentMapData().tilewidth-game->GetCurrentMapData().tilewidth/2.f*GetSizeMult())); Moved(); return true; @@ -155,7 +155,7 @@ bool Monster::_SetY(float y,const bool monsterInvoked){ vf2d newPos={pos.x,y}; vi2d tilePos=vi2d(newPos/float(game->GetCurrentMapData().tilewidth))*game->GetCurrentMapData().tilewidth; geom2d::rectcollisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos,upperLevel); - if(collisionRect.pos==game->NO_COLLISION.pos&&collisionRect.size==game->NO_COLLISION.size){ + if(collisionRect==game->NO_COLLISION){ pos.y=std::clamp(y,game->GetCurrentMapData().tilewidth/2.f*GetSizeMult(),float(game->GetCurrentMapData().height*game->GetCurrentMapData().tilewidth-game->GetCurrentMapData().tilewidth/2.f*GetSizeMult())); Moved(); return true; @@ -267,6 +267,15 @@ bool Monster::Update(float fElapsedTime){ Key Monster::GetFacingDirection(){ return facingDirection; } + +void Monster::UpdateFacingDirection(vf2d facingTargetPoint){ + if(facingTargetPoint.x>GetPos().x){ + facingDirection=RIGHT; + } + if(facingTargetPoint.x0){ vf2d shadowScale=vf2d{8*GetSizeMult()/3.f,1}/std::max(1.f,GetZ()/24); @@ -458,6 +467,10 @@ void Monster::AddBuff(BuffType type,float duration,float intensity){ buffList.push_back(Buff{type,duration,intensity}); } +void Monster::RemoveBuff(BuffType type){ + std::erase_if(buffList,[&](const Buff&buff){return buff.type==type;}); +} + bool Monster::StartPathfinding(float pathingTime){ SetState(State::PATH_AROUND); path=game->pathfinder.Solve_WalkPath(pos,target,12,OnUpperLevel()); @@ -480,11 +493,7 @@ void Monster::PathAroundBehavior(float fElapsedTime){ pathIndex=0; targetAcquireTimer=0; } - if(moveTowardsLine.vector().x>0){ - facingDirection=RIGHT; - } else { - facingDirection=LEFT; - } + UpdateFacingDirection(moveTowardsLine.end); }else{ if(pathIndex>=path.points.size()-1){ //We have reached the end of the path! diff --git a/Adventures in Lestoria/Monster.h b/Adventures in Lestoria/Monster.h index 569693e5..e2681b38 100644 --- a/Adventures in Lestoria/Monster.h +++ b/Adventures in Lestoria/Monster.h @@ -133,6 +133,8 @@ public: bool IsAlive(); vf2d&GetTargetPos(); Key GetFacingDirection(); + //Will make the monster face in the correct direction relative to a given target point to look at. + void UpdateFacingDirection(vf2d facingTargetPoint); void Draw(); void DrawReflection(float drawRatioX,float multiplierX); void Collision(Player*p); @@ -155,6 +157,8 @@ public: void PathAroundBehavior(float fElapsedTime); void AddBuff(BuffType type,float duration,float intensity); std::vectorGetBuffs(BuffType buff); + //Removes all buffs of a given type. + void RemoveBuff(BuffType type); State::State GetState(); void SetState(State::State newState); static void InitializeStrategies(); diff --git a/Adventures in Lestoria/MonsterAttribute.h b/Adventures in Lestoria/MonsterAttribute.h index 59d9fc8a..19dea624 100644 --- a/Adventures in Lestoria/MonsterAttribute.h +++ b/Adventures in Lestoria/MonsterAttribute.h @@ -42,6 +42,7 @@ All rights reserved. #define S(attr) GetString(attr) #define B(attr) GetBool(attr) #define V(attr) GetVf2d(attr) +#define VEC(attr) GetVec(attr) enum class Attribute{ IFRAME_TIME_UPON_HIT, //When this is set, the monster gains iframes if they take damage based on the value this is set to. @@ -79,4 +80,9 @@ enum class Attribute{ PHASE, LOCKON_WAITTIME, LOCKON_POS, + TARGET_TIMER, + DISENGAGE_PATH, + PATH_INDEX, + PATH_DIR, + PREV_POS, }; \ No newline at end of file diff --git a/Adventures in Lestoria/Pathfinding.cpp b/Adventures in Lestoria/Pathfinding.cpp index af7b8dae..48c607c5 100644 --- a/Adventures in Lestoria/Pathfinding.cpp +++ b/Adventures in Lestoria/Pathfinding.cpp @@ -63,13 +63,13 @@ void Pathfinding::Initialize(){ node.x = x; // ...because we give each node its own coordinates node.y = y; // ...because we give each node its own coordinates geom2d::recttile=game->GetTileCollision(game->GetCurrentLevel(),{float(x),float(y)}); - if(tile.pos==game->NO_COLLISION.pos&&tile.size==game->NO_COLLISION.size){ + if(tile==game->NO_COLLISION){ node.bObstacle=false; }else{ node.bObstacle=geom2d::overlaps(vf2d{fmodf(x+gridSpacing.x/2,24),fmodf(y+gridSpacing.y/2,24)},tile); } tile=game->GetTileCollision(game->GetCurrentLevel(),{float(x),float(y)},true); - if(tile.pos==game->NO_COLLISION.pos&&tile.size==game->NO_COLLISION.size){ + if(tile==game->NO_COLLISION){ node.bObstacleUpper=false; }else{ node.bObstacleUpper=geom2d::overlaps(vf2d{fmodf(x,24),fmodf(y,24)},tile); diff --git a/Adventures in Lestoria/Player.cpp b/Adventures in Lestoria/Player.cpp index cdabf6b4..e1c68587 100644 --- a/Adventures in Lestoria/Player.cpp +++ b/Adventures in Lestoria/Player.cpp @@ -110,7 +110,7 @@ bool Player::_SetX(float x,const bool playerInvoked){ vi2d tilePos=vi2d(newPos/float(game->GetCurrentMapData().tilewidth))*game->GetCurrentMapData().tilewidth; geom2d::rectcollisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos,upperLevel); #pragma region lambdas - auto NoTileCollisionExistsHere=[&](){return collisionRect.pos==game->NO_COLLISION.pos&&collisionRect.size==game->NO_COLLISION.size;}; + auto NoTileCollisionExistsHere=[&](){return collisionRect==game->NO_COLLISION;}; #pragma endregion if(NoTileCollisionExistsHere()){ pos.x=std::clamp(x,game->GetCurrentMapData().tilewidth/2.f*GetSizeMult(),float(game->GetCurrentMapData().width*game->GetCurrentMapData().tilewidth-game->GetCurrentMapData().tilewidth/2.f*GetSizeMult())); @@ -143,7 +143,7 @@ bool Player::_SetY(float y,const bool playerInvoked){ vi2d tilePos=vi2d(newPos/float(game->GetCurrentMapData().tilewidth))*game->GetCurrentMapData().tilewidth; geom2d::rectcollisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos,upperLevel); #pragma region lambdas - auto NoTileCollisionExistsHere=[&](){return collisionRect.pos==game->NO_COLLISION.pos&&collisionRect.size==game->NO_COLLISION.size;}; + auto NoTileCollisionExistsHere=[&](){return collisionRect==game->NO_COLLISION;}; #pragma endregion if(NoTileCollisionExistsHere()){ pos.y=std::clamp(y,game->GetCurrentMapData().tilewidth/2.f*GetSizeMult(),float(game->GetCurrentMapData().height*game->GetCurrentMapData().tilewidth-game->GetCurrentMapData().tilewidth/2.f*GetSizeMult())); diff --git a/Adventures in Lestoria/Player.h b/Adventures in Lestoria/Player.h index ba38e0f3..b03d90e9 100644 --- a/Adventures in Lestoria/Player.h +++ b/Adventures in Lestoria/Player.h @@ -159,11 +159,15 @@ public: void AddBuff(BuffType type,float duration,float intensity,std::setattr); void AddBuff(BuffType type,float duration,float intensity,std::setattr); void AddBuff(BuffType type,float duration,float intensity,float timeBetweenTicks,std::functionrepeatAction); + const std::vectorGetBuffs(BuffType buff)const; const std::vectorGetStatBuffs(const std::vector&attr)const; - void RemoveBuff(BuffType type); //Removes the first buff found. - void RemoveAllBuffs(BuffType type); //Removes all buffs of a certain type. - void RemoveAllBuffs(); //Remove every buff. + //Removes the first buff found. + void RemoveBuff(BuffType type); + //Removes all buffs of a certain type. + void RemoveAllBuffs(BuffType type); + //Remove every buff. + void RemoveAllBuffs(); void RecalculateEquipStats(); diff --git a/Adventures in Lestoria/RunTowards.cpp b/Adventures in Lestoria/RunTowards.cpp index 822e0b00..db91251f 100644 --- a/Adventures in Lestoria/RunTowards.cpp +++ b/Adventures in Lestoria/RunTowards.cpp @@ -58,6 +58,9 @@ void Monster::STRATEGY::RUN_TOWARDS(Monster&m,float fElapsedTime,std::string str } m.SetState(State::MOVE_TOWARDS); } + if(geom2d::line(m.pos,m.target).length()>4.f){ + m.UpdateFacingDirection(m.target); + } switch(m.state){ case State::MOVE_TOWARDS:{ if(geom2d::line(m.pos,m.target).length()>100*fElapsedTime*m.GetMoveSpdMult()){ diff --git a/Adventures in Lestoria/ShootAfar.cpp b/Adventures in Lestoria/ShootAfar.cpp index cb20bf94..c95537a9 100644 --- a/Adventures in Lestoria/ShootAfar.cpp +++ b/Adventures in Lestoria/ShootAfar.cpp @@ -101,11 +101,7 @@ void Monster::STRATEGY::SHOOT_AFAR(Monster&m,float fElapsedTime,std::string stra if(line.length()<=24.f*ConfigInt("CloseInRange")/100.0f){ m.SetState(State::NORMAL); } - if(moveTowardsLine.vector().x>0){ - m.facingDirection=RIGHT; - } else { - m.facingDirection=LEFT; - } + m.UpdateFacingDirection(moveTowardsLine.end); m.PerformJumpAnimation(); }break; case State::MOVE_AWAY:{ @@ -129,11 +125,7 @@ void Monster::STRATEGY::SHOOT_AFAR(Monster&m,float fElapsedTime,std::string stra if((m.path.points.size()==0&&!m.canMove)||line.length()>=24.f*ConfigInt("Range")/100.f){ m.SetState(State::NORMAL); } - if(moveTowardsLine.vector().x>0){ - m.facingDirection=RIGHT; - } else { - m.facingDirection=LEFT; - } + m.UpdateFacingDirection(moveTowardsLine.end); m.PerformJumpAnimation(); }break; case State::PATH_AROUND:{ diff --git a/Adventures in Lestoria/TODO.txt b/Adventures in Lestoria/TODO.txt index 66377dbd..ac51c7f6 100644 --- a/Adventures in Lestoria/TODO.txt +++ b/Adventures in Lestoria/TODO.txt @@ -12,6 +12,8 @@ Settings Menu January 31st ============ +Make new unlocked nodes more obvious, made neighboring nodes more obvious + Implement the rest of the enemy types: - Baby Wolf - Wolf diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h index c23d2973..df05af58 100644 --- a/Adventures in Lestoria/Version.h +++ b/Adventures in Lestoria/Version.h @@ -39,7 +39,7 @@ All rights reserved. #define VERSION_MAJOR 0 #define VERSION_MINOR 2 #define VERSION_PATCH 1 -#define VERSION_BUILD 5761 +#define VERSION_BUILD 5794 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Adventures in Lestoria/Wizard.cpp b/Adventures in Lestoria/Wizard.cpp index 7f1db84b..bcb2f6cd 100644 --- a/Adventures in Lestoria/Wizard.cpp +++ b/Adventures in Lestoria/Wizard.cpp @@ -124,7 +124,7 @@ void Wizard::InitializeClassAbilities(){ vi2d tilePos=vi2d(teleportPoint/float(game->GetCurrentMapData().tilewidth))*game->GetCurrentMapData().tilewidth; geom2d::rectcollisionRect=game->GetTileCollision(game->GetCurrentLevel(),teleportPoint,p->OnUpperLevel()); #pragma region lambdas - auto NoTileCollisionExistsHere=[&](){return collisionRect.pos==game->NO_COLLISION.pos&&collisionRect.size==game->NO_COLLISION.size;}; + auto NoTileCollisionExistsHere=[&](){return collisionRect==game->NO_COLLISION;}; #pragma endregion collisionRect.pos+=tilePos; #pragma region lambdas diff --git a/Adventures in Lestoria/Wolf.cpp b/Adventures in Lestoria/Wolf.cpp index 40fbc2e1..345d898a 100644 --- a/Adventures in Lestoria/Wolf.cpp +++ b/Adventures in Lestoria/Wolf.cpp @@ -51,20 +51,74 @@ using A=Attribute; void Monster::STRATEGY::WOLF(Monster&m,float fElapsedTime,std::string strategy){ switch(m.I(A::PHASE)){ case 0:{ //Run towards the player. - float distToPlayer = geom2d::line(game->GetPlayer()->GetPos(),m.GetPos()).length(); - if(distToPlayer<=ConfigFloat("Lockon Range")){ + float distToPlayer=geom2d::line(game->GetPlayer()->GetPos(),m.GetPos()).length(); + if(distToPlayer<=ConfigFloat("Lockon Range")/100*24.f){ m.I(A::PHASE)=1; - m.V(A::LOCKON_POS)=game->GetPlayer()->GetPos(); - m.AddBuff(BuffType::) + m.V(A::LOCKON_POS)=geom2d::line(m.GetPos(),game->GetPlayer()->GetPos()).upoint(1.2f); + m.AddBuff(BuffType::LOCKON_SPEEDBOOST,INFINITE,ConfigFloat("Lockon Speed Boost")/100); + m.F(A::TARGET_TIMER)=5.0f; } - + m.target=game->GetPlayer()->GetPos(); RUN_TOWARDS(m,fElapsedTime,"Run Towards"); }break; case 1:{ //Charge the player. - + m.F(A::TARGET_TIMER)=std::max(0.f,m.F(A::TARGET_TIMER)-fElapsedTime); + float distToTarget=geom2d::line(m.GetPos(),m.V(A::LOCKON_POS)).length(); + if(distToTarget<=12.f||m.F(A::TARGET_TIMER)==0.f){ + m.I(A::PHASE)=2; + m.F(A::RECOVERY_TIME)=ConfigFloat("Charge Recovery Time"); + m.PerformIdleAnimation(); + }else{ + m.target=m.V(A::LOCKON_POS); + RUN_TOWARDS(m,fElapsedTime,"Run Towards"); + } + }break; + case 2:{ //Recovery period after charging. + m.F(A::RECOVERY_TIME)=std::max(0.f,m.F(A::RECOVERY_TIME)-fElapsedTime); + if(m.F(A::RECOVERY_TIME)==0.f){ + m.RemoveBuff(BuffType::LOCKON_SPEEDBOOST); + m.AddBuff(BuffType::SPEEDBOOST,ConfigFloatArr("Disengage Speed Boost",1),ConfigFloatArr("Disengage Speed Boost",0)/100); + std::vectordisengagePoints; + for(float angle=0.f;angle<360.f;angle+=22.5f){ + float range=50; + vf2d checkLoc=vf2d{0,util::degToRad(angle)}.cart(); + while(range<=ConfigFloat("Disengage Range")){ + checkLoc=game->GetPlayer()->GetPos()+vf2d{range/100*24.f,util::degToRad(angle)}.cart(); + if(game->GetTileCollision(game->GetCurrentMapName(),checkLoc,m.OnUpperLevel())!=game->NO_COLLISION){ + break; + } + range+=50; + } + disengagePoints.push_back(checkLoc); + } + m.path.Initialize(disengagePoints); + if(disengagePoints.size()!=16)ERR(std::format("Disengage Points size was not equal to 16! Size: {}",disengagePoints.size())); + if(m.path.points.size()!=16)ERR(std::format("Path Points size was not equal to 16! Size: {}",m.path.points.size())); + m.I(A::PATH_DIR)=util::random()%2; + if(m.I(A::PATH_DIR)==0)m.I(A::PATH_DIR)=-1; + m.pathIndex=util::random()%disengagePoints.size(); + m.I(A::PHASE)=3; + m.F(A::RUN_AWAY_TIMER)=ConfigFloat("Disengage Duration"); + m.PerformJumpAnimation(); + } }break; - case 3:{ - + case 3:{ //Disengage. + m.F(A::RUN_AWAY_TIMER)=std::max(0.f,m.F(A::RUN_AWAY_TIMER)-fElapsedTime); + m.pathIndex+=m.I(A::PATH_DIR)*fElapsedTime*1.25f; + m.pathIndex=fmod(m.pathIndex,m.path.points.size()); + if(m.pathIndex<0){ //When the modulus is negative, adding the total number of elements gets us to the correct index. + m.pathIndex=m.pathIndex+m.path.points.size(); + } + if(m.F(A::RUN_AWAY_TIMER)==0.f){ + m.I(A::PHASE)=0; + } + m.target=m.path.GetSplinePoint(m.pathIndex).pos; + geom2d::linemoveTowardsLine=geom2d::line(m.pos,m.path.GetSplinePoint(m.pathIndex).pos); + + if(moveTowardsLine.length()>4.f){ + m.UpdateFacingDirection(moveTowardsLine.end); + } + m.SetPos(m.pos+moveTowardsLine.vector().norm()*100*fElapsedTime*m.GetMoveSpdMult()); }break; } } \ No newline at end of file diff --git a/Adventures in Lestoria/assets/Campaigns/1_1_v2.tmx b/Adventures in Lestoria/assets/Campaigns/1_1_v2.tmx index 0117442c..236590f9 100644 --- a/Adventures in Lestoria/assets/Campaigns/1_1_v2.tmx +++ b/Adventures in Lestoria/assets/Campaigns/1_1_v2.tmx @@ -1075,7 +1075,7 @@ - + @@ -1716,14 +1716,14 @@ - + - + diff --git a/Adventures in Lestoria/assets/config/MonsterStrategies.txt b/Adventures in Lestoria/assets/config/MonsterStrategies.txt index 41adec49..75ee3ed0 100644 --- a/Adventures in Lestoria/assets/config/MonsterStrategies.txt +++ b/Adventures in Lestoria/assets/config/MonsterStrategies.txt @@ -198,10 +198,16 @@ MonsterStrategy # The speed boost percentage to increase by during the charge. Lockon Speed Boost = 15% + # Time waiting after charging. + Charge Recovery Time = 1.0s + # The speed boost percentage to increase by and the duration while disengaging. Disengage Speed Boost = 30%, 3s # The distance to disengage the player. Disengage Range = 800 + + # The amount of time to spend disengaged. + Disengage Duration = 3.0s } } \ No newline at end of file diff --git a/Adventures in Lestoria/assets/config/Monsters.txt b/Adventures in Lestoria/assets/config/Monsters.txt index 9f3cb928..9ac4b8eb 100644 --- a/Adventures in Lestoria/assets/config/Monsters.txt +++ b/Adventures in Lestoria/assets/config/Monsters.txt @@ -221,7 +221,7 @@ Monsters XP = 14 - Strategy = Run Towards + Strategy = Wolf #Size of each animation frame SheetFrameSize = 24,24 diff --git a/Adventures in Lestoria/olcUTIL_Geometry2D.h b/Adventures in Lestoria/olcUTIL_Geometry2D.h index b7fdcccb..87b0561a 100644 --- a/Adventures in Lestoria/olcUTIL_Geometry2D.h +++ b/Adventures in Lestoria/olcUTIL_Geometry2D.h @@ -2428,6 +2428,11 @@ namespace olc::utils::geom2d return internal::filter_duplicate_points(intersections); } + + template + inline const bool operator ==(const rect&r1,const rect&r2){ + return r1.pos==r2.pos&&r1.size==r2.size; + } } using namespace olc;