Unit Building completed.

CorrectiveAction
sigonasr2 1 year ago
parent e6b31af7de
commit fc98f34b4a
  1. 1
      olcCodeJam2023Entry/Constant.cpp
  2. 1
      olcCodeJam2023Entry/Constant.h
  3. 12
      olcCodeJam2023Entry/Resources.h
  4. 53
      olcCodeJam2023Entry/Unit.cpp
  5. 15
      olcCodeJam2023Entry/Unit.h
  6. 79
      olcCodeJam2023Entry/VirusAttack.cpp
  7. 5
      olcCodeJam2023Entry/VirusAttack.h
  8. 8
      olcCodeJam2023Entry/olcPGEX_QuickGUI.h

@ -31,3 +31,4 @@ float CONSTANT::COLLECTION_WAIT_TIME=8;
int CONSTANT::MEMORY_ALLOCATOR_COST=5;
float CONSTANT::UNIT_BUILD_TIME=10;
int CONSTANT::STARTING_RESOURCE_COUNT=5;

@ -35,4 +35,5 @@ public:
static int MEMORY_ALLOCATOR_COST;
static float UNIT_BUILD_TIME;
static int STARTING_RESOURCE_COUNT;
};

@ -1,10 +1,10 @@
#pragma once
#include "Constant.h"
struct Resources{
int health=0;
int atkSpd=0;
int moveSpd=0;
int range=0;
int procedure=0;
int health=CONSTANT::STARTING_RESOURCE_COUNT;
int atkSpd=CONSTANT::STARTING_RESOURCE_COUNT;
int moveSpd=CONSTANT::STARTING_RESOURCE_COUNT;
int range=CONSTANT::STARTING_RESOURCE_COUNT;
int procedure=CONSTANT::STARTING_RESOURCE_COUNT;
};

