Add in sound effects.

master
sigonasr2 1 year ago
parent bb33e8a8cd
commit 10bbb07894
  1. 2
      olcCodeJam2023Entry/GameFlags.h
  2. 88
      olcCodeJam2023Entry/Scenario.cpp
  3. 1
      olcCodeJam2023Entry/Scenario.h
  4. 12
      olcCodeJam2023Entry/Sound.h
  5. 2
      olcCodeJam2023Entry/Textbox.cpp
  6. 87
      olcCodeJam2023Entry/Unit.cpp
  7. 45
      olcCodeJam2023Entry/Unit.h
  8. 72
      olcCodeJam2023Entry/VirusAttack.cpp
  9. BIN
      olcCodeJam2023Entry/pge.data
  10. 2
      olcCodeJam2023Entry/pge.js
  11. BIN
      olcCodeJam2023Entry/pge.wasm

@ -4,6 +4,6 @@ struct GameFlags{
bool unitMetersGreyedOut=true;//If true, all but health meters show up as dark grey.
bool playerInControl=false;
bool limitedBuildOptions=false;
bool guideEnabled=true;
bool guideEnabled=false;
bool flashMemoryBar=false;
};

@ -160,18 +160,20 @@ Stage2::Stage2(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_
void Stage2::Start(){
flags.playerInControl=false;
flags.limitedBuildOptions=true;
flags.flashMemoryBar=false;
SetCameraTarget({7*24,10*24},true);
nextLevel=LevelName::STAGE3;
};
void Stage2::Update(){
switch(state){
case 0:{
SetCameraTarget({7*24,10*24},true);
DisplayBox("You took care of that sector flawlessly Hacker, this next one needs a bit more hand-holding.");
if(box.bPressed){
state=1;
}
}break;
case 1:{
SetObjective("Create a RAM bank.");
DisplayBox("We have analyzed the data from the RAM bank and can now create one. Go ahead and select the Platform here and construct one.");
if(box.bPressed){
state=2;
@ -184,6 +186,7 @@ void Stage2::Update(){
if(u->IsRAMBank()&&u->IsFriendly()){
state=3;
flags.playerInControl=false;
SetObjective("");
break;
}
}
@ -209,6 +212,7 @@ void Stage2::Update(){
}
}break;
case 6:{
SetObjective("Build a Memory Allocator.");
DisplayBox("To allocate 5 bits, select the RAM bank and click the Memory Allocator button.\n\nGive it a try now.");
if(box.bPressed){
state=7;
@ -221,11 +225,13 @@ void Stage2::Update(){
if(u->IsAllocator()&&u->IsFriendly()){
state=8;
flags.playerInControl=false;
SetObjective("");
break;
}
}
}break;
case 8:{
SetObjective("Build a Left or Right Bit Shifter.");
DisplayBox("Now select the memory allocator and let's make a Shifter unit.");
if(box.bPressed){
state=9;
@ -238,6 +244,7 @@ void Stage2::Update(){
if(!u->IsAllocator()&&!u->IsRAMBank()&&u->IsFriendly()){
state=10;
flags.playerInControl=false;
SetObjective("");
break;
}
}
@ -278,18 +285,95 @@ bool Stage2::MissionCompleted(){
Stage3::Stage3(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage3::Start(){
flags.playerInControl=false;
flags.unitMetersGreyedOut=true;
flags.guideEnabled=false;
SetCameraTarget({3*24,6*24},true);
oopsTimer=0.3;
nextLevel=LevelName::STAGE4;
};
void Stage3::Update(){
switch(state){
case 0:{
DisplayBox("I haven't touched on what the other meters on your units are, but they are important!");
if(box.bPressed){
SOUNDS[Sound::SWITCH]->PlayCentered();
flags.unitMetersGreyedOut=false;
state=1;
}
}break;
case 1:{
DisplayBox("The Blue bits indicates movement capabilities of a unit.");
if(box.bPressed){
state=2;
}
}break;
case 2:{
DisplayBox("The Green bits indicates the range of a unit.");
if(box.bPressed){
state=3;
}
}break;
case 3:{
DisplayBox("The Red bits are the attack speed bits.");
if(box.bPressed){
state=4;
}
}break;
case 4:{
DisplayBox("And Purple are the Procedure bits. Without these, your unit will fail to recall how to function.");
if(box.bPressed){
state=5;
}
}break;
case 5:{
DisplayBox("As units attack each other, their bits are going to get shuffled around, impeding their ability to perform.");
if(box.bPressed){
state=6;
}
}break;
case 6:{
DisplayBox("Your immediate goal is to always take out the Yellow bits but sometimes taking out other bits is important too.");
if(box.bPressed){
SOUNDS[Sound::SWITCH]->PlayCentered();
flags.guideEnabled=true;
state=7;
}
}break;
case 7:{
DisplayBox("I'll leave a guide by the map in case your memory betrays you.");
if(box.bPressed){
state=8;
}
}break;
case 8:{
SetObjective("Defeat all units");
DisplayBox("You now have access to more units as well. Do check them out!");
if(box.bPressed){
SetObjective("Defeat all units (Oops)");
state=9;
}
}break;
case 9:{
oopsTimer=std::max(0.f,oopsTimer-game.GetPGE()->GetElapsedTime());
if(oopsTimer==0){
SetObjective("Defeat all enemy units.");
state=10;
flags.playerInControl=true;
}
}break;
case 10:{
}break;
}
};
bool Stage3::MissionCompleted(){
for(auto&u:units){
if(!u->IsFriendly()){
return false;
}
}
return true;
}
Stage4::Stage4(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags)
:Scenario(units,IMAGES,SOUNDS,objective,game,flags){}
void Stage4::Start(){

@ -59,6 +59,7 @@ protected:
};
class Stage3:public Scenario{
public:
float oopsTimer=0.3;
Stage3(std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::string&objective,TileTransformedView&game,GameFlags&flags);
protected:
void Start();

@ -10,5 +10,17 @@ namespace Sound{
VOICEOVER,
PING,
ALARM,
SWITCH,
HIT1,
HIT2,
HIT3,
BUTTONSELECT,
SMALLBUILD,
BIGBUILD,
HEAL,
REFRESHER,
TURRET,
MEMORY_GUARD,
SPAWN,
};
}

@ -199,7 +199,7 @@ void Textbox::Draw(PixelGameEngine*pge,Resources&resources,std::vector<std::uniq
totalCost+=util::GetProcedureCost(resourceCost);
index++;
}
std::string text="Size: "+std::to_string(totalCost)+" bytes";
std::string text="Size: "+std::to_string(totalCost)+" bits";
vi2d size=pge->GetTextSizeProp(text);
drawcol=WHITE;
if(totalCost+totalUsedMemory>memoryLimit){

@ -8,14 +8,23 @@
Unit::~Unit(){};
void Unit::RandomHit(int chance,std::vector<std::unique_ptr<Audio>>&SOUNDS){
switch(rand()%chance){
case 0:{SOUNDS[Sound::HIT1]->Play(GetPos(),1,0.6);}break;
case 1:{SOUNDS[Sound::HIT2]->Play(GetPos(),1,0.6);}break;
case 2:{SOUNDS[Sound::HIT3]->Play(GetPos(),1,0.6);}break;
}
}
std::string LeftShifter::unitName="Left Shifter";
std::string LeftShifter::unitDescription="Shifts target memory 1 bit to the left.";
std::vector<Memory> LeftShifter::resourceCost={{RANGE,2},{ATKSPD,2},{MOVESPD,6},{PROCEDURE,1},{HEALTH,4}};
LeftShifter::LeftShifter(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool friendly,bool moveable)
:Unit(pge,LeftShifter::resourceCost,pos,12,*IMAGES[LEFT_SHIFTER],CONSTANT::ATTACKER_TARGET_COL,CONSTANT::ATTACKER_ATTACK_COL,friendly,moveable){}
void LeftShifter::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
void LeftShifter::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
victim<<=1;
RandomHit(6,SOUNDS);
}
std::string RightShifter::unitName="Right Shifter";
@ -24,8 +33,9 @@ std::vector<Memory> RightShifter::resourceCost={{HEALTH,4},{RANGE,2},{ATKSPD,2},
RightShifter::RightShifter(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool friendly,bool moveable)
:Unit(pge,RightShifter::resourceCost,pos,12,*IMAGES[RIGHT_SHIFTER],CONSTANT::ATTACKER_TARGET_COL,CONSTANT::ATTACKER_ATTACK_COL,friendly,moveable){}
void RightShifter::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
void RightShifter::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
victim>>=1;
RandomHit(6,SOUNDS);
}
std::string BitRestorer::unitName="Bit Restorer";
@ -34,7 +44,7 @@ std::vector<Memory> BitRestorer::resourceCost={{PROCEDURE,6},{RANGE,1},{ATKSPD,1
BitRestorer::BitRestorer(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool friendly,bool moveable)
:Unit(pge,BitRestorer::resourceCost,pos,12,*IMAGES[BIT_RESTORER],CONSTANT::HEALER_TARGET_COL,CONSTANT::HEALER_ATTACK_COL,friendly,moveable,true,false){}
void BitRestorer::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
void BitRestorer::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
std::vector<int>emptyMemoryPositions;
for(int i=0;i<victim.GetMemorySize();i++){
if(!victim.memory[i]){
@ -44,14 +54,15 @@ void BitRestorer::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUni
if(emptyMemoryPositions.size()==0){
//First see if we can find another damaged target, if we can, then we try healing them. Otherwise we exit.
appliedTarget.reset();
AttemptToHealOtherAllies(otherUnits);
AttemptToHealOtherAllies(otherUnits,SOUNDS);
return;
}
int randomBit=emptyMemoryPositions[rand()%emptyMemoryPositions.size()];
victim.memory[randomBit]=true;
SOUNDS[Sound::HEAL]->Play(GetPos(),1,0.6);
}
void BitRestorer::AttemptToHealOtherAllies(std::vector<std::shared_ptr<Unit>>&otherUnits){
void BitRestorer::AttemptToHealOtherAllies(std::vector<std::shared_ptr<Unit>>&otherUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS){
std::vector<int>emptyMemoryPositions;
for(auto&u:otherUnits){
if(u.get()!=this&&u->IsFriendly()&&InRange(u)){
@ -64,6 +75,7 @@ void BitRestorer::AttemptToHealOtherAllies(std::vector<std::shared_ptr<Unit>>&ot
int randomBit=emptyMemoryPositions[rand()%emptyMemoryPositions.size()];
u->memory[randomBit]=true;
appliedTarget=u;
SOUNDS[Sound::HEAL]->Play(GetPos(),1,0.6);
return;
}
}
@ -78,7 +90,7 @@ MemorySwapper::MemorySwapper(PixelGameEngine*pge,vf2d pos,std::vector<std::uniqu
autoAcquireFriendlyTarget=false;
}
void MemorySwapper::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
void MemorySwapper::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
std::vector<bool>oldMemory=victim.memory;
for(int i=0;i<oldMemory.size();i++){
victim.memory[i]=oldMemory[oldMemory.size()-i-1];
@ -112,6 +124,7 @@ void MemorySwapper::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherU
if(victim.atkSpd.index==9999999)victim.atkSpd.index=0;
if(victim.moveSpd.index==9999999)victim.moveSpd.index=0;
if(victim.procedure.index==9999999)victim.procedure.index=0;
RandomHit(4,SOUNDS);
}
std::string Corrupter::unitName="Corrupter";
@ -120,9 +133,12 @@ std::vector<Memory> Corrupter::resourceCost={{ATKSPD,3},{RANGE,1},{PROCEDURE,8},
Corrupter::Corrupter(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool friendly,bool moveable)
:Unit(pge,Corrupter::resourceCost,pos,12,*IMAGES[CORRUPTER],CONSTANT::ATTACKER_TARGET_COL,CONSTANT::ATTACKER_ATTACK_COL,friendly,moveable){}
void Corrupter::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
void Corrupter::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
//Chooses a bit at random and corrupts it.
int randomBit=rand()%victim.memory.size();
if(victim.memory[randomBit]){
RandomHit(5,SOUNDS);
}
victim.memory[randomBit]=false;
}
@ -134,7 +150,7 @@ MemoryAllocator::MemoryAllocator(PixelGameEngine*pge,vf2d pos,std::vector<std::u
isAllocator=true;
}
void MemoryAllocator::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
void MemoryAllocator::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
}
@ -147,6 +163,7 @@ void MemoryAllocator::Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Aud
for(int i=0;i<GetMemorySize();i++){
memory[i]=false; //Kill the unit.
}
SOUNDS[Sound::SPAWN]->Play(GetPos());
queuedUnits.push_back(std::move(buildTransformUnit));
}
}
@ -194,7 +211,7 @@ RAMBank::RAMBank(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Render
isRAMBank=true;
}
void RAMBank::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
void RAMBank::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
}
@ -293,7 +310,7 @@ _Platform::_Platform(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Re
isPlatform=true;
}
void _Platform::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){};
void _Platform::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits ,std::vector<std::unique_ptr<Audio>>&SOUNDS){};
void _Platform::Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::vector<std::shared_ptr<Unit>>&queuedUnits){
if(IsBuilding()){
@ -304,6 +321,7 @@ void _Platform::Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&S
for(int i=0;i<GetMemorySize();i++){
memory[i]=false; //Kill the unit.
}
SOUNDS[Sound::SPAWN]->Play(GetPos());
queuedUnits.push_back(std::move(buildTransformUnit));
}
}
@ -335,7 +353,7 @@ Refresher::Refresher(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Re
:Unit(pge,Refresher::resourceCost,pos,24,*IMAGES[REFRESHER],CONSTANT::ATTACKER_TARGET_COL,CONSTANT::ATTACKER_ATTACK_COL,friendly,false
,true,false){}
void Refresher::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
void Refresher::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
target.reset(); //Doesn't acquire a target.
for(auto&u:otherUnits){
if(IsFriendly()==u->IsFriendly()&&InRange(u.get())){
@ -352,6 +370,15 @@ void Refresher::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits
}
}
}
void Refresher::OnDeath(std::vector<std::unique_ptr<Audio>>&SOUNDS){
SOUNDS[Sound::REFRESHER]->Stop(soundHandle);
};
void Refresher::Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::vector<std::shared_ptr<Unit>>&queuedUnits){
if(!soundStarted){
soundStarted=true;
soundHandle=SOUNDS[Sound::REFRESHER]->Play(GetPos(),1,1,true);
}
};
std::string Turret::unitName="Turret";
std::string Turret::unitDescription="Automatically targets attack and movement speed memory ranges before others.";
@ -359,7 +386,7 @@ std::vector<Memory> Turret::resourceCost={{ATKSPD,4},{RANGE,5},{HEALTH,6},{PROCE
Turret::Turret(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool friendly,bool moveable)
:Unit(pge,Turret::resourceCost,pos,24,*IMAGES[TURRET],CONSTANT::ATTACKER_TARGET_COL,CONSTANT::ATTACKER_ATTACK_COL,friendly,false){}
void Turret::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
void Turret::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
if(victim.GetMoveSpd()>0){
for(int i=0;i<victim.moveSpd.size;i++){
if(victim.memory[victim.moveSpd.index+i]){
@ -387,6 +414,15 @@ void Turret::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
attempts++;
}
}
void Turret::OnDeath(std::vector<std::unique_ptr<Audio>>&SOUNDS){
SOUNDS[Sound::TURRET]->Stop(soundHandle);
};
void Turret::Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::vector<std::shared_ptr<Unit>>&queuedUnits){
if(!soundStarted){
soundStarted=true;
soundHandle=SOUNDS[Sound::TURRET]->Play(GetPos(),1,1,true);
}
};
std::string MemoryGuard::unitName="Memory Guard";
std::string MemoryGuard::unitDescription="Reduces the chance of bit modification for all surrounding units by 30%";
@ -395,7 +431,7 @@ MemoryGuard::MemoryGuard(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_pt
:Unit(pge,MemoryGuard::resourceCost,pos,24,*IMAGES[MEMORY_GUARD],CONSTANT::ATTACKER_TARGET_COL,CONSTANT::ATTACKER_ATTACK_COL,friendly,false
,true,false){}
void MemoryGuard::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
void MemoryGuard::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
target.reset(); //Doesn't acquire a target.
for(auto&u:otherUnits){
if(IsFriendly()==u->IsFriendly()&&InRange(u.get())){
@ -403,6 +439,15 @@ void MemoryGuard::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUni
}
}
}
void MemoryGuard::OnDeath(std::vector<std::unique_ptr<Audio>>&SOUNDS){
SOUNDS[Sound::MEMORY_GUARD]->Stop(soundHandle);
};
void MemoryGuard::Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::vector<std::shared_ptr<Unit>>&queuedUnits){
if(!soundStarted){
soundStarted=true;
soundHandle=SOUNDS[Sound::MEMORY_GUARD]->Play(GetPos(),1,1,true);
}
};
Unit::Unit(PixelGameEngine*pge,std::vector<Memory>memory,vf2d pos,float radius,Renderable&img,Pixel targetLineColor,Pixel attackingLineColor,bool friendly,bool moveable,bool friendlyInteractable,bool enemyInteractable)
:pos(pos),radius(radius),ghostPos({-999999,-999999}),img(img),targetLineCol(targetLineColor),attackingLineCol(attackingLineColor),friendly(friendly),moveable(moveable),friendlyInteractable(friendlyInteractable),enemyInteractable(enemyInteractable){
@ -791,7 +836,7 @@ void Unit::SetPos(vf2d newPos){
pos=newPos;
}
void Unit::AttemptAttack(std::weak_ptr<Unit>attacker,std::weak_ptr<Unit>unit,std::vector<std::shared_ptr<Unit>>&otherUnits,std::vector<DebuffIcon>&debuffIcons,std::vector<std::unique_ptr<Renderable>>&IMAGES){
void Unit::AttemptAttack(std::weak_ptr<Unit>attacker,std::weak_ptr<Unit>unit,std::vector<std::shared_ptr<Unit>>&otherUnits,std::vector<DebuffIcon>&debuffIcons,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS){
if(reloadTimer>0)return;
std::weak_ptr<Unit>finalTarget;
if(!unit.expired()){
@ -810,7 +855,7 @@ void Unit::AttemptAttack(std::weak_ptr<Unit>attacker,std::weak_ptr<Unit>unit,std
bool hadMoveSpd=finalTarget.lock()->GetMoveSpd()>0;
bool hadRange=finalTarget.lock()->GetRange()>0;
bool hadProcedure=finalTarget.lock()->GetProcedure()>0;
_Attack(attacker,finalTarget,otherUnits); //Call the parent function first, followed by the child.
_Attack(attacker,finalTarget,otherUnits,SOUNDS); //Call the parent function first, followed by the child.
if(hadAtkSpd&&finalTarget.lock()->GetAtkSpd()==0){
debuffIcons.emplace_back(IMAGES[RLD_ICON].get(),IMAGES[RED_X].get(),finalTarget.lock()->GetPos()-vf2d{util::random(12)-6,4});
}
@ -838,12 +883,12 @@ void Unit::_Attacked(std::weak_ptr<Unit>attacker){
}
}
void Unit::_Attack(std::weak_ptr<Unit>attacker,std::weak_ptr<Unit>finalTarget,std::vector<std::shared_ptr<Unit>>&otherUnits){
void Unit::_Attack(std::weak_ptr<Unit>attacker,std::weak_ptr<Unit>finalTarget,std::vector<std::shared_ptr<Unit>>&otherUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS){
if(GetProcedure()>0&&GetAtkSpd()>0){
attackFailed=false;
float procChance=float(GetProcedure())/procedure.size;
if(util::random(1)>=1-procChance){
Attack(*finalTarget.lock(),otherUnits);
Attack(*finalTarget.lock(),otherUnits,SOUNDS);
finalTarget.lock()->_Attacked(attacker);
reloadTimer=1.f/(GetAtkSpd()/2.f);
if(GetCurrentTarget().expired()&&!IsFriendly()){
@ -944,9 +989,15 @@ bool Unit::IsAllocator(){
return isAllocator&&attachedPoint.expired()&&buildTime<=0;
}
void Unit::SetBuildUnit(float buildTime,std::shared_ptr<Unit>finalUnit){
void Unit::SetBuildUnit(float buildTime,std::shared_ptr<Unit>finalUnit,std::vector<std::unique_ptr<Audio>>&SOUNDS){
this->buildTime=buildTime;
this->buildTransformUnit=std::move(finalUnit);
if(this->IsAllocator()){
SOUNDS[Sound::SMALLBUILD]->Play(GetPos());
} else
if(this->IsPlatform()){
SOUNDS[Sound::BIGBUILD]->Play(GetPos());
}
}
bool Unit::IsBuilding(){

@ -46,7 +46,7 @@ public:
std::vector<bool>ghostMemory;
std::vector<bool>savedMemory;
virtual void Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::vector<std::shared_ptr<Unit>>&queuedUnits);
virtual void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)=0;
virtual void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS)=0;
virtual void Draw(TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES);
virtual void DrawHud(TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES);
void _DrawHud(TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool unitMetersGreyedOut);
@ -61,7 +61,7 @@ public:
void SetTargetUnit(std::weak_ptr<Unit>target);
void SetTargetLocation(vf2d targetLoc);
void SetPos(vf2d newPos);
void AttemptAttack(std::weak_ptr<Unit>attacker,std::weak_ptr<Unit>unit,std::vector<std::shared_ptr<Unit>>&otherUnits,std::vector<DebuffIcon>&debuffIcons,std::vector<std::unique_ptr<Renderable>>&IMAGES);
void AttemptAttack(std::weak_ptr<Unit>attacker,std::weak_ptr<Unit>unit,std::vector<std::shared_ptr<Unit>>&otherUnits,std::vector<DebuffIcon>&debuffIcons,std::vector<std::unique_ptr<Renderable>>&IMAGES,std::vector<std::unique_ptr<Audio>>&SOUNDS);
bool InFogOfWar();
bool GhostInFogOfWar();
void HideGhost();
@ -85,7 +85,7 @@ public:
virtual void UpdateGUIState(TileTransformedView&game,Resources&player_resources,Textbox&displayBox,bool&hovered,int totalUsedMemory,int availableMemory);
virtual bool ClickHandled(TileTransformedView&game,Resources&player_resources,std::vector<std::shared_ptr<Unit>>&units,std::vector<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::shared_ptr<Unit>finalUnit);
void SetBuildUnit(float buildTime,std::shared_ptr<Unit>finalUnit,std::vector<std::unique_ptr<Audio>>&SOUNDS);
bool IsBuilding();
void SetGuardTime(float time);
bool IsGuarded();
@ -93,6 +93,7 @@ public:
bool IsPlatform();
bool IsAttached();
bool IsRAMBank();
void RandomHit(int chance,std::vector<std::unique_ptr<Audio>>&SOUNDS); //3 of chance odds of making a sound.
Unit*GetBuildUnit();
Marker health={};
Marker range={};
@ -142,7 +143,7 @@ private:
int GetBits(Marker&m);
bool selected=false;
bool dead=false;
void _Attack(std::weak_ptr<Unit>attacker,std::weak_ptr<Unit>finalTarget,std::vector<std::shared_ptr<Unit>>&otherUnits);
void _Attack(std::weak_ptr<Unit>attacker,std::weak_ptr<Unit>finalTarget,std::vector<std::shared_ptr<Unit>>&otherUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS);
bool moveable=true;
bool friendlyInteractable=false;
bool enemyInteractable=true;
@ -159,7 +160,7 @@ private:
struct LeftShifter:Unit{
LeftShifter(PixelGameEngine*pge,vf2d pos,std::vector<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>>&otherUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
static std::vector<Memory> resourceCost;
static std::string unitName;
static std::string unitDescription;
@ -167,7 +168,7 @@ struct LeftShifter:Unit{
struct RightShifter:Unit{
RightShifter(PixelGameEngine*pge,vf2d pos,std::vector<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>>&otherUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
static std::vector<Memory> resourceCost;
static std::string unitName;
static std::string unitDescription;
@ -175,8 +176,8 @@ struct RightShifter:Unit{
struct BitRestorer:Unit{
BitRestorer(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true);
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
void AttemptToHealOtherAllies(std::vector<std::shared_ptr<Unit>>&otherUnits);
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
void AttemptToHealOtherAllies(std::vector<std::shared_ptr<Unit>>&otherUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS);
static std::vector<Memory> resourceCost;
static std::string unitName;
static std::string unitDescription;
@ -184,7 +185,7 @@ struct BitRestorer:Unit{
struct MemorySwapper:Unit{
MemorySwapper(PixelGameEngine*pge,vf2d pos,std::vector<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>>&otherUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
static std::vector<Memory> resourceCost;
static std::string unitName;
static std::string unitDescription;
@ -192,7 +193,7 @@ struct MemorySwapper:Unit{
struct Corrupter:Unit{
Corrupter(PixelGameEngine*pge,vf2d pos,std::vector<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>>&otherUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
static std::vector<Memory> resourceCost;
static std::string unitName;
static std::string unitDescription;
@ -200,7 +201,7 @@ struct Corrupter:Unit{
struct MemoryAllocator:Unit{
MemoryAllocator(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true);
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&units)override;
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
void Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::vector<std::shared_ptr<Unit>>&queuedUnits)override;
void Draw(TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES)override;
static std::vector<Memory> resourceCost;
@ -219,7 +220,7 @@ struct RAMBank:Unit{
QuickGUI::ImageButton*allocatorButton;
RAMBank(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool friendly=false);
void Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::vector<std::shared_ptr<Unit>>&queuedUnits)override;
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
void Draw(TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES)override;
void OnDeath(std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
bool ClickHandled(TileTransformedView&game,Resources&player_resources,std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES)override;
@ -232,7 +233,7 @@ struct RAMBank:Unit{
struct _Platform:Unit{
_Platform(PixelGameEngine*pge,vf2d pos,std::vector<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>>&otherUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
void Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::vector<std::shared_ptr<Unit>>&queuedUnits)override;
void Draw(TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES)override;
static std::vector<Memory> resourceCost;
@ -241,24 +242,36 @@ struct _Platform:Unit{
};
struct MemoryGuard:Unit{
bool soundStarted=false;
int soundHandle=-1;
MemoryGuard(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true);
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
void Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::vector<std::shared_ptr<Unit>>&queuedUnits)override;
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
void OnDeath(std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
static std::vector<Memory> resourceCost;
static std::string unitName;
static std::string unitDescription;
};
struct Refresher:Unit{
bool soundStarted=false;
int soundHandle=-1;
Refresher(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true);
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
void Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::vector<std::shared_ptr<Unit>>&queuedUnits)override;
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
void OnDeath(std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
static std::vector<Memory> resourceCost;
static std::string unitName;
static std::string unitDescription;
};
struct Turret:Unit{
bool soundStarted=false;
int soundHandle=-1;
Turret(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool friendly=false,bool moveable=true);
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
void Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::vector<std::shared_ptr<Unit>>&queuedUnits)override;
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
void OnDeath(std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
static std::vector<Memory> resourceCost;
static std::string unitName;
static std::string unitDescription;

@ -145,6 +145,41 @@ void VirusAttack::InitializeLevelData(){
}
}
#pragma endregion
#pragma region Stage 3
{
//Stage 3 data.
LevelName stage=STAGE3;
levelData[stage].name=stage;
levelData[stage].cameraStart={96,96};
levelData[stage].worldZoom={1,1};
levelData[stage].size={30,30};
levelData[stage].levelColor=DARK_GREEN;
levelData[stage].bgm=Sound::GRAVITY;
levelData[stage].scenarioIndex=int(stage);
levelData[stage].availableMemory=240;
levelData[stage].player_starting_resources={100,40,60,40,100};
levelData[stage].enemy_starting_resources={0,0,0,0,0};
{
std::vector<UnitData>&units=levelData[stage].unitPlacement;
std::vector<CPData>&collectionPoints=levelData[stage].cpPlacement;
units.push_back({UnitType::RAMBank,vf2d{3*24,6*24},true});
for(int i=0;i<4;i++){
units.push_back({UnitType::RightShifter,vf2d{3*24,8*24},true});
}
units.push_back({UnitType::LeftShifter,vf2d{3*24,7*24},true});
units.push_back({UnitType::RightShifter,vf2d{18*24,19*24},false});
units.push_back({UnitType::LeftShifter,vf2d{20*24,22*24},false});
units.push_back({UnitType::LeftShifter,vf2d{21*24,22*24},false});
for(int i=0;i<8;i++){
units.push_back({UnitType::MemoryAllocator,vf2d{20*24,17*24},false});
}
units.push_back({UnitType::_Platform,vf2d{22*24,23*24},false});
}
}
#pragma endregion
}
bool VirusAttack::OnUserCreate(){
@ -303,6 +338,17 @@ void VirusAttack::InitializeSounds(){
LoadSound(Sound::VOICEOVER,"voice.mp3");
LoadSound(Sound::PING,"ping.mp3");
LoadSound(Sound::ALARM,"alarm.mp3");
LoadSound(Sound::SWITCH,"switch.mp3");
LoadSound(Sound::HIT1,"hit1.mp3");
LoadSound(Sound::HIT2,"hit2.mp3");
LoadSound(Sound::HIT3,"hit3.mp3");
LoadSound(Sound::BUTTONSELECT,"buttonselect.mp3");
LoadSound(Sound::SMALLBUILD,"smallbuild.mp3");
LoadSound(Sound::BIGBUILD,"bigbuild.mp3");
LoadSound(Sound::HEAL,"heal.mp3");
LoadSound(Sound::REFRESHER,"refresher.mp3");
LoadSound(Sound::TURRET,"turret.mp3");
LoadSound(Sound::MEMORY_GUARD,"memoryguard.mp3");
}
bool VirusAttack::UnitCreationClickHandled(){
@ -311,14 +357,14 @@ bool VirusAttack::UnitCreationClickHandled(){
for(auto&u:units){ \
if(u->IsSelected()&&u->Validator()&&CanAfford(player_resources,UnitClass::resourceCost)) { \
std::shared_ptr<UnitClass>buildUnit=std::make_shared<UnitClass>(this,u->GetPos(),IMAGES,u->IsFriendly()); \
u->SetBuildUnit(CONSTANT::UNIT_BUILD_TIME,std::move(buildUnit)); \
u->SetBuildUnit(CONSTANT::UNIT_BUILD_TIME,std::move(buildUnit),SOUNDS); \
ExpendResources(player_resources,UnitClass::resourceCost); \
CalculateUsedMemory(); \
} \
} \
SOUNDS[Sound::BUTTONSELECT]->PlayCentered(); \
return true; \
}
CheckClick(LeftShifter,leftShifterButton,IsAllocator)
CheckClick(RightShifter,rightShifterButton,IsAllocator)
CheckClick(BitRestorer,bitRestorerButton,IsAllocator)
@ -686,9 +732,13 @@ bool VirusAttack::OnUserUpdate(float fElapsedTime){
mainMenu.Update(this);
if(campaignStartButton->bPressed){
SOUNDS[Sound::BUTTONSELECT]->PlayCentered();
state=GameState::GAMEPLAY;
RestartLevel();
}
if(exitGameButton->bPressed){
SOUNDS[Sound::BUTTONSELECT]->PlayCentered();
}
titleScreenY=std::min(0.f,titleScreenY+fElapsedTime*120);
nextColorChange=std::max(0.f,nextColorChange-fElapsedTime);
@ -816,7 +866,7 @@ bool VirusAttack::OnUserUpdate(float fElapsedTime){
}
}
}
u->AttemptAttack(u,closestUnit,units,debuffIcons,IMAGES);
u->AttemptAttack(u,closestUnit,units,debuffIcons,IMAGES,SOUNDS);
u->_Update(this,SOUNDS,player_resources,enemy_resources,queuedUnits,resourceGainTimer,resourceGainIcons,IMAGES);
}
@ -991,16 +1041,16 @@ void VirusAttack::DrawSystemMemoryBar(float fElapsedTime){
col=CONSTANT::HEALTH_COLOR;
}break;
case 1:{
col=CONSTANT::RANGE_COLOR;
col=flags.unitMetersGreyedOut?DARK_GREY:CONSTANT::RANGE_COLOR;
}break;
case 2:{
col=CONSTANT::ATKSPD_COLOR;
col=flags.unitMetersGreyedOut?DARK_GREY:CONSTANT::ATKSPD_COLOR;
}break;
case 3:{
col=CONSTANT::MOVESPD_COLOR;
col=flags.unitMetersGreyedOut?DARK_GREY:CONSTANT::MOVESPD_COLOR;
}break;
case 4:{
col=CONSTANT::PROCEDURE_COLOR;
col=flags.unitMetersGreyedOut?DARK_GREY:CONSTANT::PROCEDURE_COLOR;
}break;
}
DrawPartialDecal(barPos+vf2d{barOffset+1,1.f},{barSegmentWidth,3},IMAGES[SEGMENT_BAR]->Decal(),{0,0},{float(playerUsedDisplayMemory[i]),3.f},col);
@ -1016,16 +1066,16 @@ void VirusAttack::DrawSystemMemoryBar(float fElapsedTime){
col=CONSTANT::HEALTH_COLOR;
}break;
case 1:{
col=CONSTANT::RANGE_COLOR;
col=flags.unitMetersGreyedOut?DARK_GREY:CONSTANT::RANGE_COLOR;
}break;
case 2:{
col=CONSTANT::ATKSPD_COLOR;
col=flags.unitMetersGreyedOut?DARK_GREY:CONSTANT::ATKSPD_COLOR;
}break;
case 3:{
col=CONSTANT::MOVESPD_COLOR;
col=flags.unitMetersGreyedOut?DARK_GREY:CONSTANT::MOVESPD_COLOR;
}break;
case 4:{
col=CONSTANT::PROCEDURE_COLOR;
col=flags.unitMetersGreyedOut?DARK_GREY:CONSTANT::PROCEDURE_COLOR;
}break;
}
DrawPartialDecal(barPos+vf2d{barOffset+actualBarWidth+3-barSegmentWidth,1.f},{barSegmentWidth,3},IMAGES[SEGMENT_BAR]->Decal(),{0,0},{float(enemyUsedDisplayMemory[i]),3.f},col);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 MiB

After

Width:  |  Height:  |  Size: 24 MiB

File diff suppressed because one or more lines are too long

Binary file not shown.
Loading…
Cancel
Save