Compare commits

..

3 Commits

  1. 5
      .gitignore
  2. 2
      olcCodeJam2023Entry/Constant.cpp
  3. 2
      olcCodeJam2023Entry/Constant.h
  4. 10
      olcCodeJam2023Entry/GameFlags.h
  5. 9
      olcCodeJam2023Entry/GameState.h
  6. 3
      olcCodeJam2023Entry/Image.h
  7. 17
      olcCodeJam2023Entry/Info.txt
  8. 8
      olcCodeJam2023Entry/Level.h
  9. 7
      olcCodeJam2023Entry/Memory.h
  10. 838
      olcCodeJam2023Entry/Scenario.cpp
  11. 118
      olcCodeJam2023Entry/Scenario.h
  12. 35
      olcCodeJam2023Entry/Sound.h
  13. 106
      olcCodeJam2023Entry/Textbox.cpp
  14. 14
      olcCodeJam2023Entry/Textbox.h
  15. 406
      olcCodeJam2023Entry/Unit.cpp
  16. 139
      olcCodeJam2023Entry/Unit.h
  17. 1223
      olcCodeJam2023Entry/VirusAttack.cpp
  18. 59
      olcCodeJam2023Entry/VirusAttack.h
  19. BIN
      olcCodeJam2023Entry/assets/ending.png
  20. BIN
      olcCodeJam2023Entry/assets/restart.png
  21. BIN
      olcCodeJam2023Entry/assets/restartHover.png
  22. BIN
      olcCodeJam2023Entry/assets/round_bar.png
  23. BIN
      olcCodeJam2023Entry/assets/shieldbubble.png
  24. 2
      olcCodeJam2023Entry/emscripten_build.ps1
  25. 27
      olcCodeJam2023Entry/olcCodeJam2023Entry.vcxproj
  26. 9
      olcCodeJam2023Entry/olcCodeJam2023Entry.vcxproj.filters
  27. 24
      olcCodeJam2023Entry/olcPGEX_AudioSource.h
  28. 120
      olcCodeJam2023Entry/olcPGEX_QuickGUI.h
  29. 4
      olcCodeJam2023Entry/olcPGEX_SplashScreen.h
  30. 6
      olcCodeJam2023Entry/olcPGEX_TransformedView.h
  31. 14
      olcCodeJam2023Entry/olcPixelGameEngine.h
  32. 6
      olcCodeJam2023Entry/olcUTIL_Camera2D.h
  33. BIN
      olcCodeJam2023Entry/pge.data
  34. 1297
      olcCodeJam2023Entry/pge.html
  35. 11154
      olcCodeJam2023Entry/pge.js
  36. BIN
      olcCodeJam2023Entry/pge.wasm
  37. 4
      olcCodeJam2023Entry/util.cpp
  38. 2
      olcCodeJam2023Entry/util.h

5
.gitignore vendored

@ -11,9 +11,6 @@
*.sln.docstates
*.wav
Windows
Emscripten
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
@ -366,5 +363,3 @@ MigrationBackup/
# Fody - auto-generated XML schema
FodyWeavers.xsd
*.mp3
*.zip
/olcCodeJam2023Entry/VirusAttack.exe

@ -39,5 +39,3 @@ std::string CONSTANT::MEMORY_ALLOCATOR_BOX_HEADER_STRING="Memory Allocator";
Pixel CONSTANT::INCREASE_VALUE_COLOR={7, 223, 247};
Pixel CONSTANT::DECREASE_VALUE_COLOR={201, 30, 30};
float CONSTANT::RESTART_BUTTON_HOLD_TIME=2.5;

@ -43,6 +43,4 @@ public:
static Pixel INCREASE_VALUE_COLOR;
static Pixel DECREASE_VALUE_COLOR;
static float RESTART_BUTTON_HOLD_TIME;
};

@ -1,10 +0,0 @@
#pragma once
struct GameFlags{
bool unitMetersGreyedOut=true;//If true, all but health meters show up as dark grey.
bool playerInControl=false;
bool limitedBuildOptions=false;
bool guideEnabled=false;
bool flashMemoryBar=false;
int difficulty=1; //0=Easy, 1=Normal, 2=Hard
};

@ -1,9 +0,0 @@
#pragma once
enum class GameState{
MAIN_MENU,
GAMEPLAY,
COMPLETED,
CREDITS
};

@ -42,8 +42,5 @@ enum Image{
SEGMENT_BAR,
HOODED_FIGURE,
SPOOK_HOODED_FIGURE,
RESTART,
RESTART_HOVER,
SHIELD_BUBBLE,
};

@ -39,7 +39,7 @@ Fake allies the narrator forgot to switch over
Day 9 Sounds/Music/Menus - Timer (Speedrun) Difficulty Selection
Ending...Shows Four Seasons of Loneliness boss zoom out...
Easy Difficulty: AI generate no new resources. Start with 100 of each.
Easy Difficulty: AI generate no new resources.
Normal Difficulty: AI generates resources at normal rate.
Hard Difficulty: AI generates resources at x4 rate.
@ -56,7 +56,7 @@ Stage 1:
The yellow bar represent a unit's Health memory allocation. Make sure there's always at least 1 bit of it.
(Simulate dragging over unit and selection)
Drag over your target unit and then select a target location via right-click.
Highlight over your target unit and then select a target location via right-click.
That should be all you need for now. I'll be back after my coffee break.
@ -102,8 +102,7 @@ Stage 4:
[Pan over to a collection point]
But we can collect bits from the system using these collection points.
Simply bring over any unit to these and attach them to it. They will start providing you with system resources to make what you need.
Remember that the system has limited memory available. You'll always be fighting for free space from the system.
(After attaching two units to collection points...)
(After attaching a unit to a collection point...)
2 Left shifters wander into the area.
[Pan over to the RAM bank]
An ambush...? I, WHAT? -- THIS IS NOT-
@ -129,9 +128,6 @@ Stage 8:
(New Scenario Objective:
-Defeat all enemy units)
Create a Restart feature.
Distribution of Collection Points:
HEALTH 60
ATKSPD 21
@ -152,10 +148,3 @@ Space - Gravity (Ambient 1)
1 Glorious Venture (Ending theme?)
Credits
Finish Scenarios (End condition for the game)
Finish up main menu stuff (including credits)
AI stuff