@ -108,6 +108,37 @@ void MemoryAllocator::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&othe
}
void MemoryAllocator::Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS,std::vector<std::unique_ptr<Unit>>&queuedUnits){
if(IsBuilding()){
buildTime-=pge->GetElapsedTime();
if(buildTime<=0){
for(int i=0;i<GetMemorySize();i++){
memory[i]=false; //Kill the unit.
}
queuedUnits.push_back(std::move(buildTransformUnit));
}
}
}
void MemoryAllocator::Draw(TileTransformedView&game,std::map<Image,std::unique_ptr<Renderable>>&IMAGES){
if(IsBuilding()){
game.GetPGE()->SetDrawTarget(img.Sprite());
game.GetPGE()->Clear(BLANK);
Renderable&targetImg=buildTransformUnit->GetImage();
game.GetPGE()->SetDrawTarget(nullptr);
game.DrawPartialRotatedDecal(GetGhostPos(),img.Decal(),0,img.Sprite()->Size()/2,{0,0},{float(img.Sprite()->width),float((buildTime/CONSTANT::UNIT_BUILD_TIME)*img.Sprite()->height)},{1,1},GetUnitColor()/3);
game.DrawPartialRotatedDecal(GetGhostPos()+vf2d{0.f,(buildTime/CONSTANT::UNIT_BUILD_TIME)*buildTransformUnit->GetImage().Sprite()->height},buildTransformUnit->GetImage().Decal(),0,buildTransformUnit->GetImage().Sprite()->Size()/2,{0.f,(buildTime/CONSTANT::UNIT_BUILD_TIME)*buildTransformUnit->GetImage().Sprite()->height},{float(buildTransformUnit->GetImage().Sprite()->width),float(buildTransformUnit->GetImage().Sprite()->height-(buildTime/CONSTANT::UNIT_BUILD_TIME)*buildTransformUnit->GetImage().Sprite()->height)},{1,1},GetUnitColor()/1.5f);
if(fmod(buildTime,1)>0.5){
game.DrawRotatedDecal(GetGhostPos(),IMAGES[SELECTION_CIRCLE]->Decal(),0,IMAGES[SELECTION_CIRCLE]->Sprite()->Size()/2,vf2d(img.Sprite()->Size())/IMAGES[SELECTION_CIRCLE]->Sprite()->Size(),{0, 202, 217});
}
} else {
game.DrawRotatedDecal(GetGhostPos(),img.Decal(),0,img.Sprite()->Size()/2,{1,1},GetUnitColor());
if(IsSelected()){
game.DrawRotatedDecal(GetGhostPos(),IMAGES[SELECTION_CIRCLE]->Decal(),0,IMAGES[SELECTION_CIRCLE]->Sprite()->Size()/2,vf2d(img.Sprite()->Size())/IMAGES[SELECTION_CIRCLE]->Sprite()->Size(),WHITE);
}
}
}
std::vector<Memory> RAMBank::resourceCost={{RANGE,0},{ATKSPD,0},{MOVESPD,0},{PROCEDURE,25},{HEALTH,16}};
RAMBank::RAMBank(PixelGameEngine*pge,vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly)
:Unit(pge,RAMBank::resourceCost,pos,41,*IMAGES[RAM_BANK],WHITE,WHITE,friendly,false
@ -140,7 +171,7 @@ void RAMBank::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
}
void RAMBank::Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS){
void RAMBank::Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS,std::vector<std::unique_ptr<Unit>>&queuedUnits){
pge->SetDrawTarget(img.Sprite());
for(int y=0;y<img.Sprite()->height;y++){
for(int x=0;x<img.Sprite()->width;x++){
@ -293,9 +324,9 @@ void Unit::DrawRangeIndicator(PixelGameEngine*pge,TileTransformedView&game,std::
}
void Unit::Draw(TileTransformedView&game,std::map<Image,std::unique_ptr<Renderable>>&IMAGES){
game.DrawRotatedDecal(ghostPos,img.Decal(),0,img.Sprite()->Size()/2,{1,1},GetUnitColor());
game.DrawRotatedDecal(GetGhostPos(),img.Decal(),0,img.Sprite()->Size()/2,{1,1},GetUnitColor());
if(IsSelected()){
game.DrawRotatedDecal(ghostPos,IMAGES[SELECTION_CIRCLE]->Decal(),0,IMAGES[SELECTION_CIRCLE]->Sprite()->Size()/2,vf2d(img.Sprite()->Size())/IMAGES[SELECTION_CIRCLE]->Sprite()->Size(),WHITE);
game.DrawRotatedDecal(GetGhostPos(),IMAGES[SELECTION_CIRCLE]->Decal(),0,IMAGES[SELECTION_CIRCLE]->Sprite()->Size()/2,vf2d(img.Sprite()->Size())/IMAGES[SELECTION_CIRCLE]->Sprite()->Size(),WHITE);
}
}
@ -457,17 +488,19 @@ void Unit::_RunAI(PixelGameEngine*pge){
RunAI(pge);
}
void Unit::_Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS,Resources&player_resources,Resources&enemy_resources){
void Unit::_Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS,Resources&player_resources,Resources&enemy_resources,std::vector<std::unique_ptr<Unit>>&queuedUnits){
if(!target.expired()){
auto ptrTarget=target.lock();
if(!InRange(ptrTarget)){
if(!InRange(ptrTarget)&&CanMove()){
SetPos(GetPos()+(ptrTarget->GetPos()-pos).norm()*GetMoveSpd()*24*pge->GetElapsedTime());
}
} else
if(targetLoc!=CONSTANT::UNSELECTED){
float dist=geom2d::line<float>(pos,targetLoc).length();
if(dist>24){
SetPos(GetPos()+(targetLoc-pos).norm()*GetMoveSpd()*24*pge->GetElapsedTime());
if(CanMove()){
SetPos(GetPos()+(targetLoc-pos).norm()*GetMoveSpd()*24*pge->GetElapsedTime());
}
} else {
if(willAttachWhenReachingDestination&&!attachTarget.expired()&&attachTarget.lock()->attachedUnit.expired()){
attachedPoint=attachTarget;
@ -515,7 +548,7 @@ void Unit::_Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SO
lineShift-=pge->GetElapsedTime();
if(lineShift<-25)lineShift+=25;
Update(pge,SOUNDS);
Update(pge,SOUNDS,queuedUnits);
}
std::vector<bool> operator <<(Unit&u,const int n){
@ -636,7 +669,7 @@ void Unit::AttemptAttack(std::weak_ptr<Unit>attacker,std::weak_ptr<Unit>unit,std
}
}
void Unit::Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS){}
void Unit::Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS,std::vector<std::unique_ptr<Unit>>&queuedUnits){}
void Unit::Attacked(std::weak_ptr<Unit>attacker){}
@ -757,3 +790,7 @@ void Unit::SetBuildUnit(float buildTime,std::unique_ptr<Unit>finalUnit){
this->buildTime=buildTime;
this->buildTransformUnit=std::move(finalUnit);
}
bool Unit::IsBuilding(){
return buildTime>0;
}

@ -34,7 +34,7 @@ public:
int GetMemorySize();
std::vector<bool>memory;
std::vector<bool>ghostMemory;
virtual void Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS);
virtual void Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS,std::vector<std::unique_ptr<Unit>>&queuedUnits);
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 DrawHud(TileTransformedView&game,std::map<Image,std::unique_ptr<Renderable>>&IMAGES);
@ -55,7 +55,7 @@ public:
bool GhostInFogOfWar();
void HideGhost();
vf2d GetGhostPos();
void _Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS,Resources&player_resources,Resources&enemy_resources);
void _Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS,Resources&player_resources,Resources&enemy_resources,std::vector<std::unique_ptr<Unit>>&queuedUnits);
bool IsMoveable();
void DrawRangeIndicator(PixelGameEngine*pge,TileTransformedView&game,std::map<Image,std::unique_ptr<Renderable>>&IMAGES);
bool CanInteractWithEnemies();
@ -75,6 +75,7 @@ public:
virtual bool ClickHandled(TileTransformedView&game,Resources&player_resources,std::vector<std::shared_ptr<Unit>>&units,std::map<Image,std::unique_ptr<Renderable>>&IMAGES); //If you return true here, then the left click does not pass back to the main Virus Attack class.
bool IsAllocator();
void SetBuildUnit(float buildTime,std::unique_ptr<Unit>finalUnit);
bool IsBuilding();
std::vector<bool>& operator <<=(const int n){
for(int i=0;i<GetMemorySize()-1;i++){
@ -115,6 +116,8 @@ protected:
bool attackFailed=false;
bool autoAcquireFriendlyTarget=true;
bool isAllocator=false;
std::unique_ptr<Unit>buildTransformUnit;
float buildTime=0;
private:
Renderable targetingLine;
Renderable attackingLine;
@ -136,8 +139,6 @@ private:
bool willAttachWhenReachingDestination=false;
std::weak_ptr<Unit>self_ptr;
float collectionTime=0;
float buildTime=0;
std::unique_ptr<Unit>buildTransformUnit;
};
struct BasicUnit:Unit{
@ -185,7 +186,9 @@ struct Corrupter:Unit{
struct MemoryAllocator:Unit{
MemoryAllocator(PixelGameEngine*pge,vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true);
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&units)override;
void Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS,std::vector<std::unique_ptr<Unit>>&queuedUnits)override;
void Draw(TileTransformedView&game,std::map<Image,std::unique_ptr<Renderable>>&IMAGES)override;
static std::vector<Memory> resourceCost;
};
@ -199,7 +202,7 @@ struct RAMBank:Unit{
QuickGUI::Manager allocatorManager;
QuickGUI::ImageButton*allocatorButton;
RAMBank(PixelGameEngine*pge,vf2d pos,std::map<Image,std::unique_ptr<Renderable>>&IMAGES,bool friendly=false);
void Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS)override;
void Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS,std::vector<std::unique_ptr<Unit>>&queuedUnits)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 OnDeath(std::map<Sound,std::unique_ptr<Audio>>&SOUNDS)override;

