Proximity targeting and healing other targets when one's health is full.

CorrectiveAction
sigonasr2 1 year ago
parent fd5e6048ac
commit bc3e2bf6b0
  1. 58
      olcCodeJam2023Entry/Unit.cpp
  2. 31
      olcCodeJam2023Entry/Unit.h
  3. 29
      olcCodeJam2023Entry/VirusAttack.cpp

@ -14,7 +14,7 @@ BasicUnit::BasicUnit(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES
},pos,12,*IMAGES[VIRUS_IMG1],friendly,moveable){} },pos,12,*IMAGES[VIRUS_IMG1],friendly,moveable){}
void BasicUnit::Attack(Unit&victim){ void BasicUnit::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
victim<<=1; victim<<=1;
} }
@ -27,7 +27,7 @@ BasicUnit2::BasicUnit2(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAG
{HEALTH,4}, {HEALTH,4},
},pos,12,*IMAGES[VIRUS_IMG1],friendly,moveable){} },pos,12,*IMAGES[VIRUS_IMG1],friendly,moveable){}
void BasicUnit2::Attack(Unit&victim){ void BasicUnit2::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
victim>>=1; victim>>=1;
} }
@ -40,7 +40,7 @@ LeftShifter::LeftShifter(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IM
{HEALTH,4}, {HEALTH,4},
},pos,12,*IMAGES[LEFT_SHIFTER],friendly,moveable){} },pos,12,*IMAGES[LEFT_SHIFTER],friendly,moveable){}
void LeftShifter::Attack(Unit&victim){ void LeftShifter::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
victim<<=1; victim<<=1;
} }
@ -53,7 +53,7 @@ RightShifter::RightShifter(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&
{PROCEDURE,1}, {PROCEDURE,1},
},pos,12,*IMAGES[RIGHT_SHIFTER],friendly,moveable){} },pos,12,*IMAGES[RIGHT_SHIFTER],friendly,moveable){}
void RightShifter::Attack(Unit&victim){ void RightShifter::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
victim>>=1; victim>>=1;
} }
@ -66,8 +66,38 @@ BitRestorer::BitRestorer(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IM
{HEALTH,2}, {HEALTH,2},
},pos,12,*IMAGES[BIT_RESTORER],friendly,moveable,true,false){} },pos,12,*IMAGES[BIT_RESTORER],friendly,moveable,true,false){}
void BitRestorer::Attack(Unit&victim){ void BitRestorer::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
std::vector<int>emptyMemoryPositions;
for(int i=0;i<victim.GetMemorySize();i++){
if(!victim.memory[i]){
emptyMemoryPositions.emplace_back(i);
}
}
if(emptyMemoryPositions.size()==0){
//First see if we can find another damaged target, if we can, then we try healing them. Otherwise we exit.
AttemptToHealOtherAllies(otherUnits);
return;
}
int randomBit=emptyMemoryPositions[rand()%emptyMemoryPositions.size()];
victim.memory[randomBit]=victim.ghostMemory[randomBit]=true;
}
void BitRestorer::AttemptToHealOtherAllies(std::vector<std::shared_ptr<Unit>>&otherUnits){
std::vector<int>emptyMemoryPositions;
for(auto&u:otherUnits){
if(u->IsFriendly()&&InRange(u)){
for(int i=0;i<u->GetMemorySize();i++){
if(!u->memory[i]){
emptyMemoryPositions.emplace_back(i);
}
}
if(emptyMemoryPositions.size()!=0){
int randomBit=emptyMemoryPositions[rand()%emptyMemoryPositions.size()];
u->memory[randomBit]=u->ghostMemory[randomBit]=true;
return;
}
}
}
} }
MemorySwapper::MemorySwapper(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly,bool moveable) MemorySwapper::MemorySwapper(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly,bool moveable)
@ -79,7 +109,7 @@ MemorySwapper::MemorySwapper(vf2d pos,std::map<Image,std::unique_ptr<Renderable>
{MOVESPD,2}, {MOVESPD,2},
},pos,12,*IMAGES[MEMORY_SWAPPER],friendly,moveable,true){} },pos,12,*IMAGES[MEMORY_SWAPPER],friendly,moveable,true){}
void MemorySwapper::Attack(Unit&victim){ void MemorySwapper::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
} }
@ -92,7 +122,7 @@ Corrupter::Corrupter(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES
{HEALTH,4}, {HEALTH,4},
},pos,12,*IMAGES[CORRUPTER],friendly,moveable){} },pos,12,*IMAGES[CORRUPTER],friendly,moveable){}
void Corrupter::Attack(Unit&victim){ void Corrupter::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
} }
@ -105,7 +135,7 @@ MemoryAllocator::MemoryAllocator(vf2d pos,std::map<Image,std::unique_ptr<Rendera
{HEALTH,1}, {HEALTH,1},
},pos,12,*IMAGES[UNIT_ALLOCATOR],friendly,false,false){} },pos,12,*IMAGES[UNIT_ALLOCATOR],friendly,false,false){}
void MemoryAllocator::Attack(Unit&victim){ void MemoryAllocator::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
} }
@ -127,7 +157,7 @@ RAMBank::RAMBank(PixelGameEngine*pge,vf2d pos,std::map<Image,std::unique_ptr<Ren
pge->SetDrawTarget(nullptr); pge->SetDrawTarget(nullptr);
} }
void RAMBank::Attack(Unit&victim){ void RAMBank::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
} }
@ -419,7 +449,7 @@ void Unit::SetPos(vf2d newPos){
} }
} }
void Unit::AttemptAttack(Unit*unit){ void Unit::AttemptAttack(Unit*unit,std::vector<std::shared_ptr<Unit>>&otherUnits){
if(reloadTimer>0)return; if(reloadTimer>0)return;
Unit*finalTarget=nullptr; Unit*finalTarget=nullptr;
if(unit!=nullptr){ if(unit!=nullptr){
@ -433,15 +463,15 @@ void Unit::AttemptAttack(Unit*unit){
} }
if(finalTarget!=nullptr){ if(finalTarget!=nullptr){
if(InRange(finalTarget)){ if(InRange(finalTarget)){
_Attack(finalTarget); //Call the parent function first, followed by the child. _Attack(finalTarget,otherUnits); //Call the parent function first, followed by the child.
} }
} }
} }
void Unit::Update(PixelGameEngine*pge){} void Unit::Update(PixelGameEngine*pge){}
void Unit::_Attack(Unit*finalTarget){ void Unit::_Attack(Unit*finalTarget,std::vector<std::shared_ptr<Unit>>&otherUnits){
Attack(*finalTarget); Attack(*finalTarget,otherUnits);
reloadTimer=1.f/(GetAtkSpd()/2.f); reloadTimer=1.f/(GetAtkSpd()/2.f);
} }

@ -35,7 +35,7 @@ public:
std::vector<bool>memory; std::vector<bool>memory;
std::vector<bool>ghostMemory; std::vector<bool>ghostMemory;
virtual void Update(PixelGameEngine*pge); virtual void Update(PixelGameEngine*pge);
virtual void Attack(Unit&victim)=0; virtual void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)=0;
virtual void Draw(TileTransformedView&game,std::map<Image,std::unique_ptr<Renderable>>&IMAGES); virtual void Draw(TileTransformedView&game,std::map<Image,std::unique_ptr<Renderable>>&IMAGES);
virtual void DrawHud(TileTransformedView&game,std::map<Image,std::unique_ptr<Renderable>>&IMAGES); virtual void DrawHud(TileTransformedView&game,std::map<Image,std::unique_ptr<Renderable>>&IMAGES);
bool IsFriendly(); bool IsFriendly();
@ -48,7 +48,7 @@ public:
void SetTargetUnit(std::weak_ptr<Unit>target); void SetTargetUnit(std::weak_ptr<Unit>target);
void SetTargetLocation(vf2d targetLoc); void SetTargetLocation(vf2d targetLoc);
void SetPos(vf2d newPos); void SetPos(vf2d newPos);
void AttemptAttack(Unit*unit); void AttemptAttack(Unit*unit,std::vector<std::shared_ptr<Unit>>&otherUnits);
bool InFogOfWar(); bool InFogOfWar();
bool GhostInFogOfWar(); bool GhostInFogOfWar();
void HideGhost(); void HideGhost();
@ -90,6 +90,9 @@ protected:
Marker procedure; Marker procedure;
std::weak_ptr<Unit>target; std::weak_ptr<Unit>target;
vf2d targetLoc=CONSTANT::UNSELECTED; vf2d targetLoc=CONSTANT::UNSELECTED;
bool InRange(std::shared_ptr<Unit>target);
bool InRange(Unit*target);
bool InRange(vf2d pos);
private: private:
vf2d pos; vf2d pos;
vf2d ghostPos; vf2d ghostPos;
@ -97,11 +100,8 @@ private:
int GetBits(Marker&m); int GetBits(Marker&m);
bool selected=false; bool selected=false;
bool dead=false; bool dead=false;
bool InRange(std::shared_ptr<Unit>target);
bool InRange(Unit*target);
bool InRange(vf2d pos);
float reloadTimer=0; float reloadTimer=0;
void _Attack(Unit*finalTarget); void _Attack(Unit*finalTarget,std::vector<std::shared_ptr<Unit>>&otherUnits);
vf2d movementVel={0,0}; vf2d movementVel={0,0};
float changeDirTimer=0; float changeDirTimer=0;
bool moveable=true; bool moveable=true;
@ -111,42 +111,43 @@ private:
struct BasicUnit:Unit{ struct BasicUnit:Unit{
BasicUnit(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true); BasicUnit(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true);
void Attack(Unit&victim)override; void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
}; };
struct BasicUnit2:Unit{ struct BasicUnit2:Unit{
BasicUnit2(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true); BasicUnit2(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true);
void Attack(Unit&victim)override; void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
}; };
struct LeftShifter:Unit{ struct LeftShifter:Unit{
LeftShifter(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true); LeftShifter(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true);
void Attack(Unit&victim)override; void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
}; };
struct RightShifter:Unit{ struct RightShifter:Unit{
RightShifter(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true); RightShifter(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true);
void Attack(Unit&victim)override; void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
}; };
struct BitRestorer:Unit{ struct BitRestorer:Unit{
BitRestorer(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true); BitRestorer(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true);
void Attack(Unit&victim)override; void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
void AttemptToHealOtherAllies(std::vector<std::shared_ptr<Unit>>&otherUnits);
}; };
struct MemorySwapper:Unit{ struct MemorySwapper:Unit{
MemorySwapper(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true); MemorySwapper(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true);
void Attack(Unit&victim)override; void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
}; };
struct Corrupter:Unit{ struct Corrupter:Unit{
Corrupter(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true); Corrupter(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true);
void Attack(Unit&victim)override; void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
}; };
struct MemoryAllocator:Unit{ struct MemoryAllocator:Unit{
MemoryAllocator(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true); MemoryAllocator(vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true);
void Attack(Unit&victim)override; void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
}; };
struct RAMBank:Unit{ struct RAMBank:Unit{
@ -156,6 +157,6 @@ struct RAMBank:Unit{
Renderable&matrixImg; Renderable&matrixImg;
RAMBank(PixelGameEngine*pge,vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false); RAMBank(PixelGameEngine*pge,vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false);
void Update(PixelGameEngine*pge)override; void Update(PixelGameEngine*pge)override;
void Attack(Unit&victim)override; void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
void Draw(TileTransformedView&game,std::map<Image,std::unique_ptr<Renderable>>&IMAGES)override; void Draw(TileTransformedView&game,std::map<Image,std::unique_ptr<Renderable>>&IMAGES)override;
}; };

@ -64,6 +64,8 @@ bool VirusAttack::OnUserCreate(){
units.push_back(std::make_unique<RAMBank>(this,vf2d{320,320},IMAGES,false)); units.push_back(std::make_unique<RAMBank>(this,vf2d{320,320},IMAGES,false));
units.push_back(std::make_unique<RightShifter>(vf2d{360,300},IMAGES,false));
return true; return true;
} }
@ -109,17 +111,20 @@ void VirusAttack::HandleRightClickMove(){
if (GetMouse(1).bHeld){ if (GetMouse(1).bHeld){
bool selectedTarget=false; bool selectedTarget=false;
for(auto&u:units){ for(auto&u:units){
if(!u->IsFriendly()){ geom2d::rect<float> unitRegion(u->GetPos()-u->GetUnitSize()/2,u->GetUnitSize());
geom2d::rect<float> unitRegion(u->GetPos()-u->GetUnitSize()/2,u->GetUnitSize()); if(geom2d::overlaps(unitRegion,GetWorldMousePos())){
if(geom2d::overlaps(unitRegion,GetWorldMousePos())){ for(auto&u2:units){
for(auto&u2:units){ if(&u!=&u2){
if(u2->IsFriendly()&&u2->IsSelected()){ if(!u->IsFriendly()&&u2->IsFriendly()&&u2->IsSelected()&&u2->CanInteractWithEnemies()){
u2->SetTargetUnit(u);
} else
if(u->IsFriendly()&&u2->IsFriendly()&&u2->IsSelected()&&u2->CanInteractWithAllies()){
u2->SetTargetUnit(u); u2->SetTargetUnit(u);
} }
} }
selectedTarget=true;
break;
} }
selectedTarget=true;
break;
} }
} }
if(!selectedTarget){ if(!selectedTarget){
@ -148,7 +153,13 @@ void VirusAttack::CollisionChecking(std::shared_ptr<Unit>u,std::shared_ptr<Unit>
} }
void VirusAttack::IdentifyClosestTarget(Unit*&closestUnit,float&closestDist,std::shared_ptr<Unit>u,std::shared_ptr<Unit>u2){ void VirusAttack::IdentifyClosestTarget(Unit*&closestUnit,float&closestDist,std::shared_ptr<Unit>u,std::shared_ptr<Unit>u2){
if(u->IsFriendly()!=u2->IsFriendly()){ bool canInteract;
canInteract=
(u->IsFriendly()&&u->CanInteractWithEnemies()&&!u2->IsFriendly())||
(u->IsFriendly()&&u->CanInteractWithAllies()&&u2->IsFriendly())||
(!u->IsFriendly()&&u->CanInteractWithEnemies()&&u2->IsFriendly())||
(!u->IsFriendly()&&u->CanInteractWithAllies()&&!u2->IsFriendly());
if(canInteract){
geom2d::line<float>unitLine(u->GetPos(),u2->GetPos()); geom2d::line<float>unitLine(u->GetPos(),u2->GetPos());
if(unitLine.length()<closestDist){ if(unitLine.length()<closestDist){
closestUnit=u2.get(); closestUnit=u2.get();
@ -314,7 +325,7 @@ bool VirusAttack::OnUserUpdate(float fElapsedTime){
} }
} }
} }
u->AttemptAttack(closestUnit); u->AttemptAttack(closestUnit,units);
u->_Update(this); u->_Update(this);
} }
game.DrawPartialDecal({0,0},CONSTANT::WORLD_SIZE*CONSTANT::TILE_SIZE,IMAGES[TILE]->Decal(),{0,0},CONSTANT::WORLD_SIZE*CONSTANT::TILE_SIZE,DARK_GREEN); game.DrawPartialDecal({0,0},CONSTANT::WORLD_SIZE*CONSTANT::TILE_SIZE,IMAGES[TILE]->Decal(),{0,0},CONSTANT::WORLD_SIZE*CONSTANT::TILE_SIZE,DARK_GREEN);

Loading…
Cancel
Save