@ -3,6 +3,8 @@
#include "Unit.h"
#include "CollectionPoint.h"
class Scenario;
enum LevelName{
STAGE1,
STAGE2,
@ -12,7 +14,6 @@ enum LevelName{
STAGE6,
STAGE7,
STAGE8,
FINISH,
};
struct UnitData{
@ -32,14 +33,13 @@ struct CPData{
//Large: 1280
struct Level{
LevelName name=STAGE1;
vi2d size={1,1};
Resources player_starting_resources;
Resources enemy_starting_resources;
std::vector<UnitData>unitPlacement;
std::vector<CPData>cpPlacement;
Sound::Sound bgm=Sound::COSMOS;
int scenarioIndex=0;
Sound bgm=Sound::COSMOS;
Scenario*scenario;
vf2d cameraStart={96,96};
vf2d worldZoom={1,1};
Pixel levelColor=DARK_GREEN;

@ -1,7 +0,0 @@
#pragma once
#include "MemoryType.h"
struct Memory{
MemoryType type;
int size;
};

@ -1,838 +1,38 @@
#include "Scenario.h"
#include "TileManager.h"
#include "olcUTIL_Geometry2D.h"
extern VirusAttack*game;
Scenario::Scenario(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)
:units(units),IMAGES(IMAGES),SOUNDS(SOUNDS),objective(objective),game(game),flags(flags){}
Scenario::~Scenario(){};
void Scenario::_Start(){
state=0;
camera=utils::Camera2D{game.GetPGE()->GetScreenSize(),game.GetWorldOffset()};
camera.SetLazyFollowRate(2);
camera.SetMode(utils::Camera2D::Mode::LazyFollow);
targetPos={96,96};
box.SetVisible(false);
initialWaitTime=3;
camera.SetTarget(targetPos);
missionCompletedTimer=0;
transitionToNextLevel=false;
setupEasyMode=false;
Start();
Scenario::Scenario(){
dialog.SetVisible(false);
}
void Scenario::Start(){};
void Scenario::_Update(Resources&enemy_resources,std::vector<std::shared_ptr<CollectionPoint>>&collectionPoints,int availableMemory,std::vector<std::shared_ptr<Unit>>&queuedUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS){
initialWaitTime=std::max(0.f,initialWaitTime-game.GetPGE()->GetElapsedTime());
missionFinishWaitTime=std::max(0.f,missionFinishWaitTime-game.GetPGE()->GetElapsedTime());
smallTimePass=std::min(1.f,smallTimePass+game.GetPGE()->GetElapsedTime());
if(flags.playerInControl){
smallTimePass=0;
}
if(missionCompleted){
missionCompletedTimer+=game.GetPGE()->GetElapsedTime();
} else {
missionCompleted=MissionCompleted();
}
if(flags.playerInControl){
RunAI(enemy_resources,collectionPoints,availableMemory,queuedUnits,SOUNDS);
}
if(initialWaitTime==0){
Update();
}
};
void Scenario::RunAI(Resources&enemy_resources,std::vector<std::shared_ptr<CollectionPoint>>&collectionPoints,int availableMemory,std::vector<std::shared_ptr<Unit>>&queuedUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS){
if(!flags.guideEnabled||flags.limitedBuildOptions||flags.unitMetersGreyedOut)return; //We don't enable advanced AI during tutorials.
Scenario::~Scenario(){}
if(!setupEasyMode&&flags.difficulty==0){
enemy_resources={100,100,100,100,100};
setupEasyMode=true;
}
attackTimer=std::max(0.f,attackTimer-game.GetPGE()->GetElapsedTime());
unitBuildTimer=std::max(0.f,unitBuildTimer-game.GetPGE()->GetElapsedTime());
std::weak_ptr<Unit>baseOfOperations;
std::weak_ptr<Unit>enemyBaseOfOperations;
for(auto&u:units){
if(!u->IsFriendly()&&u->IsRAMBank()){
baseOfOperations=u;
break;
}
}
for(auto&u:units){
if(u->IsFriendly()&&u->IsRAMBank()){
enemyBaseOfOperations=u;
break;
}
}
if(baseOfOperations.expired()){
for(auto&u:units){
if(!u->IsFriendly()){
baseOfOperations=u;
break;
}
}
}
//See if there are collectors, if so send memory allocator units towards them.
if(!baseOfOperations.expired()){
std::sort(collectionPoints.begin(),collectionPoints.end(),[&](std::shared_ptr<CollectionPoint>cp1,std::shared_ptr<CollectionPoint>cp2){
geom2d::line<float>toCP1={cp1->pos,baseOfOperations.lock()->GetPos()};
geom2d::line<float>toCP2={cp2->pos,baseOfOperations.lock()->GetPos()};
return toCP1.length()<toCP2.length();});
}
int maxOfResources=enemy_resources.health;
maxOfResources=std::max(maxOfResources,enemy_resources.atkSpd);
maxOfResources=std::max(maxOfResources,enemy_resources.moveSpd);
maxOfResources=std::max(maxOfResources,enemy_resources.procedure);
maxOfResources=std::max(maxOfResources,enemy_resources.range);
if(maxOfResources<10){
for(auto&cp:collectionPoints){
if(cp->attachedUnit.expired()){
if(cpCheckTimer.count(cp.get())==0||cpCheckTimer[cp.get()]<=0){
for(auto&u:units){
if(!u->IsFriendly()&&u->IsAllocator()&&u->attachTarget.expired()){
//Tell this unit to move towards that collection point.
u->SetTargetCollectionPoint(cp,u);
break;
}
}
//Hasn't been checked recently.
cpCheckTimer[cp.get()]=60;
}
}
}
}
for(auto&key:cpCheckTimer){
cpCheckTimer[key.first]=std::max(0.0f,cpCheckTimer[key.first]-game.GetPGE()->GetElapsedTime());
}
int memoryAllocatorCount=0;
for(auto&u:units){
if(!u->IsFriendly()&&u->IsAllocator()){
memoryAllocatorCount++;
}
}
if(memoryAllocatorCount<3){
for(auto&u:units){
if(!u->IsFriendly()&&u->IsRAMBank()){
AttemptBuild(UnitType::MemoryAllocator,u->GetPos(),MemoryAllocator::resourceCost,enemy_resources,availableMemory,queuedUnits);
}
}
}
void Scenario::Start(){}
//Randomly turn memory allocators into other units.
if(unitBuildTimer==0){
for(auto&u:units){
if(!u->IsFriendly()&&u->IsAllocator()&&u->attachTarget.expired()){
std::array<UnitType,10>unitChoiceList={UnitType::LeftShifter,UnitType::LeftShifter,UnitType::RightShifter,UnitType::RightShifter,
UnitType::Corrupter,UnitType::MemorySwapper,UnitType::BitRestorer,UnitType::BitRestorer,UnitType::_Platform,UnitType::Corrupter};
std::array<std::vector<Memory>,10>unitResourceCostList={LeftShifter::resourceCost,LeftShifter::resourceCost,RightShifter::resourceCost,RightShifter::resourceCost,
Corrupter::resourceCost,MemorySwapper::resourceCost,BitRestorer::resourceCost,BitRestorer::resourceCost,_Platform::resourceCost,Corrupter::resourceCost};
int randomIndex=rand()%unitChoiceList.size();
UnitType buildUnit=unitChoiceList[randomIndex];
int totalCost=0;
for(int i=0;i<unitResourceCostList[randomIndex].size();i++){
totalCost+=unitResourceCostList[randomIndex][i].size;
}
if(totalCost<=availableMemory){
#define Build(type) \
case UnitType::type:{ \
u->SetBuildUnit(8,std::make_shared<type>(game.GetPGE(),u->GetPos(),IMAGES,false),SOUNDS); \
}break;
switch(buildUnit){
Build(LeftShifter)
Build(RightShifter)
Build(BitRestorer)
Build(_Platform)
Build(Corrupter)
Build(MemorySwapper)
}
if(enemy_resources.health>0){enemy_resources.health=std::max(0,enemy_resources.health-totalCost);}else
if(enemy_resources.atkSpd>0){enemy_resources.atkSpd=std::max(0,enemy_resources.atkSpd-totalCost);}else
if(enemy_resources.moveSpd>0){enemy_resources.moveSpd=std::max(0,enemy_resources.moveSpd-totalCost);}else
if(enemy_resources.range>0){enemy_resources.range=std::max(0,enemy_resources.range-totalCost);}else
{enemy_resources.procedure=std::max(0,enemy_resources.procedure-totalCost);
}
availableMemory-=totalCost;
}
}
if(!u->IsFriendly()&&u->IsPlatform()){
std::array<UnitType,7>unitChoiceList={UnitType::RAMBank,UnitType::Refresher,UnitType::Refresher,UnitType::Turret,
UnitType::Turret,UnitType::Turret,UnitType::MemoryGuard};
std::array<std::vector<Memory>,7>unitResourceCostList={RAMBank::resourceCost,Refresher::resourceCost,Refresher::resourceCost,Turret::resourceCost,
Turret::resourceCost,Turret::resourceCost,MemoryGuard::resourceCost};
int randomIndex=rand()%unitChoiceList.size();
UnitType buildUnit=unitChoiceList[randomIndex];
int totalCost=0;
for(int i=0;i<unitResourceCostList[randomIndex].size();i++){
totalCost+=unitResourceCostList[randomIndex][i].size;
}
if(totalCost<=availableMemory){
#define Build(type) \
case UnitType::type:{ \
u->SetBuildUnit(8,std::make_shared<type>(game.GetPGE(),u->GetPos(),IMAGES,false),SOUNDS); \
}break;
switch(buildUnit){
Build(RAMBank)
Build(Refresher)
Build(Turret)
Build(MemoryGuard)
}
if(enemy_resources.health>0){enemy_resources.health=std::max(0,enemy_resources.health-totalCost);}else
if(enemy_resources.atkSpd>0){enemy_resources.atkSpd=std::max(0,enemy_resources.atkSpd-totalCost);}else
if(enemy_resources.moveSpd>0){enemy_resources.moveSpd=std::max(0,enemy_resources.moveSpd-totalCost);}else
if(enemy_resources.range>0){enemy_resources.range=std::max(0,enemy_resources.range-totalCost);}else
{enemy_resources.procedure=std::max(0,enemy_resources.procedure-totalCost);
}
availableMemory-=totalCost;
}
}
switch(flags.difficulty){
case 0:{
unitBuildTimer=120;
}break;
case 1:{
unitBuildTimer=60;
}break;
case 2:{
unitBuildTimer=10;
}break;
}
}
}
if(attackTimer==0){
if(!enemyBaseOfOperations.expired()){
for(auto&u:units){
if(!u->IsFriendly()&&rand()%3==0){
if(u->CanInteractWithEnemies()&&!u->IsAllocator()&&u->CanMove()){
u->SetTargetUnit(enemyBaseOfOperations);
}
}
}
for(auto&u:units){
if(!u->IsFriendly()&&u->GetCurrentTarget().expired()&&u->CanInteractWithAllies()){
if(rand()%5==0){
u->SetTargetLocation(enemyBaseOfOperations.lock()->GetPos());
}
}
}
}
switch(flags.difficulty){
case 0:{
attackTimer=999;
}break;
case 1:{
attackTimer=300;
}break;
case 2:{
attackTimer=120;
}break;
}
}
void Scenario::_Update(){
initialWaitTimer=std::max(0.f,initialWaitTimer-game->GetElapsedTime());
Update();
}
/*
std::shared_ptr<UnitClass>buildUnit=std::make_shared<UnitClass>(this,u->GetPos(),IMAGES,u->IsFriendly()); \
u->SetBuildUnit(CONSTANT::UNIT_BUILD_TIME,std::move(buildUnit),SOUNDS); \
*/
bool Scenario::AttemptBuild(UnitType unit,vf2d pos,std::vector<Memory>&resourceCost,Resources&enemy_resources,int availableMemory,std::vector<std::shared_ptr<Unit>>&queuedUnits){
int enemyTotalResources=enemy_resources.atkSpd+enemy_resources.health+enemy_resources.moveSpd+enemy_resources.procedure+enemy_resources.range;
int totalCost=0;
for(int i=0;i<resourceCost.size();i++){
totalCost+=resourceCost[i].size;
}
if(totalCost>availableMemory)return false;
if(enemyTotalResources>=totalCost){
if(enemy_resources.health>0){enemy_resources.health=std::max(0,enemy_resources.health-totalCost);}else
if(enemy_resources.atkSpd>0){enemy_resources.atkSpd=std::max(0,enemy_resources.atkSpd-totalCost);}else
if(enemy_resources.moveSpd>0){enemy_resources.moveSpd=std::max(0,enemy_resources.moveSpd-totalCost);}else
if(enemy_resources.range>0){enemy_resources.range=std::max(0,enemy_resources.range-totalCost);}else
{enemy_resources.procedure=std::max(0,enemy_resources.procedure-totalCost);}
#define TranslateUnit(type) \
case UnitType::type:{ \
queuedUnits.emplace_back(std::make_shared<type>(game.GetPGE(),pos,IMAGES,false)); \
}break;
switch(unit){
TranslateUnit(MemoryAllocator)
TranslateUnit(LeftShifter)
TranslateUnit(RightShifter)
TranslateUnit(BitRestorer)
TranslateUnit(MemorySwapper)
TranslateUnit(Corrupter)
TranslateUnit(RAMBank)
TranslateUnit(MemoryGuard)
TranslateUnit(Refresher)
TranslateUnit(Turret)
TranslateUnit(_Platform)
}
}
return true;
void Scenario::_Draw(){
Draw();
}
bool Scenario::MissionCompleted(){return false;}
void Scenario::Update(){};
void Scenario::Draw(){
if(objective.length()>0){
game.GetPGE()->DrawShadowStringDecal({4,24},"Objective:");
game.GetPGE()->DrawShadowStringDecal({6,36},objective);
game.GetPGE()->DrawShadowStringDecal({4,24},missionCompleted?"Objective Complete!":"Objective:",missionCompleted?GREEN:WHITE);
vf2d textSize=game.GetPGE()->GetTextSize(objective);
game.GetPGE()->DrawShadowStringDecal({6,36},objective,missionCompleted?GREEN:WHITE);
if(missionCompleted&&missionFinishWaitTime==0){
game.GetPGE()->FillRectDecal(vf2d{6,36}+vf2d{0,textSize.y/2-1},{textSize.x,3});
std::string continueText="< Press [Spacebar] to continue >";
vf2d textScale={2,3};
vf2d textSize=game.GetPGE()->GetTextSizeProp(continueText)*textScale;
game.GetPGE()->DrawShadowStringPropDecal(game.GetPGE()->GetScreenSize()/2-textSize/2+vf2d{0,72},continueText,{255,255,255,uint8_t(abs(sin(2*missionCompletedTimer))*255)},{0,0,0,uint8_t(abs(sin(2*missionCompletedTimer))*255)},textScale);
if(game.GetPGE()->GetKey(SPACE).bPressed){
transitionToNextLevel=true;
}
}
}
Resources temp={0,0,0,0,0};
box.UpdateAndDraw({24,64},game.GetPGE(),temp,IMAGES,0,0);
}
void Scenario::SetCameraTarget(vf2d pos,bool instant){
if(instant){camera.SetMode(utils::Camera2D::Mode::Simple);} else {camera.SetMode(utils::Camera2D::Mode::LazyFollow);}
targetPos=pos;
camera.SetTarget(targetPos);
camera.Update(game.GetPGE()->GetElapsedTime());
game.SetWorldOffset(camera.GetViewPosition());
}
void Scenario::SetObjective(std::string objective){
this->objective=objective;
}
void Scenario::RevealTiles(vf2d pos){
for(int y=-1;y<=1;y++){
for(int x=-1;x<=1;x++){
vi2d basePos={int(pos.x+x*96),int(pos.y+y*96)};
TileManager::visibleTiles[{basePos.x/96,basePos.y/96}]=30;
}
}
}
Stage1::Stage1(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){}
Stage1::Stage1(){}
Stage1::~Stage1(){}
void Stage1::Start(){
flags.unitMetersGreyedOut=true;
flags.playerInControl=false;
nextLevel=LevelName::STAGE2;
};
void Scenario::DisplayBox(std::string text,bool scaryHoodedFigure){
if(smallTimePass==1){
box.Initialize(text,{24,64},"",scaryHoodedFigure?IMAGES[SPOOK_HOODED_FIGURE].get():IMAGES[HOODED_FIGURE].get(),{378,28},SOUNDS[Sound::VOICEOVER].get());
}
game->unitMetersGreyedOut=true;
game->playerInControl=false;
}
void Stage1::Update(){
switch(state){
case 0:{
DisplayBox("Hello Hacker, thank you for taking on this request for me.");
if(box.bPressed){
state=1;
}
}break;
case 1:{
DisplayBox("It appears we have no time to waste, many sectors are already infected and the virus spread will just keep getting worse.");
if(box.bPressed){
state=2;
SOUNDS[Sound::PING]->PlayCentered();
RevealTiles({320,320});
}
}break;
case 2:{
SetCameraTarget({320,320});
if(camera.ReachedTarget()){
state=3;
}
}break;
case 3:{
DisplayBox("Your mission is to take out all the RAM banks from the system, this will stop any further creation and spread of viruses.");
if(box.bPressed){
state=4;
}
}break;
case 4:{
SetCameraTarget({128,128});
if(camera.ReachedTarget()){
state=5;
}
}break;
case 5:{
DisplayBox("The yellow bars represent units' allocated Health memory. Take out the enemies' and make sure you always have at least 1 bit of it.");
if(box.bPressed){
state=6;
}
}break;
case 6:{
DisplayBox("Drag over your target unit and then select a target location via right-click.");
if(box.bPressed){
state=7;
}
}break;
case 7:{
SetObjective("Defeat the RAM bank");
DisplayBox("That should be all you need for now. I'll be back after my coffee break.");
if(box.bPressed){
state=8;
box.SetVisible(false);
flags.playerInControl=true;
}
}break;
case 8:{
}break;
}
};
bool Stage1::MissionCompleted(){
for(auto&u:units){
if(!u->IsFriendly()&&u->IsRAMBank()){
return false;
}
}
return true;
}
Stage2::Stage2(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 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:{
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;
box.SetVisible(false);
flags.playerInControl=true;
}
}break;
case 2:{
for(auto&u:units){
if(u->IsRAMBank()&&u->IsFriendly()){
state=3;
flags.playerInControl=false;
SetObjective("");
break;
}
}
}break;
case 3:{
DisplayBox("Excellent, each RAM bank has the capability to allocate memory into the system. See that indicator down below?");
flags.flashMemoryBar=true;
if(box.bPressed){
state=4;
}
}break;
case 4:{
DisplayBox("This sector lets us allocate 30 bytes of RAM. That's 240 bits for the savvy folks out there.");
if(box.bPressed){
state=5;
flags.flashMemoryBar=false;
}
dialog.Initialize("Hello Hacker, thank you for taking on this request for me.",{24,64},"",&game->IMAGES[SEGMENT_BAR],{378,28});
}break;
case 5:{
DisplayBox("Some of it has already been used up by our RAM bank and other system resources... ");
if(box.bPressed){
state=6;
}
}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;
box.SetVisible(false);
flags.playerInControl=true;
}
}break;
case 7:{
for(auto&u:units){
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;
box.SetVisible(false);
flags.playerInControl=true;
}
}break;
case 9:{
for(auto&u:units){
if(!u->IsAllocator()&&!u->IsRAMBank()&&u->IsFriendly()){
state=10;
flags.playerInControl=false;
SetObjective("");
break;
}
}
}break;
case 10:{
DisplayBox("The memory shifters will be your primary way to delete memory from units.");
if(box.bPressed){
state=11;
SOUNDS[Sound::ALARM]->PlayCentered();
}
}break;
case 11:{
SetCameraTarget({22*24,23*24});
RevealTiles({22*24,23*24});
if(camera.ReachedTarget()){
state=12;
}
}break;
case 12:{
SetObjective("Defeat all enemy units.");
DisplayBox("I have detected viruses in the system again. Please eradicate them and free system resources.");
if(box.bPressed){
state=13;
flags.playerInControl=true;
box.SetVisible(false);
}
}break;
}
};
bool Stage2::MissionCompleted(){
for(auto&u:units){
if(!u->IsFriendly()){
return false;
}
}
return true;
}
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;
flags.limitedBuildOptions=true;
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.limitedBuildOptions=false;
flags.playerInControl=true;
box.SetVisible(false);
}
}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(){
nextLevel=LevelName::STAGE5;
flags.playerInControl=false;
flags.guideEnabled=true;
flags.limitedBuildOptions=false;
flags.unitMetersGreyedOut=false;
flags.flashMemoryBar=false;
SetCameraTarget({4*24,4*24},true);
};
void Stage4::Update(){
switch(state){
case 0:{
DisplayBox("Hacker, I have unfortunate news. I can't supply you with any more bits to construct things with.");
if(box.bPressed){
state=1;
}
}break;
case 1:{
DisplayBox("You've only got 3 health bits to start with this time. To allocate memory you always need at least 5 bits of memory.");
if(box.bPressed){
state=2;
}
}break;
case 2:{
SetCameraTarget({8*24,1*24});
if(camera.ReachedTarget()){
state=3;
}
}break;
case 3:{
DisplayBox("But we can collect bits from the system using these collection points.");
if(box.bPressed){
state=4;
}
}break;
case 4:{
DisplayBox("Simply bring over any unit to these and attach them to it. They will start providing you with system resources to make what you need.");
if(box.bPressed){
state=5;
}
}break;
case 5:{
flags.flashMemoryBar=true;
SetObjective("Setup units at collection points");
DisplayBox("Remember that the system has limited memory available. You'll always be fighting for free space from the system.");
if(box.bPressed){
state=6;
box.SetVisible(false);
flags.playerInControl=true;
flags.flashMemoryBar=false;
}
}break;
case 6:{
collectorsAttached=0;
for(auto&u:units){
if(u->IsAttached()){
collectorsAttached++;
}
}
if(collectorsAttached>=2){
std::shared_ptr<Unit>target;
for(auto&u:units){
if(u->IsRAMBank()){
target=u;
}
}
state=7;
SOUNDS[Sound::ALARM]->PlayCentered();
flags.playerInControl=false;
auto u1=std::make_shared<LeftShifter>(game.GetPGE(),vf2d{4*24,10*24},IMAGES,false);
auto u2=std::make_shared<LeftShifter>(game.GetPGE(),vf2d{4*24,10*24},IMAGES,false);
auto u3=std::make_shared<LeftShifter>(game.GetPGE(),vf2d{4*24,10*24},IMAGES,false);
units.push_back(u1);
units.push_back(u2);
units.push_back(u3);
u1->SetTargetUnit(target);
u2->SetTargetUnit(target);
u3->SetTargetUnit(target);
}
}break;
case 7:{
SetCameraTarget({4*24,4*24});
if(camera.ReachedTarget()){
state=8;
SOUNDS[Sound::WIND]->PlayCentered();
}
}break;
case 8:{
DisplayBox("An ambush...? I, WHAT? -- THIS IS NOT-");
if(box.bPressed){
state=9;
box.SetVisible(false);
nextLevelTimer=5;
}
}break;
case 9:{
nextLevelTimer=std::max(0.f,nextLevelTimer-game.GetPGE()->GetElapsedTime());
if(nextLevelTimer==0){
state=10;
}
}break;
case 10:{
transitionToNextLevel=true;
state=11;
}break;
}
};
bool Stage4::MissionCompleted(){
return false;
}
Stage5::Stage5(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 Stage5::Start(){
SetCameraTarget({4*24,4*24},true);
flags.playerInControl=true;
SetObjective("Defeat all enemy RAM banks.");
nextLevel=LevelName::STAGE6;
};
void Stage5::Update(){
switch(state){
case 0:{
void Stage1::Draw(){
}break;
}
};
bool Stage5::MissionCompleted(){
for(auto&u:units){
if(!u->IsFriendly()&&u->IsRAMBank()){
return false;
}
}
return true;
}
Stage6::Stage6(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 Stage6::Start(){
SetCameraTarget({4*24,4*24},true);
flags.playerInControl=true;
SetObjective("Defeat all enemy RAM banks.");
nextLevel=LevelName::STAGE7;
};
void Stage6::Update(){
switch(state){
case 0:{
flags.playerInControl=false;
DisplayBox("...");
if(box.bPressed){
flags.playerInControl=true;
box.SetVisible(false);
state=1;
}
}break;
}
};
bool Stage6::MissionCompleted(){
for(auto&u:units){
if(!u->IsFriendly()&&u->IsRAMBank()){
return false;
}
}
return true;
}
Stage7::Stage7(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 Stage7::Start(){
SetCameraTarget({4*24,4*24},true);
flags.playerInControl=true;
SetObjective("Defeat all enemy units.");
nextLevel=LevelName::STAGE8;
};
void Stage7::Update(){
switch(state){
case 0:{
flags.playerInControl=false;
DisplayBox("I see you have a few new tricks up your sleeve, Hacker.",true);
if(box.bPressed){
state=1;
}
}break;
case 1:{
DisplayBox("Don't think it'll be that easy to get through this one...",true);
if(box.bPressed){
state=2;
flags.playerInControl=true;
box.SetVisible(false);
}
}break;
}
};
bool Stage7::MissionCompleted(){
for(auto&u:units){
if(!u->IsFriendly()){
return false;
}
}
return true;
}
Stage8::Stage8(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 Stage8::Start(){
SetCameraTarget({4*24,4*24},true);
flags.playerInControl=false;
SetObjective("Defeat all enemy units.");
nextLevel=LevelName::FINISH;
};
void Stage8::Update(){
switch(state){
case 0:{
DisplayBox("You need to cease all operations, you are causing more harm than good.",true);
if(box.bPressed){
state=1;
flags.playerInControl=true;
box.SetVisible(false);
}
}break;
}
};
bool Stage8::MissionCompleted(){
for(auto&u:units){
if(!u->IsFriendly()){
return false;
}
}
return true;
}

@ -1,116 +1,26 @@
#pragma once
#include "olcUTIL_Camera2D.h"
#include "Textbox.h"
#include "Unit.h"
#include "olcPGEX_AudioSource.h"
#include "olcPGEX_TransformedView.h"
#include "GameFlags.h"
#include "Level.h"
#include "VirusAttack.h"
class Scenario{
public:
Scenario(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);
virtual~Scenario();
void _Start();
void Draw();
Scenario();
virtual ~Scenario();
virtual void Start();
void _Update(Resources&enemy_resources,std::vector<std::shared_ptr<CollectionPoint>>&collectionPoints,int availableMemory,std::vector<std::shared_ptr<Unit>>&queuedUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS);
bool transitionToNextLevel=false;
LevelName nextLevel=LevelName::STAGE1;
void RunAI(Resources&enemy_resources,std::vector<std::shared_ptr<CollectionPoint>>&collectionPoints,int availableMemory,std::vector<std::shared_ptr<Unit>>&queuedUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS);
bool setupEasyMode=false;
float attackTimer=120;
std::map<CollectionPoint*,float>cpCheckTimer;
bool AttemptBuild(UnitType unit,vf2d pos,std::vector<Memory>&resourceCost,Resources&enemy_resources,int availableMemory,std::vector<std::shared_ptr<Unit>>&queuedUnits);
void _Update();
virtual void Update()=0;
void _Draw();
virtual void Draw()=0;
protected:
void DisplayBox(std::string text,bool scaryHoodedFigure=false);
void SetCameraTarget(vf2d pos,bool instant=false);
void SetObjective(std::string objective);
void RevealTiles(vf2d pos);
virtual bool MissionCompleted();
virtual void Update();
int state=0;
utils::Camera2D camera;
vf2d targetPos;
Textbox box;
float initialWaitTime=3;
bool missionCompleted=false;
float missionFinishWaitTime=3;
float missionCompletedTimer=0;
float smallTimePass=0;
std::vector<std::shared_ptr<Unit>>&units;
std::vector<std::unique_ptr<Renderable>>&IMAGES;
std::vector<std::unique_ptr<Audio>>&SOUNDS;
GameFlags&flags;
std::string&objective;
TileTransformedView&game;
float unitBuildTimer=0;
Textbox dialog;
float initialWaitTimer=3;
};
class Stage1:public Scenario{
public:
Stage1(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();
void Update();
bool MissionCompleted();
};
class Stage2:public Scenario{
public:
Stage2(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();
void Update();
bool MissionCompleted();
};
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();
void Update();
bool MissionCompleted();
};
class Stage4:public Scenario{
public:
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);
int collectorsAttached=0;
float nextLevelTimer=0;
protected:
void Start();
void Update();
bool MissionCompleted();
};
class Stage5:public Scenario{
public:
Stage5(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();
void Update();
bool MissionCompleted();
};
class Stage6:public Scenario{
public:
Stage6(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();
void Update();
bool MissionCompleted();
};
class Stage7:public Scenario{
public:
Stage7(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();
void Update();
bool MissionCompleted();
};
class Stage8:public Scenario{
public:
Stage8(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();
void Update();
bool MissionCompleted();
Stage1();
~Stage1();
void Start()override;
void Update()override;
void Draw()override;
};

@ -1,30 +1,9 @@
#pragma once
namespace Sound{
enum Sound:int{
HUM,
GRAVITY,
COSMOS,
BOSS1,
BOSS2,
VOICEOVER,
PING,
ALARM,
SWITCH,
HIT1,
HIT2,
HIT3,
BUTTONSELECT,
SMALLBUILD,
BIGBUILD,
HEAL,
REFRESHER,
TURRET,
MEMORY_GUARD,
SPAWN,
DEAD1,
DEAD2,
DEAD3,
WIND,
};
}
enum class Sound{
HUM,
GRAVITY,
COSMOS,
BOSS1,
BOSS2,
};

@ -4,7 +4,7 @@
Textbox::Textbox(){};
void Textbox::Initialize(std::string text,vf2d pos,std::string headerText,Renderable*boxImg,vf2d maxSize,Audio*dialogSound,std::vector<Memory>resourceCost,float letterDisplayDelay)
void Textbox::Initialize(std::string text,vf2d pos,std::string headerText,Renderable*boxImg,vf2d maxSize,std::vector<Memory>resourceCost,float letterDisplayDelay)
{
if(GetCurrentString()!=text){ //Make sure this is actually a new textbox
SetDefaults();
@ -13,15 +13,6 @@ void Textbox::Initialize(std::string text,vf2d pos,std::string headerText,Render
this->maxSize=maxSize;
this->resourceCost=resourceCost;
this->letterDisplayDelay=letterDisplayDelay;
this->boxImg=boxImg;
if(this->dialogSound!=nullptr){
this->dialogSound->Stop(soundHandle);
this->dialogSound=nullptr;
}
if(dialogSound!=nullptr){
this->dialogSound=dialogSound;
soundHandle=this->dialogSound->PlayCentered(1,audioVolume,true);
}
visible=true;
}
}
@ -37,19 +28,11 @@ void Textbox::SetDefaults(){
displayHeaderText="";
text="";
headerText="";
audioVolume=0;
continueWordTimer=0;
bPressed=false;
}
void Textbox::Update(PixelGameEngine*pge){
if(!visible){
if(dialogSound!=nullptr){
audioVolume=std::max(0.f,audioVolume-pge->GetElapsedTime()*2);
dialogSound->SetVolume(soundHandle,audioVolume);
}
return;
}
if(!visible)return;
lastLetterTime-=pge->GetElapsedTime();
continueWordTimer+=pge->GetElapsedTime();
if(lastLetterTime<=0){
@ -58,10 +41,6 @@ void Textbox::Update(PixelGameEngine*pge){
tempText+=text[textboxMarker+1];
auto WrapText=[&](std::string&tempText,std::string&text,std::string&displayText,int&lastWordMarker,std::string&lastWord){
vf2d maxSize=this->maxSize;
if(boxImg!=nullptr){
maxSize-={26,0};
}
if(pge->GetTextSizeProp(tempText).x>=maxSize.x){
displayText=displayText.substr(0,lastWordMarker);
displayText+='\n';
@ -84,71 +63,38 @@ void Textbox::Update(PixelGameEngine*pge){
WrapText(tempHeaderText,headerText,displayHeaderText,lastHeaderWordMarker,lastHeaderWord);
}
textboxMarker++;
if(dialogSound!=nullptr){
audioVolume=std::min(1.f,audioVolume+0.01f*2);
dialogSound->SetVolume(soundHandle,audioVolume);
audioFadeOutDelay=2;
}
}else{
if(dialogSound!=nullptr){
audioFadeOutDelay=std::max(0.f,audioFadeOutDelay-0.01f);
if(audioFadeOutDelay<=0){
audioVolume=std::max(0.f,audioVolume-0.01f*2);
dialogSound->SetVolume(soundHandle,audioVolume);
}
}
}
maxSize.y=std::max(maxSize.y,float(pge->GetTextSizeProp(displayHeaderText).y+pge->GetTextSizeProp(displayText).y));
lastLetterTime=letterDisplayDelay;
}
if(textboxMarker>=int(text.length()-1)){
bPressed=pge->GetMouse(0).bPressed||pge->GetMouse(1).bPressed;
}
}
void Textbox::Draw(PixelGameEngine*pge,Resources&resources,std::vector<std::unique_ptr<Renderable>>&IMAGES,int totalUsedMemory,int memoryLimit){
void Textbox::Draw(PixelGameEngine*pge,Resources&resources,std::vector<Renderable>&IMAGES,int totalUsedMemory,int memoryLimit){
if(visible){
geom2d::rect<float>boundingRect={pos-vf2d{3,3},maxSize+vf2d{6,6}};
geom2d::rect<float>boxRect={pos-vf2d{3,3},maxSize+vf2d{6,6}};
if(resourceCost.size()>0){
boundingRect.size.x+=36;
boundingRect.size.y=std::max(36.f,boundingRect.size.y);
}
if(boxImg!=nullptr){
boundingRect.size.x+=26;
}
if(boundingRect.bottom().start.y>=pge->ScreenHeight()){
boundingRect.pos-={0,boundingRect.bottom().start.y-pge->ScreenHeight()};
}
if(boundingRect.right().start.x>=pge->ScreenWidth()){
boundingRect.pos-={boundingRect.right().start.x-pge->ScreenWidth(),0};
}
if(boundingRect.top().start.y<0){
boundingRect.pos+={0,-boundingRect.top().start.y};
boxRect.size.x+=36;
boxRect.size.y=std::max(36.f,boxRect.size.y);
}
if(boundingRect.left().start.x<0){
boundingRect.pos+={-boundingRect.left().start.x,0};
if(boxRect.bottom().start.y>=pge->ScreenHeight()){
boxRect.pos-={0,boxRect.bottom().start.y-pge->ScreenHeight()};
}
geom2d::rect<float>textboxRect=boundingRect;
if(boxImg!=nullptr){
textboxRect.pos.x+=26;
textboxRect.size.x-=50;
if(boxRect.right().start.x>=pge->ScreenWidth()){
boxRect.pos-={boxRect.right().start.x-pge->ScreenWidth(),0};
}
pge->FillRectDecal(boundingRect.pos,maxSize+vf2d{6,6},backCol);
pge->DrawRectDecal(boundingRect.pos+vf2d{1,1},maxSize+vf2d{4,4},WHITE);
if(boxImg!=nullptr){
pge->DrawDecal(boundingRect.pos+vf2d{3,3},IMAGES[MATRIX]->Decal(),{0.375,0.375},DARK_GREY);
pge->DrawDecal(boundingRect.pos+vf2d{3,3},boxImg->Decal());
pge->DrawRectDecal(boundingRect.pos+vf2d{3,3},{24,24},YELLOW);
if(boxRect.top().start.y<0){
boxRect.pos+={0,-boxRect.top().start.y};
}
pge->DrawShadowStringPropDecal(textboxRect.pos+vf2d{3,3},displayHeaderText,{245, 218, 66});
pge->DrawShadowStringPropDecal(textboxRect.pos+vf2d{3.f,float(3+pge->GetTextSizeProp(displayHeaderText).y)},displayText,{220,220,220});
if(textboxMarker==int(text.length()-1)&&boxImg!=nullptr){
std::string continueText="Click to Continue";
pge->DrawShadowStringPropDecal(textboxRect.pos+textboxRect.size-vf2d(pge->GetTextSizeProp(continueText))*vf2d{0.6,1}-vf2d{5,-9},continueText,{255,255,255,uint8_t(abs(sin(2*continueWordTimer))*255)},{0,0,0,uint8_t(abs(sin(2*continueWordTimer))*255)},{0.6,1});
if(boxRect.left().start.x<0){
boxRect.pos+={-boxRect.left().start.x,0};
}
pge->FillRectDecal(boxRect.pos,maxSize+vf2d{6,6},backCol);
pge->DrawRectDecal(boxRect.pos+vf2d{1,1},maxSize+vf2d{4,4},WHITE);
pge->DrawShadowStringPropDecal(boxRect.pos+vf2d{3,3},displayHeaderText,{245, 218, 66});
pge->DrawShadowStringPropDecal(boxRect.pos+vf2d{3.f,float(3+pge->GetTextSizeProp(displayHeaderText).y)},displayText,{220,220,220});
if(resourceCost.size()>0){
geom2d::rect<float>resourceBoxRect={textboxRect.pos+vf2d{6+maxSize.x,0},{36,42}};
geom2d::rect<float>resourceBoxRect={boxRect.pos+vf2d{6+maxSize.x,0},{36,42}};
pge->FillRectDecal(resourceBoxRect.pos,resourceBoxRect.size,backCol);
pge->DrawRectDecal(resourceBoxRect.pos+vf2d{1,1},resourceBoxRect.size-vf2d{2,2},WHITE);
vf2d contentPos=resourceBoxRect.pos+vf2d{3,3};
@ -171,35 +117,35 @@ void Textbox::Draw(PixelGameEngine*pge,Resources&resources,std::vector<std::uniq
int totalCost=0;
if(util::GetHealthCost(resourceCost)!=-1){
DrawResourceAmount(index,util::GetHealthCost(resourceCost),resources.health);
pge->DrawDecal(contentPos+vf2d{0,index*6.f},IMAGES[RESOURCE]->Decal(),{0.5,0.5},CONSTANT::HEALTH_COLOR);
pge->DrawDecal(contentPos+vf2d{0,index*6.f},IMAGES[RESOURCE].Decal(),{0.5,0.5},CONSTANT::HEALTH_COLOR);
totalCost+=util::GetHealthCost(resourceCost);
index++;
}
if(util::GetAtkSpdCost(resourceCost)!=-1){
DrawResourceAmount(index,util::GetAtkSpdCost(resourceCost),resources.atkSpd);
pge->DrawDecal(contentPos+vf2d{0,index*6.f},IMAGES[RESOURCE]->Decal(),{0.5,0.5},CONSTANT::ATKSPD_COLOR);
pge->DrawDecal(contentPos+vf2d{0,index*6.f},IMAGES[RESOURCE].Decal(),{0.5,0.5},CONSTANT::ATKSPD_COLOR);
totalCost+=util::GetAtkSpdCost(resourceCost);
index++;
}
if(util::GetMoveSpdCost(resourceCost)!=-1){
DrawResourceAmount(index,util::GetMoveSpdCost(resourceCost),resources.moveSpd);
pge->DrawDecal(contentPos+vf2d{0,index*6.f},IMAGES[RESOURCE]->Decal(),{0.5,0.5},CONSTANT::MOVESPD_COLOR);
pge->DrawDecal(contentPos+vf2d{0,index*6.f},IMAGES[RESOURCE].Decal(),{0.5,0.5},CONSTANT::MOVESPD_COLOR);
totalCost+=util::GetMoveSpdCost(resourceCost);
index++;
}
if(util::GetRangeCost(resourceCost)!=-1){
DrawResourceAmount(index,util::GetRangeCost(resourceCost),resources.range);
pge->DrawDecal(contentPos+vf2d{0,index*6.f},IMAGES[RESOURCE]->Decal(),{0.5,0.5},CONSTANT::RANGE_COLOR);
pge->DrawDecal(contentPos+vf2d{0,index*6.f},IMAGES[RESOURCE].Decal(),{0.5,0.5},CONSTANT::RANGE_COLOR);
totalCost+=util::GetRangeCost(resourceCost);
index++;
}
if(util::GetProcedureCost(resourceCost)!=-1){
DrawResourceAmount(index,util::GetProcedureCost(resourceCost),resources.procedure);
pge->DrawDecal(contentPos+vf2d{0,index*6.f},IMAGES[RESOURCE]->Decal(),{0.5,0.5},CONSTANT::PROCEDURE_COLOR);
pge->DrawDecal(contentPos+vf2d{0,index*6.f},IMAGES[RESOURCE].Decal(),{0.5,0.5},CONSTANT::PROCEDURE_COLOR);
totalCost+=util::GetProcedureCost(resourceCost);
index++;
}
std::string text="Size: "+std::to_string(totalCost)+" bits";
std::string text="Size: "+std::to_string(totalCost)+" bytes";
vi2d size=pge->GetTextSizeProp(text);
drawcol=WHITE;
if(totalCost+totalUsedMemory>memoryLimit){
@ -227,7 +173,7 @@ void Textbox::SetVisible(bool visible){
}
}
void Textbox::UpdateAndDraw(vf2d pos,PixelGameEngine*pge,Resources&resources,std::vector<std::unique_ptr<Renderable>>&IMAGES,int totalUsedMemory,int memoryLimit){
void Textbox::UpdateAndDraw(vf2d pos,PixelGameEngine*pge,Resources&resources,std::vector<Renderable>&IMAGES,int totalUsedMemory,int memoryLimit){
UpdatePosition(pos);
Update(pge);
Draw(pge,resources,IMAGES,totalUsedMemory,memoryLimit);

@ -2,8 +2,7 @@
#include "olcPixelGameEngine.h"
#include "olcPGEX_TransformedView.h"
#include "Resources.h"
#include "olcPGEX_AudioSource.h"
#include "Memory.h"
#include "Unit.h"
class Textbox{
std::string headerText=""; //If a textbox has a header, it displays at the top in a special color.
@ -11,12 +10,8 @@ class Textbox{
std::string text="";
std::string displayText="";
Renderable*boxImg=nullptr;
Audio*dialogSound=nullptr;
int soundHandle=-1;
float audioFadeOutDelay=2;
vf2d pos={};
vf2d maxSize={};
float audioVolume=0;
float lastLetterTime=0;
float letterDisplayDelay=0.01;
int textboxMarker=-1;
@ -30,18 +25,17 @@ class Textbox{
Pixel backCol=CONSTANT::MESSAGE_BOX_DEFAULT_BACKCOL;
public:
Textbox();
void Initialize(std::string text,vf2d pos={},std::string headerText="",Renderable*boxImg=nullptr,vf2d maxSize={120,1},Audio*dialogSound=nullptr,std::vector<Memory>resourceCost={},float letterDisplayDelay=0.01);
void Initialize(std::string text,vf2d pos={},std::string headerText="",Renderable*boxImg=nullptr,vf2d maxSize={120,1},std::vector<Memory>resourceCost={},float letterDisplayDelay=0.01);
void UpdateAndDraw(vf2d pos,PixelGameEngine*pge,Resources&resources,std::vector<std::unique_ptr<Renderable>>&IMAGES,int totalUsedMemory,int memoryLimit);
void UpdateAndDraw(vf2d pos,PixelGameEngine*pge,Resources&resources,std::vector<Renderable>&IMAGES,int totalUsedMemory,int memoryLimit);
std::string&GetCurrentString();
void SetVisible(bool visible);
vf2d GetSize();
void SetBackgroundColor(Pixel col);
bool IsVisible();
bool bPressed=false;
private:
void Update(PixelGameEngine*pge);
void UpdatePosition(vf2d newPos);
void Draw(PixelGameEngine*pge,Resources&resources,std::vector<std::unique_ptr<Renderable>>&IMAGES,int totalUsedMemory,int memoryLimit);
void Draw(PixelGameEngine*pge,Resources&resources,std::vector<Renderable>&IMAGES,int totalUsedMemory,int memoryLimit);
void SetDefaults();
};

@ -7,44 +7,45 @@
#include "Textbox.h"
Unit::~Unit(){};
void Unit::RandomHit(std::vector<std::unique_ptr<Audio>>&SOUNDS){
switch(rand()%3){
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;
}
}
LeftShifter::~LeftShifter(){};
RightShifter::~RightShifter(){};
BitRestorer::~BitRestorer(){};
MemorySwapper::~MemorySwapper(){};
Corrupter::~Corrupter(){};
MemoryAllocator::~MemoryAllocator(){};
RAMBank::~RAMBank(){};
MemoryGuard::~MemoryGuard(){};
Refresher::~Refresher(){};
Turret::~Turret(){};
_Platform::~_Platform(){};
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){}
LeftShifter::LeftShifter(PixelGameEngine*pge,vf2d pos,std::vector<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 ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
void LeftShifter::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
victim<<=1;
RandomHit(SOUNDS);
}
std::string RightShifter::unitName="Right Shifter";
std::string RightShifter::unitDescription="Shifts target memory 1 bit to the right.";
std::vector<Memory> RightShifter::resourceCost={{HEALTH,4},{RANGE,2},{ATKSPD,2},{MOVESPD,6},{PROCEDURE,1}};
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){}
RightShifter::RightShifter(PixelGameEngine*pge,vf2d pos,std::vector<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 ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
void RightShifter::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
victim>>=1;
RandomHit(SOUNDS);
}
std::string BitRestorer::unitName="Bit Restorer";
std::string BitRestorer::unitDescription="Randomly restores 1 missing bit to a target.";
std::vector<Memory> BitRestorer::resourceCost={{PROCEDURE,6},{RANGE,1},{ATKSPD,1},{MOVESPD,2},{HEALTH,2}};
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){}
BitRestorer::BitRestorer(PixelGameEngine*pge,vf2d pos,std::vector<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 ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
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]){
@ -54,15 +55,14 @@ 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,SOUNDS);
AttemptToHealOtherAllies(otherUnits);
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,std::vector<std::unique_ptr<Audio>>&SOUNDS){
void BitRestorer::AttemptToHealOtherAllies(std::vector<std::shared_ptr<Unit>>&otherUnits){
std::vector<int>emptyMemoryPositions;
for(auto&u:otherUnits){
if(u.get()!=this&&u->IsFriendly()&&InRange(u)){
@ -75,7 +75,6 @@ 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;
}
}
@ -85,12 +84,12 @@ void BitRestorer::AttemptToHealOtherAllies(std::vector<std::shared_ptr<Unit>>&ot
std::string MemorySwapper::unitName="Memory Swapper";
std::string MemorySwapper::unitDescription="Flips the orientation of all bits of a target around.";
std::vector<Memory> MemorySwapper::resourceCost={{RANGE,3},{ATKSPD,1},{HEALTH,3},{PROCEDURE,3},{MOVESPD,4}};
MemorySwapper::MemorySwapper(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool friendly,bool moveable)
:Unit(pge,MemorySwapper::resourceCost,pos,12,*IMAGES[MEMORY_SWAPPER],CONSTANT::ATTACKER_TARGET_COL,CONSTANT::ATTACKER_ATTACK_COL,friendly,moveable,true){
MemorySwapper::MemorySwapper(PixelGameEngine*pge,vf2d pos,std::vector<Renderable>&IMAGES,bool friendly,bool moveable)
:Unit(pge,MemorySwapper::resourceCost,pos,12,IMAGES[MEMORY_SWAPPER],CONSTANT::ATTACKER_TARGET_COL,CONSTANT::ATTACKER_ATTACK_COL,friendly,moveable,true){
autoAcquireFriendlyTarget=false;
}
void MemorySwapper::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
void MemorySwapper::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
std::vector<bool>oldMemory=victim.memory;
for(int i=0;i<oldMemory.size();i++){
victim.memory[i]=oldMemory[oldMemory.size()-i-1];
@ -124,37 +123,33 @@ 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(SOUNDS);
}
std::string Corrupter::unitName="Corrupter";
std::string Corrupter::unitDescription="Chooses a random bit and negates it on a target.";
std::vector<Memory> Corrupter::resourceCost={{ATKSPD,3},{RANGE,1},{PROCEDURE,8},{MOVESPD,8},{HEALTH,4}};
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){}
Corrupter::Corrupter(PixelGameEngine*pge,vf2d pos,std::vector<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 ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
void Corrupter::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
//Chooses a bit at random and corrupts it.
int randomBit=rand()%victim.memory.size();
if(victim.memory[randomBit]){
RandomHit(SOUNDS);
}
victim.memory[randomBit]=false;
}
std::string MemoryAllocator::unitName="Memory Allocator";
std::string MemoryAllocator::unitDescription="A unit that builds other units.";
std::vector<Memory> MemoryAllocator::resourceCost={{RANGE,1},{ATKSPD,1},{MOVESPD,2},{PROCEDURE,1},{HEALTH,1}};
MemoryAllocator::MemoryAllocator(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool friendly,bool moveable)
:Unit(pge,MemoryAllocator::resourceCost,pos,12,*IMAGES[UNIT_ALLOCATOR],CONSTANT::ATTACKER_TARGET_COL,CONSTANT::ATTACKER_ATTACK_COL,friendly,true,false){
MemoryAllocator::MemoryAllocator(PixelGameEngine*pge,vf2d pos,std::vector<Renderable>&IMAGES,bool friendly,bool moveable)
:Unit(pge,MemoryAllocator::resourceCost,pos,12,IMAGES[UNIT_ALLOCATOR],CONSTANT::ATTACKER_TARGET_COL,CONSTANT::ATTACKER_ATTACK_COL,friendly,true,false){
isAllocator=true;
}
void MemoryAllocator::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
void MemoryAllocator::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
}
void MemoryAllocator::Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::vector<std::shared_ptr<Unit>>&queuedUnits){
void MemoryAllocator::Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS,std::vector<std::unique_ptr<Unit>>&queuedUnits){
if(IsBuilding()){
SetTargetLocation(CONSTANT::UNSELECTED);
target.reset();
@ -163,14 +158,13 @@ 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));
}
}
}
void MemoryAllocator::Draw(TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES){
if(IsBuilding()&&!InFogOfWar()){
void MemoryAllocator::Draw(TileTransformedView&game,std::vector<Renderable>&IMAGES){
if(IsBuilding()){
game.GetPGE()->SetDrawTarget(img.Sprite());
game.GetPGE()->Clear(BLANK);
Renderable&targetImg=buildTransformUnit->GetImage();
@ -178,15 +172,12 @@ void MemoryAllocator::Draw(TileTransformedView&game,std::vector<std::unique_ptr<
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});
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);
}
if(IsAttached()){
game.DrawRotatedDecal(GetGhostPos(),IMAGES[SELECTION_CIRCLE]->Decal(),0,IMAGES[SELECTION_CIRCLE]->Sprite()->Size()/2,vf2d(img.Sprite()->Size())/IMAGES[SELECTION_CIRCLE]->Sprite()->Size(),IsFriendly()?GREEN:RED);
game.DrawRotatedDecal(GetGhostPos(),IMAGES[SELECTION_CIRCLE].Decal(),0,IMAGES[SELECTION_CIRCLE].Sprite()->Size()/2,vf2d(img.Sprite()->Size())/IMAGES[SELECTION_CIRCLE].Sprite()->Size(),WHITE);
}
}
}
@ -194,15 +185,15 @@ void MemoryAllocator::Draw(TileTransformedView&game,std::vector<std::unique_ptr<
std::string RAMBank::unitName="RAM Bank";
std::string RAMBank::unitDescription="Allows for the construction of Memory Allocators.";
std::vector<Memory> RAMBank::resourceCost={{PROCEDURE,25},{HEALTH,16}};
RAMBank::RAMBank(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool friendly)
:Unit(pge,RAMBank::resourceCost,pos,41,*IMAGES[RAM_BANK],WHITE,WHITE,friendly,false
RAMBank::RAMBank(PixelGameEngine*pge,vf2d pos,std::vector<Renderable>&IMAGES,bool friendly)
:Unit(pge,RAMBank::resourceCost,pos,41,IMAGES[RAM_BANK],WHITE,WHITE,friendly,false
,false,false
),randomOffset({util::random(128),util::random(128)}),matrixImg(*IMAGES[MATRIX]),
originalImg(*IMAGES[RAM_BANK]){
img.Create(IMAGES[RAM_BANK]->Sprite()->width,IMAGES[RAM_BANK]->Sprite()->height);
),randomOffset({util::random(128),util::random(128)}),matrixImg(IMAGES[MATRIX]),
originalImg(IMAGES[RAM_BANK]){
img.Create(IMAGES[RAM_BANK].Sprite()->width,IMAGES[RAM_BANK].Sprite()->height);
pge->SetDrawTarget(img.Sprite());
pge->Clear(BLANK);
pge->DrawSprite({0,0},IMAGES[RAM_BANK]->Sprite());
pge->DrawSprite({0,0},IMAGES[RAM_BANK].Sprite());
pge->SetDrawTarget(nullptr);
allocatorManager.colNormal = olc::VERY_DARK_GREEN;
allocatorManager.colHover = olc::GREEN;
@ -210,16 +201,14 @@ RAMBank::RAMBank(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Render
allocatorManager.colDisable = olc::DARK_GREY;
allocatorManager.colBorder = olc::YELLOW;
allocatorManager.colText = olc::WHITE;
allocatorButton = new QuickGUI::ImageButton(allocatorManager,*IMAGES[UNIT_ALLOCATOR],{0.5f,0.5f},pos-vf2d{8,48},{20,20});
isRAMBank=true;
platformStructure=true;
allocatorButton = new QuickGUI::ImageButton(allocatorManager,IMAGES[UNIT_ALLOCATOR],{0.5f,0.5f},pos-vf2d{8,48},{20,20});
}
void RAMBank::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
void RAMBank::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
}
void RAMBank::Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::vector<std::shared_ptr<Unit>>&queuedUnits){
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++){
@ -231,30 +220,27 @@ void RAMBank::Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOU
}
if(!soundStarted){
soundStarted=true;
soundHandle=SOUNDS[int(Sound::HUM)]->Play(GetPos(),0.4,0.4,true);
soundHandle=SOUNDS[Sound::HUM]->Play(GetPos(),0.4,0.4,true);
}
img.Decal()->Update();
pge->SetDrawTarget(nullptr);
}
void RAMBank::DrawHud(TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES){
void RAMBank::DrawHud(TileTransformedView&game,std::vector<Renderable>&IMAGES){
if(IsSelected()){
allocatorManager.DrawDecal(game);
}
}
void RAMBank::Draw(TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES){
void RAMBank::Draw(TileTransformedView&game,std::vector<Renderable>&IMAGES){
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);
}
if(IsAttached()){
game.DrawRotatedDecal(GetGhostPos(),IMAGES[SELECTION_CIRCLE]->Decal(),0,IMAGES[SELECTION_CIRCLE]->Sprite()->Size()/2,vf2d(img.Sprite()->Size())/IMAGES[SELECTION_CIRCLE]->Sprite()->Size(),IsFriendly()?GREEN:RED);
game.DrawRotatedDecal(GetGhostPos(),IMAGES[SELECTION_CIRCLE].Decal(),0,IMAGES[SELECTION_CIRCLE].Sprite()->Size()/2,vf2d(img.Sprite()->Size())/IMAGES[SELECTION_CIRCLE].Sprite()->Size(),WHITE);
}
}
void RAMBank::OnDeath(std::vector<std::unique_ptr<Audio>>&SOUNDS){
SOUNDS[int(Sound::HUM)]->Stop(soundHandle);
void RAMBank::OnDeath(std::map<Sound,std::unique_ptr<Audio>>&SOUNDS){
SOUNDS[Sound::HUM]->Stop(soundHandle);
}
void RAMBank::UpdateGUIState(TileTransformedView&game,Resources&player_resources,Textbox&displayBox,bool&hovered,int totalUsedMemory,int availableMemory){
@ -275,7 +261,7 @@ void RAMBank::UpdateGUIState(TileTransformedView&game,Resources&player_resources
allocatorButton->Enable(buttonEnabled);
}
bool RAMBank::ClickHandled(TileTransformedView&game,Resources&player_resources,std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES){
bool RAMBank::ClickHandled(TileTransformedView&game,Resources&player_resources,std::vector<std::shared_ptr<Unit>>&units,std::vector<Renderable>&IMAGES){
if(allocatorButton->bPressed){
//First try to take one of each.
if(player_resources.atkSpd>0&&player_resources.health>0&&player_resources.moveSpd>0&&player_resources.procedure>0&&player_resources.range>0){
@ -312,15 +298,14 @@ bool RAMBank::ClickHandled(TileTransformedView&game,Resources&player_resources,s
std::string _Platform::unitName="Platform";
std::string _Platform::unitDescription="Anchored to the ground, this unit is an intermediate step for larger units.";
std::vector<Memory> _Platform::resourceCost={{HEALTH,6}};
_Platform::_Platform(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool friendly,bool moveable)
:Unit(pge,_Platform::resourceCost,pos,24,*IMAGES[PLATFORM],CONSTANT::ATTACKER_TARGET_COL,CONSTANT::ATTACKER_ATTACK_COL,friendly,false){
_Platform::_Platform(PixelGameEngine*pge,vf2d pos,std::vector<Renderable>&IMAGES,bool friendly,bool moveable)
:Unit(pge,_Platform::resourceCost,pos,24,IMAGES[PLATFORM],CONSTANT::ATTACKER_TARGET_COL,CONSTANT::ATTACKER_ATTACK_COL,friendly,false){
isPlatform=true;
platformStructure=true;
}
void _Platform::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits ,std::vector<std::unique_ptr<Audio>>&SOUNDS){};
void _Platform::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){};
void _Platform::Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::vector<std::shared_ptr<Unit>>&queuedUnits){
void _Platform::Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS,std::vector<std::unique_ptr<Unit>>&queuedUnits){
if(IsBuilding()){
SetTargetLocation(CONSTANT::UNSELECTED);
target.reset();
@ -329,13 +314,12 @@ 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));
}
}
}
void _Platform::Draw(TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES){
void _Platform::Draw(TileTransformedView&game,std::vector<Renderable>&IMAGES){
if(IsBuilding()){
game.GetPGE()->SetDrawTarget(img.Sprite());
game.GetPGE()->Clear(BLANK);
@ -344,15 +328,12 @@ void _Platform::Draw(TileTransformedView&game,std::vector<std::unique_ptr<Render
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});
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);
}
if(IsAttached()){
game.DrawRotatedDecal(GetGhostPos(),IMAGES[SELECTION_CIRCLE]->Decal(),0,IMAGES[SELECTION_CIRCLE]->Sprite()->Size()/2,vf2d(img.Sprite()->Size())/IMAGES[SELECTION_CIRCLE]->Sprite()->Size(),IsFriendly()?GREEN:RED);
game.DrawRotatedDecal(GetGhostPos(),IMAGES[SELECTION_CIRCLE].Decal(),0,IMAGES[SELECTION_CIRCLE].Sprite()->Size()/2,vf2d(img.Sprite()->Size())/IMAGES[SELECTION_CIRCLE].Sprite()->Size(),WHITE);
}
}
}
@ -360,13 +341,11 @@ void _Platform::Draw(TileTransformedView&game,std::vector<std::unique_ptr<Render
std::string Refresher::unitName="Refresher";
std::string Refresher::unitDescription="Repairs missing bits to surrounding units.";
std::vector<Memory> Refresher::resourceCost={{ATKSPD,3},{RANGE,1},{PROCEDURE,8},{HEALTH,4}};
Refresher::Refresher(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool friendly,bool moveable)
:Unit(pge,Refresher::resourceCost,pos,24,*IMAGES[REFRESHER],CONSTANT::ATTACKER_TARGET_COL,CONSTANT::ATTACKER_ATTACK_COL,friendly,false
,true,false){
platformStructure=true;
}
Refresher::Refresher(PixelGameEngine*pge,vf2d pos,std::vector<Renderable>&IMAGES,bool friendly,bool moveable)
: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 ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
void Refresher::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
target.reset(); //Doesn't acquire a target.
for(auto&u:otherUnits){
if(IsFriendly()==u->IsFriendly()&&InRange(u.get())){
@ -383,25 +362,14 @@ 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.";
std::vector<Memory> Turret::resourceCost={{ATKSPD,4},{RANGE,5},{HEALTH,6},{PROCEDURE,16}};
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){
platformStructure=true;
}
Turret::Turret(PixelGameEngine*pge,vf2d pos,std::vector<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 ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
void Turret::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
if(victim.GetMoveSpd()>0){
for(int i=0;i<victim.moveSpd.size;i++){
if(victim.memory[victim.moveSpd.index+i]){
@ -429,26 +397,15 @@ void Turret::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits ,s
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%";
std::vector<Memory> MemoryGuard::resourceCost={{HEALTH,10},{ATKSPD,4},{RANGE,4},{PROCEDURE,12}};
MemoryGuard::MemoryGuard(PixelGameEngine*pge,vf2d pos,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool friendly,bool moveable)
:Unit(pge,MemoryGuard::resourceCost,pos,24,*IMAGES[MEMORY_GUARD],CONSTANT::ATTACKER_TARGET_COL,CONSTANT::ATTACKER_ATTACK_COL,friendly,false
,true,false){
platformStructure=true;
}
MemoryGuard::MemoryGuard(PixelGameEngine*pge,vf2d pos,std::vector<Renderable>&IMAGES,bool friendly,bool moveable)
: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 ,std::vector<std::unique_ptr<Audio>>&SOUNDS){
void MemoryGuard::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
target.reset(); //Doesn't acquire a target.
for(auto&u:otherUnits){
if(IsFriendly()==u->IsFriendly()&&InRange(u.get())){
@ -456,15 +413,6 @@ 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){
@ -503,7 +451,7 @@ Unit::Unit(PixelGameEngine*pge,std::vector<Memory>memory,vf2d pos,float radius,R
targetingLine.Create(25,24,false,false);
}
void Unit::DrawRangeIndicator(PixelGameEngine*pge,TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES){
void Unit::DrawRangeIndicator(PixelGameEngine*pge,TileTransformedView&game,std::vector<Renderable>&IMAGES){
if(!CanInteractWithAllies()&&!CanInteractWithEnemies())return;
float dist=geom2d::line<float>(game.ScreenToWorld(pge->GetMousePos()),GetGhostPos()).length();
float range=12*(GetRange()+1);
@ -516,7 +464,7 @@ void Unit::DrawRangeIndicator(PixelGameEngine*pge,TileTransformedView&game,std::
} else {
col={0,196,0};
}
game.DrawRotatedDecal(GetGhostPos(),IMAGES[RANGE_INDICATOR]->Decal(),0,IMAGES[RANGE_INDICATOR]->Sprite()->Size()/2,{totalRange/12,totalRange/12},col);
game.DrawRotatedDecal(GetGhostPos(),IMAGES[RANGE_INDICATOR].Decal(),0,IMAGES[RANGE_INDICATOR].Sprite()->Size()/2,{totalRange/12,totalRange/12},col);
}else
if(dist<range*2){
@ -535,23 +483,20 @@ void Unit::DrawRangeIndicator(PixelGameEngine*pge,TileTransformedView&game,std::
}
}
uint8_t transparency=uint8_t((1.f-(dist/(range*2)))*255);
game.DrawRotatedDecal(GetGhostPos(),IMAGES[RANGE_INDICATOR]->Decal(),0,IMAGES[RANGE_INDICATOR]->Sprite()->Size()/2,{totalRange/12,totalRange/12},{col.r,col.g,col.b,transparency});
game.DrawRotatedDecal(GetGhostPos(),IMAGES[RANGE_INDICATOR].Decal(),0,IMAGES[RANGE_INDICATOR].Sprite()->Size()/2,{totalRange/12,totalRange/12},{col.r,col.g,col.b,transparency});
}
}
void Unit::Draw(TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES){
void Unit::Draw(TileTransformedView&game,std::vector<Renderable>&IMAGES){
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);
}
if(IsAttached()){
game.DrawRotatedDecal(GetGhostPos(),IMAGES[SELECTION_CIRCLE]->Decal(),0,IMAGES[SELECTION_CIRCLE]->Sprite()->Size()/2,vf2d(img.Sprite()->Size())/IMAGES[SELECTION_CIRCLE]->Sprite()->Size(),IsFriendly()?GREEN:RED);
game.DrawRotatedDecal(GetGhostPos(),IMAGES[SELECTION_CIRCLE].Decal(),0,IMAGES[SELECTION_CIRCLE].Sprite()->Size()/2,vf2d(img.Sprite()->Size())/IMAGES[SELECTION_CIRCLE].Sprite()->Size(),WHITE);
}
}
void Unit::DrawHud(TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES){}
void Unit::DrawHud(TileTransformedView&game,std::vector<Renderable>&IMAGES){}
void Unit::_DrawHud(TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES,bool unitMetersGreyedOut){
void Unit::_DrawHud(TileTransformedView&game,std::vector<Renderable>&IMAGES){
DrawHud(game,IMAGES);
int initialBarX=ghostPos.x-GetMemorySize()/2*CONSTANT::BAR_SQUARE_SIZE.x-CONSTANT::BAR_SQUARE_SIZE.x/2;
int initialBarY=ghostPos.y-CONSTANT::BAR_SQUARE_SIZE.y-img.Sprite()->height/2-2;
@ -563,16 +508,16 @@ void Unit::_DrawHud(TileTransformedView&game,std::vector<std::unique_ptr<Rendera
col=CONSTANT::HEALTH_COLOR;
}
if(range.index==i&&range.size>0){
col=unitMetersGreyedOut?VERY_DARK_GREY:CONSTANT::RANGE_COLOR;
col=CONSTANT::RANGE_COLOR;
}
if(atkSpd.index==i&&atkSpd.size>0){
col=unitMetersGreyedOut?VERY_DARK_GREY:CONSTANT::ATKSPD_COLOR;
col=CONSTANT::ATKSPD_COLOR;
}
if(moveSpd.index==i&&moveSpd.size>0){
col=unitMetersGreyedOut?VERY_DARK_GREY:CONSTANT::MOVESPD_COLOR;
col=CONSTANT::MOVESPD_COLOR;
}
if(procedure.index==i&&procedure.size>0){
col=unitMetersGreyedOut?VERY_DARK_GREY:CONSTANT::PROCEDURE_COLOR;
col=CONSTANT::PROCEDURE_COLOR;
}
};
@ -582,19 +527,19 @@ void Unit::_DrawHud(TileTransformedView&game,std::vector<std::unique_ptr<Rendera
}
if(GetAtkSpd()>0){
game.FillRectDecal(vf2d{float(initialBarX)+atkSpd.index*CONSTANT::BAR_SQUARE_SIZE.x,
float(initialBarY)}-vf2d{0,1},CONSTANT::BAR_SQUARE_SIZE+vf2d{CONSTANT::BAR_SQUARE_SIZE.x*atkSpd.size-1,2},unitMetersGreyedOut?VERY_DARK_GREY:CONSTANT::ATKSPD_COLOR);
float(initialBarY)}-vf2d{0,1},CONSTANT::BAR_SQUARE_SIZE+vf2d{CONSTANT::BAR_SQUARE_SIZE.x*atkSpd.size-1,2},CONSTANT::ATKSPD_COLOR);
}
if(GetMoveSpd()>0){
game.FillRectDecal(vf2d{float(initialBarX)+moveSpd.index*CONSTANT::BAR_SQUARE_SIZE.x,
float(initialBarY)}-vf2d{0,1},CONSTANT::BAR_SQUARE_SIZE+vf2d{CONSTANT::BAR_SQUARE_SIZE.x*moveSpd.size-1,2},unitMetersGreyedOut?VERY_DARK_GREY:CONSTANT::MOVESPD_COLOR);
float(initialBarY)}-vf2d{0,1},CONSTANT::BAR_SQUARE_SIZE+vf2d{CONSTANT::BAR_SQUARE_SIZE.x*moveSpd.size-1,2},CONSTANT::MOVESPD_COLOR);
}
if(GetProcedure()>0){
game.FillRectDecal(vf2d{float(initialBarX)+procedure.index*CONSTANT::BAR_SQUARE_SIZE.x,
float(initialBarY)}-vf2d{0,1},CONSTANT::BAR_SQUARE_SIZE+vf2d{CONSTANT::BAR_SQUARE_SIZE.x*procedure.size-1,2},unitMetersGreyedOut?VERY_DARK_GREY:CONSTANT::PROCEDURE_COLOR);
float(initialBarY)}-vf2d{0,1},CONSTANT::BAR_SQUARE_SIZE+vf2d{CONSTANT::BAR_SQUARE_SIZE.x*procedure.size-1,2},CONSTANT::PROCEDURE_COLOR);
}
if(GetRange()>0){
game.FillRectDecal(vf2d{float(initialBarX)+range.index*CONSTANT::BAR_SQUARE_SIZE.x,
float(initialBarY)}-vf2d{0,1},CONSTANT::BAR_SQUARE_SIZE+vf2d{CONSTANT::BAR_SQUARE_SIZE.x*range.size-1,2},unitMetersGreyedOut?VERY_DARK_GREY:CONSTANT::RANGE_COLOR);
float(initialBarY)}-vf2d{0,1},CONSTANT::BAR_SQUARE_SIZE+vf2d{CONSTANT::BAR_SQUARE_SIZE.x*range.size-1,2},CONSTANT::RANGE_COLOR);
}
for(int i=0;i<GetMemorySize();i++){
@ -607,31 +552,29 @@ void Unit::_DrawHud(TileTransformedView&game,std::vector<std::unique_ptr<Rendera
}
}
void Unit::DrawUnitDamageStats(PixelGameEngine*pge,TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES){
if(!InFogOfWar()){
if(!target.expired()){
geom2d::line<float>lineToTarget(pos,target.lock()->pos);
lineToTarget.start=lineToTarget.rpoint(GetUnitSize().x/2);
lineToTarget.end=lineToTarget.rpoint(lineToTarget.length()-GetUnitSize().x/4);
util::ApplyMatrixEffect(game.GetPGE(),targetingLine,*IMAGES[TARGETING_LINE],IMAGES[MATRIX]);
game.DrawPartialRotatedDecal(lineToTarget.upoint(0.5),targetingLine.Decal(),lineToTarget.vector().polar().y,{lineToTarget.length()/2,12},{lineShift*10,0},{lineToTarget.length(),24},{1,1},targetLineCol);
} else
if(targetLoc!=CONSTANT::UNSELECTED){
geom2d::line<float>lineToTarget(pos,targetLoc);
lineToTarget.start=lineToTarget.rpoint(GetUnitSize().x/2);
lineToTarget.end=lineToTarget.rpoint(lineToTarget.length()-GetUnitSize().x/4);
util::ApplyMatrixEffect(game.GetPGE(),targetingLine,*IMAGES[TARGETING_LINE],IMAGES[MATRIX]);
game.DrawPartialRotatedDecal(lineToTarget.upoint(0.5),targetingLine.Decal(),lineToTarget.vector().polar().y,{lineToTarget.length()/2,12},{lineShift*10,0},{lineToTarget.length(),24},{1,0.6},CONSTANT::MOVE_LINE_COL);
}
if(!appliedTarget.expired()){
geom2d::line<float>lineToTarget(pos,appliedTarget.lock()->pos);
lineToTarget.start=lineToTarget.rpoint(GetUnitSize().x/2);
lineToTarget.end=lineToTarget.rpoint(lineToTarget.length()-GetUnitSize().x/4);
if(reloadTimer>0){
util::ApplyMatrixEffect(game.GetPGE(),attackingLine,*IMAGES[ATTACKING_LINE],IMAGES[MATRIX]);
float reloadSpd=1.f/(GetAtkSpd()/2.f);
game.DrawPartialRotatedDecal(lineToTarget.upoint(0.5),attackingLine.Decal(),lineToTarget.vector().polar().y,{lineToTarget.length()/2,12},{lineShift*30,0},{lineToTarget.length(),24},{1,1+(attackFailed?-0.3f:(reloadTimer/reloadSpd)*0.25f)},attackFailed?Pixel{192,192,192,130}:Pixel{attackingLineCol.r,attackingLineCol.g,attackingLineCol.b,uint8_t(IsFriendly()?200:160)});
}
void Unit::DrawUnitDamageStats(PixelGameEngine*pge,TileTransformedView&game,std::vector<Renderable>&IMAGES){
if(!target.expired()){
geom2d::line<float>lineToTarget(pos,target.lock()->pos);
lineToTarget.start=lineToTarget.rpoint(GetUnitSize().x/2);
lineToTarget.end=lineToTarget.rpoint(lineToTarget.length()-GetUnitSize().x/4);
util::ApplyMatrixEffect(game.GetPGE(),targetingLine,IMAGES[TARGETING_LINE],IMAGES[MATRIX]);
game.DrawPartialRotatedDecal(lineToTarget.upoint(0.5),targetingLine.Decal(),lineToTarget.vector().polar().y,{lineToTarget.length()/2,12},{lineShift*10,0},{lineToTarget.length(),24},{1,1},targetLineCol);
} else
if(targetLoc!=CONSTANT::UNSELECTED){
geom2d::line<float>lineToTarget(pos,targetLoc);
lineToTarget.start=lineToTarget.rpoint(GetUnitSize().x/2);
lineToTarget.end=lineToTarget.rpoint(lineToTarget.length()-GetUnitSize().x/4);
util::ApplyMatrixEffect(game.GetPGE(),targetingLine,IMAGES[TARGETING_LINE],IMAGES[MATRIX]);
game.DrawPartialRotatedDecal(lineToTarget.upoint(0.5),targetingLine.Decal(),lineToTarget.vector().polar().y,{lineToTarget.length()/2,12},{lineShift*10,0},{lineToTarget.length(),24},{1,0.6},CONSTANT::MOVE_LINE_COL);
}
if(!appliedTarget.expired()){
geom2d::line<float>lineToTarget(pos,appliedTarget.lock()->pos);
lineToTarget.start=lineToTarget.rpoint(GetUnitSize().x/2);
lineToTarget.end=lineToTarget.rpoint(lineToTarget.length()-GetUnitSize().x/4);
if(reloadTimer>0){
util::ApplyMatrixEffect(game.GetPGE(),attackingLine,IMAGES[ATTACKING_LINE],IMAGES[MATRIX]);
float reloadSpd=1.f/(GetAtkSpd()/2.f);
game.DrawPartialRotatedDecal(lineToTarget.upoint(0.5),attackingLine.Decal(),lineToTarget.vector().polar().y,{lineToTarget.length()/2,12},{lineShift*30,0},{lineToTarget.length(),24},{1,1+(attackFailed?-0.3f:(reloadTimer/reloadSpd)*0.25f)},attackFailed?Pixel{192,192,192,130}:Pixel{attackingLineCol.r,attackingLineCol.g,attackingLineCol.b,uint8_t(IsFriendly()?200:160)});
}
}
float dist=geom2d::line<float>(game.ScreenToWorld(pge->GetMousePos()),GetGhostPos()).length();
@ -642,11 +585,11 @@ void Unit::DrawUnitDamageStats(PixelGameEngine*pge,TileTransformedView&game,std:
auto DrawStatDown=[&](Marker&maxStat,int currentStat,vf2d pos,vf2d downDisplayPos,Image img,uint8_t transparency=255){
if(maxStat.size>0){
if(currentStat!=maxStat.size){
game.DrawDecal(this->pos+pos,IMAGES[img]->Decal(),{1,1},currentStat==0?Pixel{192,64,64,transparency}:Pixel{255,255,255,transparency});
game.DrawDecal(this->pos+pos,IMAGES[img].Decal(),{1,1},currentStat==0?Pixel{192,64,64,transparency}:Pixel{255,255,255,transparency});
if(currentStat>0){
game.DrawDecal(this->pos+downDisplayPos,IMAGES[DOWN_ARROW]->Decal(),{1,1},{255,255,255,transparency});
game.DrawDecal(this->pos+downDisplayPos,IMAGES[DOWN_ARROW].Decal(),{1,1},{255,255,255,transparency});
} else {
game.DrawDecal(this->pos+downDisplayPos,IMAGES[RED_X]->Decal(),{1,1},{255,255,255,transparency});
game.DrawDecal(this->pos+downDisplayPos,IMAGES[RED_X].Decal(),{1,1},{255,255,255,transparency});
}
}
}
@ -677,21 +620,7 @@ int Unit::GetBits(Marker&m){
return activeBits;
}
void Unit::_OnDeath(std::vector<std::unique_ptr<Audio>>&SOUNDS){
switch(rand()%3){
case 0:{
SOUNDS[Sound::DEAD1]->Play(GetPos());
}break;
case 1:{
SOUNDS[Sound::DEAD2]->Play(GetPos());
}break;
case 2:{
SOUNDS[Sound::DEAD3]->Play(GetPos());
}break;
}
OnDeath(SOUNDS);
}
void Unit::OnDeath(std::vector<std::unique_ptr<Audio>>&SOUNDS){}
void Unit::OnDeath(std::map<Sound,std::unique_ptr<Audio>>&SOUNDS){}
int Unit::GetHealth(){
return GetBits(health);
@ -723,7 +652,7 @@ void Unit::_RunAI(PixelGameEngine*pge){
RunAI(pge);
}
void Unit::_Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUNDS,Resources&player_resources,Resources&enemy_resources,std::vector<std::shared_ptr<Unit>>&queuedUnits,std::array<float,5>&resourceGainTimer,std::vector<ResourceGainIcon>&resourceGainIcons,std::vector<std::unique_ptr<Renderable>>&IMAGES,GameFlags&flags){
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,std::array<float,5>&resourceGainTimer,std::vector<ResourceGainIcon>&resourceGainIcons,std::vector<Renderable>&IMAGES){
if(!target.expired()){
auto ptrTarget=target.lock();
if(!InRange(ptrTarget)&&CanMove()){
@ -747,76 +676,28 @@ void Unit::_Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUND
}
if(!attachedPoint.expired()){
SetPos(attachedPoint.lock()->pos+vf2d{cos(float(attachedPoint.lock()->rot+PI/2))*16,sin(float(attachedPoint.lock()->rot+PI/2))*16});
collectionTime-=pge->GetElapsedTime();
if(collectionTime<=0){
collectionTime=CONSTANT::COLLECTION_WAIT_TIME;
Resources&targetResource=IsFriendly()?player_resources:enemy_resources;
switch(attachedPoint.lock()->type){
case HEALTH:{
if(!IsFriendly()&&flags.difficulty==2){
targetResource.health+=3;
}
if(!IsFriendly()&&flags.difficulty==1){
targetResource.health++;
}
if(!IsFriendly()&&flags.difficulty==0){
targetResource.health--;
}
targetResource.health++;
}break;
case RANGE:{
if(!IsFriendly()&&flags.difficulty==2){
targetResource.range+=3;
}
if(!IsFriendly()&&flags.difficulty==1){
targetResource.range++;
}
if(!IsFriendly()&&flags.difficulty==0){
targetResource.range--;
}
targetResource.range++;
}break;
case ATKSPD:{
if(!IsFriendly()&&flags.difficulty==2){
targetResource.atkSpd+=3;
}
if(!IsFriendly()&&flags.difficulty==1){
targetResource.atkSpd++;
}
if(!IsFriendly()&&flags.difficulty==0){
targetResource.atkSpd--;
}
targetResource.atkSpd++;
}break;
case MOVESPD:{
if(!IsFriendly()&&flags.difficulty==2){
targetResource.moveSpd+=3;
}
if(!IsFriendly()&&flags.difficulty==1){
targetResource.moveSpd++;
}
if(!IsFriendly()&&flags.difficulty==0){
targetResource.moveSpd--;
}
targetResource.moveSpd++;
}break;
case PROCEDURE:{
if(!IsFriendly()&&flags.difficulty==2){
targetResource.procedure+=3;
}
if(!IsFriendly()&&flags.difficulty==1){
targetResource.procedure++;
}
if(!IsFriendly()&&flags.difficulty==0){
targetResource.procedure--;
}
targetResource.procedure++;
}break;
}
if(!InFogOfWar()){
resourceGainIcons.push_back({IMAGES[RESOURCE].get(),attachedPoint.lock()->type,GetPos()});
}
resourceGainIcons.emplace_back(&IMAGES[RESOURCE],attachedPoint.lock()->type,GetPos());
}
}
@ -920,7 +801,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,std::vector<std::unique_ptr<Audio>>&SOUNDS){
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<Renderable>&IMAGES){
if(reloadTimer>0)return;
std::weak_ptr<Unit>finalTarget;
if(!unit.expired()){
@ -939,59 +820,41 @@ 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,SOUNDS); //Call the parent function first, followed by the child.
_Attack(attacker,finalTarget,otherUnits); //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});
debuffIcons.emplace_back(&IMAGES[RLD_ICON],&IMAGES[RED_X],finalTarget.lock()->GetPos()-vf2d{util::random(12)-6,4});
}
if(hadMoveSpd&&finalTarget.lock()->GetMoveSpd()==0){
debuffIcons.emplace_back(IMAGES[SPD_ICON].get(),IMAGES[RED_X].get(),finalTarget.lock()->GetPos()-vf2d{util::random(12)-6,4});
debuffIcons.emplace_back(&IMAGES[SPD_ICON],&IMAGES[RED_X],finalTarget.lock()->GetPos()-vf2d{util::random(12)-6,4});
}
if(hadRange&&finalTarget.lock()->GetRange()==0){
debuffIcons.emplace_back(IMAGES[RNG_ICON].get(),IMAGES[RED_X].get(),finalTarget.lock()->GetPos()-vf2d{util::random(12)-6,4});
debuffIcons.emplace_back(&IMAGES[RNG_ICON],&IMAGES[RED_X],finalTarget.lock()->GetPos()-vf2d{util::random(12)-6,4});
}
if(hadProcedure&&finalTarget.lock()->GetProcedure()==0){
debuffIcons.emplace_back(IMAGES[PRC_ICON].get(),IMAGES[RED_X].get(),finalTarget.lock()->GetPos()-vf2d{util::random(12)-6,4});
debuffIcons.emplace_back(&IMAGES[PRC_ICON],&IMAGES[RED_X],finalTarget.lock()->GetPos()-vf2d{util::random(12)-6,4});
}
}
}
}
void Unit::Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUNDS,std::vector<std::shared_ptr<Unit>>&queuedUnits){}
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){}
void Unit::_Attacked(std::weak_ptr<Unit>attacker,std::vector<std::shared_ptr<Unit>>&otherUnits){
void Unit::_Attacked(std::weak_ptr<Unit>attacker){
Attacked(attacker);
if(attacker.lock()->IsFriendly()!=IsFriendly()&&CanInteractWithEnemies()){
SetTargetUnit(attacker);
}
if(!IsFriendly()&&!attacker.lock()->IsFriendly()&&!attacker.lock()->CanInteractWithAllies()){
attacker.lock()->SetTargetLocation(attacker.lock()->GetPos()); //This effectively negates enemies targeting each other for attacking if they're not supposed to. Somehow this occurs sometimes.
}
if(!IsFriendly()&&attacker.lock()->IsFriendly()!=IsFriendly()){
for(auto&u:otherUnits){
if(this!=u.get()&&!u->IsFriendly()&&u->GetCurrentTarget().expired()&&u->CanMove()&&!u->IsAllocator()){
geom2d::line<float>distLine={GetPos(),u->GetPos()};
if(distLine.length()<320){
if(u->CanInteractWithEnemies()){
u->SetTargetUnit(attacker);
}else
if(u->CanInteractWithAllies()){
u->SetTargetLocation(GetPos());
}
}
}
}
}
}
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){
void Unit::_Attack(std::weak_ptr<Unit>attacker,std::weak_ptr<Unit>finalTarget,std::vector<std::shared_ptr<Unit>>&otherUnits){
if(GetProcedure()>0&&GetAtkSpd()>0){
attackFailed=false;
float procChance=float(GetProcedure())/procedure.size;
if(util::random(1)>=1-procChance){
Attack(*finalTarget.lock(),otherUnits,SOUNDS);
finalTarget.lock()->_Attacked(attacker,otherUnits);
Attack(*finalTarget.lock(),otherUnits);
finalTarget.lock()->_Attacked(attacker);
reloadTimer=1.f/(GetAtkSpd()/2.f);
if(GetCurrentTarget().expired()&&!IsFriendly()){
if(finalTarget.lock()->IsFriendly()!=IsFriendly()&&CanInteractWithEnemies()){
@ -1081,7 +944,7 @@ Pixel Unit::GetUnitColor(){
}
}
bool Unit::ClickHandled(TileTransformedView&game,Resources&player_resources,std::vector<std::shared_ptr<Unit>>&units,std::vector<std::unique_ptr<Renderable>>&IMAGES){
bool Unit::ClickHandled(TileTransformedView&game,Resources&player_resources,std::vector<std::shared_ptr<Unit>>&units,std::vector<Renderable>&IMAGES){
return false;
};
@ -1091,14 +954,7 @@ bool Unit::IsAllocator(){
return isAllocator&&attachedPoint.expired()&&buildTime<=0;
}
void Unit::SetBuildUnit(float buildTime,std::shared_ptr<Unit>finalUnit,std::vector<std::unique_ptr<Audio>>&SOUNDS){
if(this->IsAllocator()){
SOUNDS[Sound::SMALLBUILD]->Play(GetPos());
} else
if(this->IsPlatform()){
SOUNDS[Sound::BIGBUILD]->Play(GetPos());
}
//Once the units start building they aren't considered allocators/platforms anymore, must do it before.
void Unit::SetBuildUnit(float buildTime,std::unique_ptr<Unit>finalUnit){
this->buildTime=buildTime;
this->buildTransformUnit=std::move(finalUnit);
}
@ -1130,11 +986,3 @@ bool Unit::IsAttached(){
Unit*Unit::GetBuildUnit(){
return buildTransformUnit.get();
}
bool Unit::IsRAMBank(){
return isRAMBank;
}
bool Unit::IsPlatformStructure(){
return platformStructure;
}

@ -8,12 +8,12 @@
#include "olcPGEX_AudioSource.h"
#include "DebuffIcon.h"
#include "CollectionPoint.h"
#include "MemoryType.h"
#include "Resources.h"
#include "Textbox.h"
#include "Memory.h"
#include "GameFlags.h"
#include "olcPGEX_QuickGUI.h"
class Textbox;
enum class UnitType{
LeftShifter,
RightShifter,
@ -33,11 +33,15 @@ struct Marker{
size_t size;
};
struct Memory{
MemoryType type;
int size;
};
struct Unit{
friend class Scenario;
public:
Unit(PixelGameEngine*pge,std::vector<Memory>memory,vf2d pos,float radius,Renderable&img,Pixel targetLineColor,Pixel attackingLineColor,bool friendly=false,bool moveable=true,bool friendlyInteractable=false,bool enemyInteractable=true);
virtual~Unit();
virtual ~Unit();
int GetHealth();
int GetRange();
int GetAtkSpd();
@ -47,13 +51,12 @@ public:
std::vector<bool>memory;
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,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);
void _OnDeath(std::vector<std::unique_ptr<Audio>>&SOUNDS);
virtual void OnDeath(std::vector<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::vector<Renderable>&IMAGES);
virtual void DrawHud(TileTransformedView&game,std::vector<Renderable>&IMAGES);
void _DrawHud(TileTransformedView&game,std::vector<Renderable>&IMAGES);
virtual void OnDeath(std::map<Sound,std::unique_ptr<Audio>>&SOUNDS);
bool IsFriendly();
bool IsSelected();
void Select();
@ -64,47 +67,43 @@ 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,std::vector<std::unique_ptr<Audio>>&SOUNDS);
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<Renderable>&IMAGES);
bool InFogOfWar();
bool GhostInFogOfWar();
void HideGhost();
vf2d GetGhostPos();
void _Update(PixelGameEngine*pge,std::vector<std::unique_ptr<Audio>>&SOUNDS,Resources&player_resources,Resources&enemy_resources,std::vector<std::shared_ptr<Unit>>&queuedUnits,std::array<float,5>&resourceGainTimer,std::vector<ResourceGainIcon>&resourceGainIcons,std::vector<std::unique_ptr<Renderable>>&IMAGES,GameFlags&flags);
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,std::array<float,5>&resourceGainTimer,std::vector<ResourceGainIcon>&resourceGainIcons,std::vector<Renderable>&IMAGES);
bool IsMoveable();
void DrawRangeIndicator(PixelGameEngine*pge,TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES);
void DrawRangeIndicator(PixelGameEngine*pge,TileTransformedView&game,std::vector<Renderable>&IMAGES);
bool CanInteractWithEnemies();
bool CanInteractWithAllies();
Renderable&GetImage();
virtual void RunAI(PixelGameEngine*pge);
void _RunAI(PixelGameEngine*pge);
virtual void Attacked(std::weak_ptr<Unit>attacker);
void _Attacked(std::weak_ptr<Unit>attacker,std::vector<std::shared_ptr<Unit>>&otherUnits);
void _Attacked(std::weak_ptr<Unit>attacker);
std::weak_ptr<Unit>GetCurrentTarget();
void DrawUnitDamageStats(PixelGameEngine*pge,TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES);
void DrawUnitDamageStats(PixelGameEngine*pge,TileTransformedView&game,std::vector<Renderable>&IMAGES);
bool AutoAcquiresFriendlyTargets();
bool CanMove();
void SetTargetCollectionPoint(std::weak_ptr<CollectionPoint>targetCP,std::weak_ptr<Unit>self_ptr);
Pixel GetUnitColor();
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.
virtual bool ClickHandled(TileTransformedView&game,Resources&player_resources,std::vector<std::shared_ptr<Unit>>&units,std::vector<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,std::vector<std::unique_ptr<Audio>>&SOUNDS);
void SetBuildUnit(float buildTime,std::unique_ptr<Unit>finalUnit);
bool IsBuilding();
void SetGuardTime(float time);
bool IsGuarded();
void SaveMemory();
bool IsPlatform();
bool IsAttached();
bool IsRAMBank();
void RandomHit(std::vector<std::unique_ptr<Audio>>&SOUNDS); //3 of chance odds of making a sound.
Unit*GetBuildUnit();
Marker health={};
Marker range={};
Marker atkSpd={};
Marker moveSpd={};
Marker procedure={};
bool platformStructure=false;
bool IsPlatformStructure();
std::vector<bool>& operator <<=(const int n){
for(int i=0;i<GetMemorySize()-1;i++){
@ -135,9 +134,8 @@ protected:
bool autoAcquireFriendlyTarget=true;
bool isAllocator=false;
bool isPlatform=false;
std::shared_ptr<Unit>buildTransformUnit;
std::unique_ptr<Unit>buildTransformUnit;
float buildTime=0;
bool isRAMBank=false;
private:
Renderable targetingLine;
Renderable attackingLine;
@ -148,7 +146,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,std::vector<std::unique_ptr<Audio>>&SOUNDS);
void _Attack(std::weak_ptr<Unit>attacker,std::weak_ptr<Unit>finalTarget,std::vector<std::shared_ptr<Unit>>&otherUnits);
bool moveable=true;
bool friendlyInteractable=false;
bool enemyInteractable=true;
@ -164,51 +162,57 @@ 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,std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
LeftShifter(PixelGameEngine*pge,vf2d pos,std::vector<Renderable>&IMAGES,bool friendly=false,bool moveable=true);
~LeftShifter();
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
static std::vector<Memory> resourceCost;
static std::string unitName;
static std::string unitDescription;
};
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,std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
RightShifter(PixelGameEngine*pge,vf2d pos,std::vector<Renderable>&IMAGES,bool friendly=false,bool moveable=true);
~RightShifter();
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
static std::vector<Memory> resourceCost;
static std::string unitName;
static std::string unitDescription;
};
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,std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
void AttemptToHealOtherAllies(std::vector<std::shared_ptr<Unit>>&otherUnits,std::vector<std::unique_ptr<Audio>>&SOUNDS);
BitRestorer(PixelGameEngine*pge,vf2d pos,std::vector<Renderable>&IMAGES,bool friendly=false,bool moveable=true);
~BitRestorer();
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
void AttemptToHealOtherAllies(std::vector<std::shared_ptr<Unit>>&otherUnits);
static std::vector<Memory> resourceCost;
static std::string unitName;
static std::string unitDescription;
};
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,std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
MemorySwapper(PixelGameEngine*pge,vf2d pos,std::vector<Renderable>&IMAGES,bool friendly=false,bool moveable=true);
~MemorySwapper();
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
static std::vector<Memory> resourceCost;
static std::string unitName;
static std::string unitDescription;
};
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,std::vector<std::unique_ptr<Audio>>&SOUNDS)override;
Corrupter(PixelGameEngine*pge,vf2d pos,std::vector<Renderable>&IMAGES,bool friendly=false,bool moveable=true);
~Corrupter();
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
static std::vector<Memory> resourceCost;
static std::string unitName;
static std::string unitDescription;
};
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,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;
MemoryAllocator(PixelGameEngine*pge,vf2d pos,std::vector<Renderable>&IMAGES,bool friendly=false,bool moveable=true);
~MemoryAllocator();
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::vector<Renderable>&IMAGES)override;
static std::vector<Memory> resourceCost;
static std::string unitName;
static std::string unitDescription;
@ -220,63 +224,56 @@ struct RAMBank:Unit{
Renderable&originalImg;
Renderable&matrixImg;
bool soundStarted=false;
int soundHandle=-1;
int soundHandle;
QuickGUI::Manager allocatorManager;
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,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;
RAMBank(PixelGameEngine*pge,vf2d pos,std::vector<Renderable>&IMAGES,bool friendly=false);
~RAMBank();
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::vector<Renderable>&IMAGES)override;
void OnDeath(std::map<Sound,std::unique_ptr<Audio>>&SOUNDS)override;
bool ClickHandled(TileTransformedView&game,Resources&player_resources,std::vector<std::shared_ptr<Unit>>&units,std::vector<Renderable>&IMAGES)override;
void UpdateGUIState(TileTransformedView&game,Resources&player_resources,Textbox&displayBox,bool&hovered,int totalUsedMemory,int availableMemory)override;
void DrawHud(TileTransformedView&game,std::vector<std::unique_ptr<Renderable>>&IMAGES)override;
void DrawHud(TileTransformedView&game,std::vector<Renderable>&IMAGES)override;
static std::vector<Memory> resourceCost;
static std::string unitName;
static std::string unitDescription;
};
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,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;
_Platform(PixelGameEngine*pge,vf2d pos,std::vector<Renderable>&IMAGES,bool friendly=false,bool moveable=true);
~_Platform();
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)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::vector<Renderable>&IMAGES)override;
static std::vector<Memory> resourceCost;
static std::string unitName;
static std::string unitDescription;
};
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 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;
MemoryGuard(PixelGameEngine*pge,vf2d pos,std::vector<Renderable>&IMAGES,bool friendly=false,bool moveable=true);
~MemoryGuard();
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)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 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;
Refresher(PixelGameEngine*pge,vf2d pos,std::vector<Renderable>&IMAGES,bool friendly=false,bool moveable=true);
~Refresher();
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)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 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;
Turret(PixelGameEngine*pge,vf2d pos,std::vector<Renderable>&IMAGES,bool friendly=false,bool moveable=true);
~Turret();
void Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits)override;
static std::vector<Memory> resourceCost;
static std::string unitName;
static std::string unitDescription;

File diff suppressed because it is too large Load Diff

@ -5,7 +5,6 @@
#include "olcPGEX_AudioListener.h"
#include "olcPGEX_AudioSource.h"
#include "olcPGEX_SplashScreen.h"
#include "olcPGEX_QuickGUI.h"
#include "Unit.h"
#include "Constant.h"
#include "Image.h"
@ -16,8 +15,6 @@
#include "Resources.h"
#include "Textbox.h"
#include "Level.h"
#include "GameFlags.h"
#include "GameState.h"
struct Letter{
vf2d pos;
@ -33,36 +30,29 @@ public:
#endif
vi2d WORLD_SIZE={64,64};
std::vector<std::shared_ptr<Unit>>queuedUnits;
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;
std::vector<DebuffIcon>debuffIcons;
std::vector<ResourceGainIcon>resourceGainIcons;
std::vector<Scenario*>scenarios;
std::vector<Renderable>IMAGES;
std::map<Sound,std::unique_ptr<Audio>>SOUNDS;
olcPGEX_AudioListener AL;
Audio*bgm=nullptr;
int bgm_handle=-1;
Resources player_resources,player_prev_resources,player_display_resources,enemy_resources;
TileTransformedView gametv;
Textbox unitCreationBox,testBox,memoryAllocatorBox,platformCreationBox,restartBox;
Textbox unitCreationBox,testBox,memoryAllocatorBox,platformCreationBox;
Level*currentLevel;
float gameplayTime;
int gameSeconds;
int audioMode=0; //0=Play everything, 1=Play sound effects, 2=Everything off.
std::map<LevelName,Level>levelData;
QuickGUI::Manager mainMenu;
QuickGUI::TransparentButton*campaignStartButton;
QuickGUI::TransparentButton*audioToggleButton;
QuickGUI::TransparentButton*difficultyToggleButton;
QuickGUI::TransparentButton*exitGameButton;
QuickGUI::Manager restartManager;
QuickGUI::TransparentImageButton*restartButton;
QuickGUI::Manager unitCreationList;
QuickGUI::ImageButton*leftShifterButton;
QuickGUI::ImageButton*rightShifterButton;
@ -91,37 +81,14 @@ public:
float memoryDisplayDelay=0;
bool memoryIncreased=true;
float memoryChangeTimer=2;
float levelForegroundFade=0;
LevelName levelToLoad;
bool reloadLevel=false;
bool restartButtonHeldDown=false;
float restartButtonHoldTime=0;
GameState state=GameState::MAIN_MENU;
float nextColorChange=10;
std::array<Pixel,7>colorChangeOptions={VERY_DARK_BLUE,VERY_DARK_CYAN,VERY_DARK_GREEN,VERY_DARK_GREY,VERY_DARK_MAGENTA,VERY_DARK_RED,VERY_DARK_YELLOW};
Pixel currentBackCol;
Pixel newCol;
float transition=0;
float flickerAmt=1;
float arrowScroll=0;
Renderable attackingLineModified;
Renderable titleScreenText;
float titleScreenY=-200;
float textOrientationY=0;
float textOrientationX=0;
int currentScenario=0;
GameFlags flags;
float flashTimer=0;
Textbox completedBox;
Textbox creditsBox;
std::string objective="";
bool unitMetersGreyedOut=false; //If true, all but health meters show up as dark grey.
bool playerInControl=true;
Renderable HOODED_FIGURE_IMG;
Renderable SPOOK_HOODED_FIGURE_IMG;
vf2d randomBackgroundOffset;
vf2d startingDragPos=CONSTANT::UNSELECTED;
void HandleGUIDisplay();
void HandleDraggingSelection();
void DrawSelectionRectangle();
void HandleRightClickMove();
@ -151,11 +118,6 @@ public:
void DrawSystemMemoryBar(float fElapsedTime);
void CalculateUsedMemory();
void InitializeScenarios();
void PerformLevelTransition(float fElapsedTime);
void RestartLevel();
void HandleRestartButton(float fElapsedTime);
void DrawCurvedTexture(vf2d offset,vf2d size,Decal*decal,vf2d texOffset,Pixel col=WHITE,float curveThickness=0.8);
std::string DisplayTime(int gameSeconds);
public:
VirusAttack();
@ -164,5 +126,4 @@ public:
bool OnUserCreate() override;
bool OnUserUpdate(float fElapsedTime) override;
bool OnUserDestroy() override;
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 772 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 576 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

@ -1,2 +1,2 @@
~\Documents\emsdk\emsdk_env.ps1 activate latest
em++ -std=c++20 -O2 -s ALLOW_MEMORY_GROWTH=1 -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_LIBPNG=1 -s USE_SDL_MIXER=2 -sSTACK_SIZE=10MB $(Get-ChildItem *.cpp) soloud.o -o pge.html --preload-file assets
em++ -std=c++20 -s ALLOW_MEMORY_GROWTH=1 -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_LIBPNG=1 -s USE_SDL_MIXER=2 -sSTACK_SIZE=5MB $(Get-ChildItem *.cpp) soloud.o -o pge.html --preload-file assets

@ -83,8 +83,10 @@
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>soloud_static.lib;sdl2.lib;sdl2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
<StackReserveSize>2000000</StackReserveSize>
<HeapReserveSize>2000000</HeapReserveSize>
<HeapReserveSize>40000000</HeapReserveSize>
<HeapCommitSize>40000000</HeapCommitSize>
<StackReserveSize>40000000</StackReserveSize>
<StackCommitSize>40000000</StackCommitSize>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -104,8 +106,10 @@
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>soloud_static.lib;sdl2.lib;sdl2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
<StackReserveSize>2000000</StackReserveSize>
<HeapReserveSize>2000000</HeapReserveSize>
<HeapReserveSize>40000000</HeapReserveSize>
<HeapCommitSize>40000000</HeapCommitSize>
<StackReserveSize>40000000</StackReserveSize>
<StackCommitSize>40000000</StackCommitSize>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -121,8 +125,10 @@
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>soloud_static.lib;sdl2.lib;sdl2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
<StackReserveSize>2000000</StackReserveSize>
<HeapReserveSize>2000000</HeapReserveSize>
<HeapReserveSize>40000000</HeapReserveSize>
<HeapCommitSize>40000000</HeapCommitSize>
<StackReserveSize>40000000</StackReserveSize>
<StackCommitSize>40000000</StackCommitSize>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -142,8 +148,10 @@
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>soloud_static.lib;sdl2.lib;sdl2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
<StackReserveSize>2000000</StackReserveSize>
<HeapReserveSize>2000000</HeapReserveSize>
<HeapReserveSize>40000000</HeapReserveSize>
<HeapCommitSize>40000000</HeapCommitSize>
<StackReserveSize>40000000</StackReserveSize>
<StackCommitSize>40000000</StackCommitSize>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
@ -151,11 +159,8 @@
<ClInclude Include="Constant.h" />
<ClInclude Include="DeathAnimation.h" />
<ClInclude Include="DebuffIcon.h" />
<ClInclude Include="GameFlags.h" />
<ClInclude Include="GameState.h" />
<ClInclude Include="Image.h" />
<ClInclude Include="Level.h" />
<ClInclude Include="Memory.h" />
<ClInclude Include="MemoryType.h" />
<ClInclude Include="olcPGEX_AudioListener.h" />
<ClInclude Include="olcPGEX_AudioSource.h" />

@ -99,15 +99,6 @@
<ClInclude Include="Scenario.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GameState.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Memory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GameFlags.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="VirusAttack.cpp">

@ -68,7 +68,7 @@ class olcPGEX_AudioSource : public olc::PGEX
{
public:
// Pointer to the Audio Listener for this object
olcPGEX_AudioListener* AL=nullptr;
olcPGEX_AudioListener* AL;
// Handle for this particular copy of the sound
int handle = 255;
@ -104,7 +104,7 @@ public:
// Instruct Audio Listener to load this sound (if not loaded already)
void LoadAudioSample(int ID, const char* fileName);
int PlayCentered(float speed = 1.0f, float vol = 1.0f, bool looping = false, bool paused = false,bool bgm=false);
void PlayCentered(float speed = 1.0f, float vol = 1.0f, bool looping = false, bool paused = false);
// Play the Audio Sample, with given parameters
int Play(vf2d pos, float speed = 1.0f, float vol = 1.0f, bool looping = false, bool paused = false);
@ -122,7 +122,6 @@ public:
// Adjust Volume
void SetVolume(float vol, float minVol = 0.0f, float maxVol = 1.0f);
void SetVolume(int handle,float vol);
// Set Default Parameters
void SetDefaults(float speed, float vol, float minVol, float maxVol, bool looping);
@ -141,10 +140,8 @@ void olcPGEX_AudioSource::LoadAudioSample(int ID, const char* fileName)
AL->LoadAudioSample(ID, fileName);
}
int olcPGEX_AudioSource::PlayCentered(float speed, float vol, bool looping, bool paused,bool bgm)
void olcPGEX_AudioSource::PlayCentered(float speed, float vol, bool looping, bool paused)
{
if(bgm&&!AL->bMusicOn)return -1;
if(!bgm&&!AL->bSoundOn)return -1;
// Set parameters
fPlaySpeed = speed;
fVolume = vol;
@ -161,12 +158,10 @@ int olcPGEX_AudioSource::PlayCentered(float speed, float vol, bool looping, bool
// Update Play status
bIsPlaying = true;
return handle;
}
int olcPGEX_AudioSource::Play(vf2d pos, float speed, float vol, bool looping, bool paused)
{
if(!AL->bSoundOn||isnan(pos.x)||isnan(pos.y))return -1;
// Set parameters
fPlaySpeed = speed;
fVolume = vol*std::max(0.f,abs(1-std::min(1.0f,(AL->GetDistance(pos)/1024.f))));
@ -203,9 +198,7 @@ void olcPGEX_AudioSource::Pause(bool pauseState)
void olcPGEX_AudioSource::Stop(int handle)
{
// Use the Audio Listener to stop the sound
if(handle!=-1){
AL->soloud.stop(handle);
}
AL->soloud.stop(handle);
}
void olcPGEX_AudioSource::Stop()
@ -238,15 +231,6 @@ void olcPGEX_AudioSource::ModulateAudio(float minPlaySpeed, float maxPlaySpeed,
AL->soloud.setRelativePlaySpeed(handle, fPlaySpeed);
}
void olcPGEX_AudioSource::SetVolume(int handle,float vol)
{
// Set volume
fVolume = vol;
// Instruct the Audio Listener to apply the volume change
AL->soloud.setVolume(handle, fVolume);
}
void olcPGEX_AudioSource::SetVolume(float vol, float minVol, float maxVol)
{
// Set volume

@ -252,31 +252,6 @@ namespace olc::QuickGUI
void DrawDecal(PixelGameEngine*pge) override;
};
// Creates a Button Control - a clickable, labelled rectangle
class TransparentButton : public Button
{
public:
TransparentButton(olc::QuickGUI::Manager& manager, // Associate with a Manager
const std::string& text, // Text to display
const olc::vf2d& pos, // Location of button top-left
const olc::vf2d& size, // Location of button top-left
const Pixel& hoverCol); // Size of button
public:
// Position of button
olc::vf2d vPos;
// Size of button
olc::vf2d vSize;
// Text displayed on button
std::string sText;
Pixel hoverCol;
public: // BaseControl overrides
void Draw(TileTransformedView&pge) override;
void DrawDecal(TileTransformedView&pge) override;
void DrawDecal(PixelGameEngine*pge) override;
};
// Creates a Button Control - a clickable, labelled rectangle
class CheckBox : public Button
{
@ -315,27 +290,6 @@ namespace olc::QuickGUI
void DrawDecal(PixelGameEngine*pge) override;
};
class TransparentImageButton : public ImageButton
{
public:
TransparentImageButton(olc::QuickGUI::Manager& manager, // Associate with a Manager
const olc::Renderable &icon, // Text to display
const olc::Renderable &iconHover, // Text to display
const olc::vf2d& iconScale,
const olc::vf2d& pos, // Location of button top-left
const olc::vf2d& size); // Size of button
public:
const olc::Renderable& pIcon;
const olc::Renderable& pIconHover;
olc::vf2d iconScale;
public:
void Draw(TileTransformedView&pge) override;
void DrawDecal(TileTransformedView&pge) override;
void DrawDecal(PixelGameEngine*pge) override;
};
class ImageCheckBox : public ImageButton
{
public:
@ -796,9 +750,8 @@ namespace olc::QuickGUI
vMouse.y >= vPos.y && vMouse.y < vPos.y + vSize.y;
bPressed = false;
bReleased = false;
if (m_state == State::Disabled || !bVisible) {
if (m_state == State::Disabled || !bVisible)
return;
}
float fElapsedTime = pge->GetElapsedTime();
@ -913,40 +866,6 @@ namespace olc::QuickGUI
}
#pragma endregion
#pragma region TransparentButton
TransparentButton::TransparentButton(olc::QuickGUI::Manager& manager, const std::string& text, const olc::vf2d& pos, const olc::vf2d& size,const Pixel& hoverCol)
: Button(manager,text,pos,size),hoverCol(hoverCol)
{
vPos = pos; vSize = size; sText = text;
}
void TransparentButton::Draw(TileTransformedView&pge)
{
if (!bVisible)
return;
pge.DrawRect(vPos, vSize - olc::vf2d(1, 1), m_manager.colBorder);
olc::vf2d vText = pge.GetPGE()->GetTextSize(sText);
//pge.DrawShadowString(vPos + (vSize - vText) * 0.5f, sText, m_manager.colText,{1,1},olc::PixelLerp(m_manager.colText, hoverCol, m_fTransition));
}
void TransparentButton::DrawDecal(TileTransformedView&pge)
{
if (!bVisible)
return;
olc::vf2d vText = pge.GetPGE()->GetTextSizeProp(sText);
pge.DrawShadowStringPropDecal(vPos + (vSize - vText) * 0.5f, sText, m_manager.colText,olc::PixelLerp(BLACK, hoverCol, m_fTransition));
}
void TransparentButton::DrawDecal(PixelGameEngine*pge)
{
if (!bVisible)
return;
olc::vf2d vText = pge->GetTextSizeProp(sText);
pge->DrawShadowStringPropDecal(vPos + (vSize - vText) * 0.5f, sText, m_manager.colText,olc::PixelLerp(BLACK, hoverCol, m_fTransition));
}
#pragma endregion
#pragma region ImageButton
ImageButton::ImageButton(olc::QuickGUI::Manager& manager, const olc::Renderable& icon, const olc::vf2d& iconScale, const olc::vf2d& pos, const olc::vf2d& size)
@ -974,43 +893,6 @@ namespace olc::QuickGUI
};
#pragma endregion
#pragma region TransparentImageButton
TransparentImageButton::TransparentImageButton(olc::QuickGUI::Manager& manager, const olc::Renderable& icon, const olc::Renderable& iconHover, const olc::vf2d& iconScale, const olc::vf2d& pos, const olc::vf2d& size)
: ImageButton(manager, icon, iconScale, pos, size), pIcon(icon), pIconHover(iconHover), iconScale(iconScale)
{
}
void TransparentImageButton::Draw(TileTransformedView&pge)
{
if (!bVisible) return;
//Button::Draw(pge);
if(bHover){
pge.DrawSprite(vPos + olc::vi2d(4, 4), pIconHover.Sprite());
} else {
pge.DrawSprite(vPos + olc::vi2d(4, 4), pIcon.Sprite());
}
}
void TransparentImageButton::DrawDecal(TileTransformedView&pge){
if (!bVisible) return;
if(bHover){
pge.DrawDecal(vPos + olc::vi2d(4, 4), pIconHover.Decal(), iconScale,m_state!=State::Disabled?WHITE:WHITE/4);
} else {
pge.DrawDecal(vPos + olc::vi2d(4, 4), pIcon.Decal(), iconScale,m_state!=State::Disabled?WHITE:WHITE/4);
}
}
void TransparentImageButton::DrawDecal(PixelGameEngine*pge){
if (!bVisible) return;
if(bHover){
pge->DrawDecal(vPos + olc::vi2d(4, 4), pIconHover.Decal(), iconScale,m_state!=State::Disabled?WHITE:WHITE/4);
} else {
pge->DrawDecal(vPos + olc::vi2d(4, 4), pIcon.Decal(), iconScale,m_state!=State::Disabled?WHITE:WHITE/4);
}
};
#pragma endregion
#pragma region ImageCheckBox
ImageCheckBox::ImageCheckBox(olc::QuickGUI::Manager& manager, const olc::Renderable& gfx, const bool check, const olc::vf2d& pos, const olc::vf2d& size)

@ -210,8 +210,8 @@ namespace olc
pge->DrawPartialDecal(vScale * vBoom[y * spr.Sprite()->width + x].first * 2.0f, spr.Decal(), olc::vf2d(x, y), { 1, 1 }, vScale * 2.0f, olc::PixelF(1.0f, 1.0f, 1.0f, std::min(1.0f, std::max(4.0f - fParticleTime, 0.0f))));
}
olc::vi2d vSize = pge->GetTextSizeProp("Copyright OneLoneCoder.com 2023");
pge->DrawStringPropDecal(olc::vf2d(float(pge->ScreenWidth()/2) - vSize.x/2, float(pge->ScreenHeight()) - vSize.y * 3.0f), "Copyright OneLoneCoder.com 2023", olc::PixelF(1.0f, 1.0f, 1.0f, 0.5f), olc::vf2d(1.0, 2.0f));
olc::vi2d vSize = pge->GetTextSizeProp("Copyright OneLoneCoder.com 2022");
pge->DrawStringPropDecal(olc::vf2d(float(pge->ScreenWidth()/2) - vSize.x/2, float(pge->ScreenHeight()) - vSize.y * 3.0f), "Copyright OneLoneCoder.com 2022", olc::PixelF(1.0f, 1.0f, 1.0f, 0.5f), olc::vf2d(1.0, 2.0f));
return true;
}

@ -180,7 +180,6 @@ namespace olc
// Draws a multiline string as a decal, with tiniting and scaling
void DrawStringDecal(const olc::vf2d& pos, const std::string& sText, const olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f });
void DrawShadowStringDecal(const olc::vf2d & pos, const std::string & sText, const olc::Pixel col=olc::WHITE, const olc::Pixel shadowCol=olc::BLACK, const olc::vf2d & scale={1,1}, const float shadowSizeFactor=1);
void DrawShadowStringPropDecal(const olc::vf2d & pos, const std::string & sText, const olc::Pixel col=olc::WHITE, const olc::Pixel shadowCol=olc::BLACK, const olc::vf2d & scale={1,1}, const float shadowSizeFactor=1);
void DrawStringPropDecal(const olc::vf2d& pos, const std::string& sText, const olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f });
// Draws a single shaded filled rectangle as a decal
void FillRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col = olc::WHITE);
@ -634,11 +633,6 @@ namespace olc
pge->DrawShadowStringDecal(WorldToScreen(pos), sText, col, shadowCol, scale * m_vWorldScale * m_vRecipPixel, shadowSizeFactor);
}
void TransformedView::DrawShadowStringPropDecal(const olc::vf2d & pos, const std::string & sText, const olc::Pixel col, const olc::Pixel shadowCol, const olc::vf2d & scale, const float shadowSizeFactor)
{
pge->DrawShadowStringPropDecal(WorldToScreen(pos), sText, col, shadowCol, scale * m_vWorldScale * m_vRecipPixel, shadowSizeFactor);
}
void TransformedView::DrawStringPropDecal(const olc::vf2d & pos, const std::string & sText, const olc::Pixel col, const olc::vf2d & scale )
{
pge->DrawStringPropDecal(WorldToScreen(pos), sText, col, scale * m_vWorldScale * m_vRecipPixel);

@ -1108,9 +1108,8 @@ namespace olc
void DrawString(const olc::vi2d& pos, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1);
olc::vi2d GetTextSize(const std::string& s);
// Draws a single line of text - non-monospaced
void DrawStringProp(const olc::vi2d& pos, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1);
void DrawStringProp(int32_t x, int32_t y, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1);
void DrawShadowStringProp(const olc::vi2d& pos, const std::string& sText, Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const float shadowSizeFactor=1);
void DrawStringProp(const olc::vi2d& pos, const std::string& sText, Pixel col = olc::WHITE, uint32_t scale = 1);
olc::vi2d GetTextSizeProp(const std::string& s);
// Decal Quad functions
@ -3521,17 +3520,6 @@ namespace olc
SetPixelMode(m);
}
void PixelGameEngine::DrawShadowStringProp(const olc::vi2d& pos, const std::string& sText, Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const float shadowSizeFactor){
for(float y=-shadowSizeFactor;y<=shadowSizeFactor+0.1;y+=shadowSizeFactor/2){
for(float x=-shadowSizeFactor;x<=shadowSizeFactor+0.1;x+=shadowSizeFactor/2){
if(x!=0||y!=0){
DrawStringProp(pos.x+x,pos.y+y, sText, shadowCol,int(scale.x));
}
}
}
DrawStringProp(pos.x,pos.y, sText, col,int(scale.x));
}
void PixelGameEngine::SetPixelMode(Pixel::Mode m)
{ nPixelMode = m; }

@ -147,12 +147,6 @@ namespace olc::utils
return m_bWorldBoundary;
}
inline bool ReachedTarget() const
{
float dist=sqrt(pow(m_vPosition.x-GetTarget().x,2)+pow(m_vPosition.y-GetTarget().y,2));
return dist<=4;
}
// Get the world boundary rectangle position
inline const olc::vf2d& GetWorldBoundaryPosition() const
{

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 MiB

After

Width:  |  Height:  |  Size: 23 MiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

@ -4,14 +4,14 @@ namespace util{
float random(float range){
return float(rand())/RAND_MAX*range;
}
void ApplyMatrixEffect(PixelGameEngine*pge,Renderable&r,Renderable&originalImg,std::unique_ptr<Renderable>&matrixImg){
void ApplyMatrixEffect(PixelGameEngine*pge,Renderable&r,Renderable&originalImg,Renderable&matrixImg){
pge->SetDrawTarget(r.Sprite());
pge->Clear(BLANK);
for(int y=0;y<r.Sprite()->height;y++){
for(int x=0;x<r.Sprite()->width;x++){
Pixel col=originalImg.Sprite()->GetPixel(x,y);
if(col==WHITE){
pge->Draw({x,y},matrixImg->Sprite()->GetPixel(x,y));
pge->Draw({x,y},matrixImg.Sprite()->GetPixel(x,y));
} else {
pge->Draw({x,y},originalImg.Sprite()->GetPixel(x,y));
}

@ -4,7 +4,7 @@
namespace util{
float random(float range);
void ApplyMatrixEffect(PixelGameEngine*pge,Renderable&r,Renderable&originalImg,std::unique_ptr<Renderable>&matrixImg);
void ApplyMatrixEffect(PixelGameEngine*pge,Renderable&r,Renderable&originalImg,Renderable&matrixImg);
bool CanAfford(Resources&resources,std::vector<Memory>&unitCosts);
int GetHealthCost(std::vector<Memory>&unitCosts);
int GetAtkSpdCost(std::vector<Memory>&unitCosts);

Loading…
Cancel
Save