@ -124,54 +124,60 @@ void VirusAttack::InitializeSounds(){
bool VirusAttack::UnitCreationClickHandled(){
if(leftShifterButton->bPressed){
for(auto&u:units){
if(u->IsSelected()&&u->IsAllocator()&&CanAfford(LeftShifter::resourceCost)){
if(u->IsSelected()&&u->IsAllocator()&&CanAfford(player_resources,LeftShifter::resourceCost)){
std::unique_ptr<LeftShifter>buildUnit=std::make_unique<LeftShifter>(this,u->GetPos(),IMAGES,u->IsFriendly());
u->SetBuildUnit(CONSTANT::UNIT_BUILD_TIME,std::move(buildUnit));
ExpendResources(player_resources,LeftShifter::resourceCost);
}
}
return true;
}
if(rightShifterButton->bPressed){
for(auto&u:units){
if(u->IsSelected()&&u->IsAllocator()&&CanAfford(RightShifter::resourceCost)){
if(u->IsSelected()&&u->IsAllocator()&&CanAfford(player_resources,RightShifter::resourceCost)){
std::unique_ptr<RightShifter>buildUnit=std::make_unique<RightShifter>(this,u->GetPos(),IMAGES,u->IsFriendly());
u->SetBuildUnit(CONSTANT::UNIT_BUILD_TIME,std::move(buildUnit));
ExpendResources(player_resources,RightShifter::resourceCost);
}
}
return true;
}
if(bitRestorerButton->bPressed){
for(auto&u:units){
if(u->IsSelected()&&u->IsAllocator()&&CanAfford(BitRestorer::resourceCost)){
if(u->IsSelected()&&u->IsAllocator()&&CanAfford(player_resources,BitRestorer::resourceCost)){
std::unique_ptr<BitRestorer>buildUnit=std::make_unique<BitRestorer>(this,u->GetPos(),IMAGES,u->IsFriendly());
u->SetBuildUnit(CONSTANT::UNIT_BUILD_TIME,std::move(buildUnit));
ExpendResources(player_resources,BitRestorer::resourceCost);
}
}
return true;
}
if(memorySwapperButton->bPressed){
for(auto&u:units){
if(u->IsSelected()&&u->IsAllocator()&&CanAfford(MemorySwapper::resourceCost)){
if(u->IsSelected()&&u->IsAllocator()&&CanAfford(player_resources,MemorySwapper::resourceCost)){
std::unique_ptr<MemorySwapper>buildUnit=std::make_unique<MemorySwapper>(this,u->GetPos(),IMAGES,u->IsFriendly());
u->SetBuildUnit(CONSTANT::UNIT_BUILD_TIME,std::move(buildUnit));
ExpendResources(player_resources,MemorySwapper::resourceCost);
}
}
return true;
}
if(corrupterButton->bPressed){
for(auto&u:units){
if(u->IsSelected()&&u->IsAllocator()&&CanAfford(Corrupter::resourceCost)){
if(u->IsSelected()&&u->IsAllocator()&&CanAfford(player_resources,Corrupter::resourceCost)){
std::unique_ptr<Corrupter>buildUnit=std::make_unique<Corrupter>(this,u->GetPos(),IMAGES,u->IsFriendly());
u->SetBuildUnit(CONSTANT::UNIT_BUILD_TIME,std::move(buildUnit));
ExpendResources(player_resources,Corrupter::resourceCost);
}
}
return true;
}
if(platformButton->bPressed){
for(auto&u:units){
if(u->IsSelected()&&u->IsAllocator()&&CanAfford(MemoryAllocator::resourceCost)){
if(u->IsSelected()&&u->IsAllocator()&&CanAfford(player_resources,MemoryAllocator::resourceCost)){
std::unique_ptr<MemoryAllocator>buildUnit=std::make_unique<MemoryAllocator>(this,u->GetPos(),IMAGES,u->IsFriendly());
u->SetBuildUnit(CONSTANT::UNIT_BUILD_TIME,std::move(buildUnit));
ExpendResources(player_resources,MemoryAllocator::resourceCost);
}
}
return true;
@ -179,6 +185,17 @@ bool VirusAttack::UnitCreationClickHandled(){
return false;
};
void VirusAttack::UpdateUnitCreationListGUI(bool allocatorSelected){
unitCreationList.DisplayAllControls(allocatorSelected);
leftShifterButton->Enable(CanAfford(player_resources,LeftShifter::resourceCost));
rightShifterButton->Enable(CanAfford(player_resources,RightShifter::resourceCost));
bitRestorerButton->Enable(CanAfford(player_resources,BitRestorer::resourceCost));
memorySwapperButton->Enable(CanAfford(player_resources,MemorySwapper::resourceCost));
corrupterButton->Enable(CanAfford(player_resources,Corrupter::resourceCost));
platformButton->Enable(CanAfford(player_resources,MemoryAllocator::resourceCost));
unitCreationList.Update(this);
}
void VirusAttack::HandleDraggingSelection(){
auto NotClickingOnMinimap=[&](){return !(GetMouseX()>=ScreenWidth()-64&&GetMouseY()>=ScreenHeight()-64);};
bool allocatorSelected=false;
@ -188,14 +205,7 @@ void VirusAttack::HandleDraggingSelection(){
allocatorSelected=true;
}
}
unitCreationList.DisplayAllControls(allocatorSelected);
leftShifterButton->Enable(CanAfford(LeftShifter::resourceCost));
rightShifterButton->Enable(CanAfford(RightShifter::resourceCost));
bitRestorerButton->Enable(CanAfford(BitRestorer::resourceCost));
memorySwapperButton->Enable(CanAfford(MemorySwapper::resourceCost));
corrupterButton->Enable(CanAfford(Corrupter::resourceCost));
platformButton->Enable(CanAfford(MemoryAllocator::resourceCost));
unitCreationList.Update(this);
UpdateUnitCreationListGUI(allocatorSelected);
if(GetMouse(0).bPressed){
if(NotClickingOnMinimap()){
for(auto&u:units){
@ -482,7 +492,7 @@ bool VirusAttack::OnUserUpdate(float fElapsedTime){
}
}
u->AttemptAttack(u,closestUnit,units,debuffIcons,IMAGES);
u->_Update(this,SOUNDS,player_resources,enemy_resources);
u->_Update(this,SOUNDS,player_resources,enemy_resources,queuedUnits);
}
std::erase_if(units,[&](std::shared_ptr<Unit>u){
@ -495,6 +505,11 @@ bool VirusAttack::OnUserUpdate(float fElapsedTime){
}
});
for(auto&queuedUnit:queuedUnits){
units.push_back(std::move(queuedUnit));
}
queuedUnits.clear();
game.DrawPartialDecal({0,0},CONSTANT::WORLD_SIZE*CONSTANT::TILE_SIZE,IMAGES[TILE]->Decal(),{0,0},CONSTANT::WORLD_SIZE*CONSTANT::TILE_SIZE,DARK_GREEN);
@ -575,29 +590,51 @@ void VirusAttack::RenderFogOfWar(){
}
}
bool VirusAttack::CanAfford(std::vector<Memory>&unitCosts){
bool VirusAttack::CanAfford(Resources&resources,std::vector<Memory>&unitCosts){
for(Memory&mem:unitCosts){
switch(mem.type){
case HEALTH:{
if(player_resources.health<mem.size)return false;
if(resources.health<mem.size)return false;
}break;
case ATKSPD:{
if(player_resources.atkSpd<mem.size)return false;
if(resources.atkSpd<mem.size)return false;
}break;
case MOVESPD:{
if(player_resources.moveSpd<mem.size)return false;
if(resources.moveSpd<mem.size)return false;
}break;
case RANGE:{
if(player_resources.range<mem.size)return false;
if(resources.range<mem.size)return false;
}break;
case PROCEDURE:{
if(player_resources.procedure<mem.size)return false;
if(resources.procedure<mem.size)return false;
}break;
}
}
return true;
}
void VirusAttack::ExpendResources(Resources&resources,std::vector<Memory>&unitCosts){
for(Memory&mem:unitCosts){
switch(mem.type){
case HEALTH:{
resources.health-=mem.size;
}break;
case ATKSPD:{
resources.atkSpd-=mem.size;
}break;
case MOVESPD:{
resources.moveSpd-=mem.size;
}break;
case RANGE:{
resources.range-=mem.size;
}break;
case PROCEDURE:{
resources.procedure-=mem.size;
}break;
}
}
}
int main()
{
VirusAttack app;

@ -21,6 +21,7 @@ struct Letter{
class VirusAttack : public olc::PixelGameEngine
{
private:
std::vector<std::unique_ptr<Unit>>queuedUnits;
std::vector<std::shared_ptr<Unit>>units;
std::vector<std::shared_ptr<CollectionPoint>>collectionPoints;
std::vector<std::unique_ptr<DeathAnimation>>deathAnimations;
@ -67,7 +68,9 @@ private:
void DrawResourceBar();
bool UnitCreationClickHandled();
void InitializeUnitCreationGUI();
bool CanAfford(std::vector<Memory>&unitCosts);
bool CanAfford(Resources&resources,std::vector<Memory>&unitCosts);
void ExpendResources(Resources&resources,std::vector<Memory>&unitCosts);
void UpdateUnitCreationListGUI(bool allocatorSelected);
public:
VirusAttack();

@ -693,11 +693,11 @@ namespace olc::QuickGUI
void Button::Update(TileTransformedView&pge)
{
bPressed = false;
bReleased = false;
if (m_state == State::Disabled || !bVisible)
return;
bPressed = false;
bReleased = false;
float fElapsedTime = pge.GetPGE()->GetElapsedTime();
olc::vf2d vMouse = pge.ScreenToWorld(pge.GetPGE()->GetMousePos());
@ -735,11 +735,11 @@ namespace olc::QuickGUI
void Button::Update(PixelGameEngine*pge)
{
bPressed = false;
bReleased = false;
if (m_state == State::Disabled || !bVisible)
return;
bPressed = false;
bReleased = false;
float fElapsedTime = pge->GetElapsedTime();
olc::vf2d vMouse = pge->GetMousePos();

Loading…
Cancel
Save