Implement Game State, transparent button, transparent image button, scenarios 2-8, bugfixes.

master
sigonasr2 1 year ago
parent f840213233
commit 2d63b9c5cc
  1. 2
      olcCodeJam2023Entry/Constant.cpp
  2. 2
      olcCodeJam2023Entry/Constant.h
  3. 8
      olcCodeJam2023Entry/GameState.h
  4. 2
      olcCodeJam2023Entry/Image.h
  5. 6
      olcCodeJam2023Entry/Info.txt
  6. 1
      olcCodeJam2023Entry/Level.h
  7. 326
      olcCodeJam2023Entry/Scenario.cpp
  8. 32
      olcCodeJam2023Entry/Scenario.h
  9. 5
      olcCodeJam2023Entry/Unit.cpp
  10. 2
      olcCodeJam2023Entry/Unit.h
  11. 115
      olcCodeJam2023Entry/VirusAttack.cpp
  12. 29
      olcCodeJam2023Entry/VirusAttack.h
  13. BIN
      olcCodeJam2023Entry/assets/restart.png
  14. BIN
      olcCodeJam2023Entry/assets/restartHover.png
  15. 1
      olcCodeJam2023Entry/olcCodeJam2023Entry.vcxproj
  16. 3
      olcCodeJam2023Entry/olcCodeJam2023Entry.vcxproj.filters
  17. 120
      olcCodeJam2023Entry/olcPGEX_QuickGUI.h
  18. 4
      olcCodeJam2023Entry/olcPGEX_SplashScreen.h
  19. 6
      olcCodeJam2023Entry/olcPGEX_TransformedView.h

@ -39,3 +39,5 @@ 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,4 +43,6 @@ public:
static Pixel INCREASE_VALUE_COLOR;
static Pixel DECREASE_VALUE_COLOR;
static float RESTART_BUTTON_HOLD_TIME;
};

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

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

@ -102,7 +102,8 @@ 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.
(After attaching a unit to a collection point...)
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...)
2 Left shifters wander into the area.
[Pan over to the RAM bank]
An ambush...? I, WHAT? -- THIS IS NOT-
@ -128,6 +129,9 @@ Stage 8:
(New Scenario Objective:
-Defeat all enemy units)
Create a Restart feature.
Distribution of Collection Points:
HEALTH 60
ATKSPD 21

@ -33,6 +33,7 @@ struct CPData{
//Large: 1280
struct Level{
LevelName name=STAGE1;
vi2d size={1,1};
Resources player_starting_resources;
Resources enemy_starting_resources;

@ -3,19 +3,37 @@
Scenario::Scenario(VirusAttack*game)
:game(game){
dialog.SetVisible(false);
}
void Scenario::Start(){}
void Scenario::_Update(){
initialWaitTimer=std::max(0.f,initialWaitTimer-game->GetElapsedTime());
waitToContinueTimer=std::max(0.f,waitToContinueTimer-game->GetElapsedTime());
if(missionCompleted){
missionCompletedTimer+=game->GetElapsedTime();
if(game->GetKey(SPACE).bPressed){
NextLevel();
}
}
if(!missionCompleted&&MissionCompleted()){
missionCompleted=true;
waitToContinueTimer=3;
}
Update();
}
void Scenario::_Draw(){
if(game->objective.length()>0){
game->DrawShadowStringDecal({4,24},"Objective:");
game->DrawShadowStringDecal({6,36},game->objective);
game->DrawShadowStringDecal({4,24},missionCompleted?"Objective Complete!":"Objective:",missionCompleted?GREEN:WHITE);
vf2d textSize=game->GetTextSize(game->objective);
game->DrawShadowStringDecal({6,36},game->objective,missionCompleted?GREEN:WHITE);
if(missionCompleted&&initialWaitTimer==0){
game->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->GetTextSizeProp(continueText)*textScale;
game->DrawShadowStringPropDecal(game->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);
}
}
Draw();
}
@ -38,12 +56,18 @@ void Scenario::MoveCamera(){
camera.Update(game->GetElapsedTime());
}
void Scenario::NextLevel(){}
Stage1::Stage1(VirusAttack*game)
:Scenario(game){}
void Stage1::Start(){
state=0;
missionCompleted=false;
dialog.SetVisible(false);
game->unitMetersGreyedOut=true;
game->playerInControl=false;
game->guideEnabled=false;
camera=utils::Camera2D(game->GetScreenSize(),game->game.GetWorldOffset());
camera.SetLazyFollowRate(1);
camera.SetMode(utils::Camera2D::Mode::LazyFollow);
@ -97,7 +121,7 @@ void Stage1::Update(){
}
}break;
case 6:{
DisplayDialog("The yellow bars represent a unit's Health memory allocation. Make sure there's always at least 1 bit of it.");
DisplayDialog("The yellow bars represent a unit's Health memory allocation. Eliminate it from enemies, and make sure you have at least 1 bit of it.");
if(dialog.bPressed){
state=7;
}
@ -119,6 +143,300 @@ void Stage1::Update(){
}break;
}
}
bool Stage1::MissionCompleted(){
for(auto&u:game->units){
if(!u->IsFriendly()&&u->IsRAMBank()){
return false;
}
}
return true;
}
void Stage1::Draw(){
dialog.UpdateAndDraw({24,64},game,game->player_resources,game->IMAGES,game->GetTotalUsedMemory(),game->currentLevel->availableMemory);
}
void Stage1::NextLevel(){
game->levelToLoad=STAGE2;
}
Stage2::Stage2(VirusAttack*game)
:Scenario(game){}
void Stage2::Start(){
state=0;
missionCompleted=false;
dialog.SetVisible(false);
game->unitMetersGreyedOut=true;
game->limitedBuildOptions=true;
game->guideEnabled=false;
game->playerInControl=false;
camera=utils::Camera2D(game->GetScreenSize(),game->game.GetWorldOffset());
camera.SetLazyFollowRate(1);
camera.SetMode(utils::Camera2D::Mode::LazyFollow);
}
void Stage2::Update(){
switch(state){
case 0:{
DisplayDialog("I am the test dialog.");
if(dialog.bPressed){
dialog.SetVisible(false);
state=1;
}
}break;
}
}
bool Stage2::MissionCompleted(){
for(auto&u:game->units){
if(!u->IsFriendly()&&u->IsRAMBank()){
return false;
}
}
return true;
}
void Stage2::Draw(){
dialog.UpdateAndDraw({24,64},game,game->player_resources,game->IMAGES,game->GetTotalUsedMemory(),game->currentLevel->availableMemory);
}
void Stage2::NextLevel(){
game->levelToLoad=STAGE3;
}
Stage3::Stage3(VirusAttack*game)
:Scenario(game){}
void Stage3::Start(){
state=0;
missionCompleted=false;
dialog.SetVisible(false);
game->unitMetersGreyedOut=false;
game->limitedBuildOptions=true;
game->guideEnabled=false;
game->playerInControl=false;
camera=utils::Camera2D(game->GetScreenSize(),game->game.GetWorldOffset());
camera.SetLazyFollowRate(1);
camera.SetMode(utils::Camera2D::Mode::LazyFollow);
}
void Stage3::Update(){
switch(state){
case 0:{
DisplayDialog("I am the test dialog.");
if(dialog.bPressed){
dialog.SetVisible(false);
state=1;
}
}break;
}
}
bool Stage3::MissionCompleted(){
for(auto&u:game->units){
if(!u->IsFriendly()&&u->IsRAMBank()){
return false;
}
}
return true;
}
void Stage3::Draw(){
dialog.UpdateAndDraw({24,64},game,game->player_resources,game->IMAGES,game->GetTotalUsedMemory(),game->currentLevel->availableMemory);
}
void Stage3::NextLevel(){
game->levelToLoad=STAGE4;
}
Stage4::Stage4(VirusAttack*game)
:Scenario(game){}
void Stage4::Start(){
state=0;
missionCompleted=false;
dialog.SetVisible(false);
game->unitMetersGreyedOut=false;
game->limitedBuildOptions=false;
game->guideEnabled=true;
game->playerInControl=false;
camera=utils::Camera2D(game->GetScreenSize(),game->game.GetWorldOffset());
camera.SetLazyFollowRate(1);
camera.SetMode(utils::Camera2D::Mode::LazyFollow);
}
void Stage4::Update(){
switch(state){
case 0:{
DisplayDialog("I am the test dialog.");
if(dialog.bPressed){
dialog.SetVisible(false);
state=1;
}
}break;
}
}
bool Stage4::MissionCompleted(){
for(auto&u:game->units){
if(!u->IsFriendly()&&u->IsRAMBank()){
return false;
}
}
return true;
}
void Stage4::Draw(){
dialog.UpdateAndDraw({24,64},game,game->player_resources,game->IMAGES,game->GetTotalUsedMemory(),game->currentLevel->availableMemory);
}
void Stage4::NextLevel(){
game->levelToLoad=STAGE5;
}
Stage5::Stage5(VirusAttack*game)
:Scenario(game){}
void Stage5::Start(){
state=0;
missionCompleted=false;
dialog.SetVisible(false);
game->unitMetersGreyedOut=false;
game->limitedBuildOptions=false;
game->guideEnabled=true;
game->playerInControl=true;
camera=utils::Camera2D(game->GetScreenSize(),game->game.GetWorldOffset());
camera.SetLazyFollowRate(1);
camera.SetMode(utils::Camera2D::Mode::LazyFollow);
}
void Stage5::Update(){
switch(state){
case 0:{
SetObjective("Defeat all enemy units.");
state=1;
}break;
}
}
bool Stage5::MissionCompleted(){
for(auto&u:game->units){
if(!u->IsFriendly()&&u->IsRAMBank()){
return false;
}
}
return true;
}
void Stage5::Draw(){
dialog.UpdateAndDraw({24,64},game,game->player_resources,game->IMAGES,game->GetTotalUsedMemory(),game->currentLevel->availableMemory);
}
void Stage5::NextLevel(){
game->levelToLoad=STAGE6;
}
Stage6::Stage6(VirusAttack*game)
:Scenario(game){}
void Stage6::Start(){
state=0;
missionCompleted=false;
dialog.SetVisible(false);
game->unitMetersGreyedOut=false;
game->limitedBuildOptions=false;
game->guideEnabled=true;
game->playerInControl=true;
camera=utils::Camera2D(game->GetScreenSize(),game->game.GetWorldOffset());
camera.SetLazyFollowRate(1);
camera.SetMode(utils::Camera2D::Mode::LazyFollow);
}
void Stage6::Update(){
switch(state){
case 0:{
SetObjective("Defeat all enemy units.");
state=1;
}break;
}
}
bool Stage6::MissionCompleted(){
for(auto&u:game->units){
if(!u->IsFriendly()&&u->IsRAMBank()){
return false;
}
}
return true;
}
void Stage6::Draw(){
dialog.UpdateAndDraw({24,64},game,game->player_resources,game->IMAGES,game->GetTotalUsedMemory(),game->currentLevel->availableMemory);
}
void Stage6::NextLevel(){
game->levelToLoad=STAGE7;
}
Stage7::Stage7(VirusAttack*game)
:Scenario(game){}
void Stage7::Start(){
state=0;
missionCompleted=false;
dialog.SetVisible(false);
game->unitMetersGreyedOut=false;
game->limitedBuildOptions=false;
game->guideEnabled=true;
game->playerInControl=true;
camera=utils::Camera2D(game->GetScreenSize(),game->game.GetWorldOffset());
camera.SetLazyFollowRate(1);
camera.SetMode(utils::Camera2D::Mode::LazyFollow);
}
void Stage7::Update(){
switch(state){
case 0:{
SetObjective("Defeat all enemy units.");
state=1;
}break;
}
}
bool Stage7::MissionCompleted(){
for(auto&u:game->units){
if(!u->IsFriendly()&&u->IsRAMBank()){
return false;
}
}
return true;
}
void Stage7::Draw(){
dialog.UpdateAndDraw({24,64},game,game->player_resources,game->IMAGES,game->GetTotalUsedMemory(),game->currentLevel->availableMemory);
}
void Stage7::NextLevel(){
game->levelToLoad=STAGE8;
}
Stage8::Stage8(VirusAttack*game)
:Scenario(game){}
void Stage8::Start(){
state=0;
missionCompleted=false;
dialog.SetVisible(false);
game->unitMetersGreyedOut=false;
game->limitedBuildOptions=false;
game->guideEnabled=true;
game->playerInControl=true;
camera=utils::Camera2D(game->GetScreenSize(),game->game.GetWorldOffset());
camera.SetLazyFollowRate(1);
camera.SetMode(utils::Camera2D::Mode::LazyFollow);
}
void Stage8::Update(){
switch(state){
case 0:{
SetObjective("Defeat all enemy units.");
state=1;
}break;
}
}
bool Stage8::MissionCompleted(){
for(auto&u:game->units){
if(!u->IsFriendly()&&u->IsRAMBank()){
return false;
}
}
return true;
}
void Stage8::Draw(){
dialog.UpdateAndDraw({24,64},game,game->player_resources,game->IMAGES,game->GetTotalUsedMemory(),game->currentLevel->availableMemory);
}
void Stage8::NextLevel(){
game->state=GameState::COMPLETED;
}

@ -14,6 +14,8 @@ public:
void SetObjective(std::string objective);
void SetupCameraTarget(vf2d pos);
void MoveCamera();
virtual bool MissionCompleted()=0;
virtual void NextLevel();
protected:
VirusAttack*game;
int state=0;
@ -21,12 +23,28 @@ protected:
float initialWaitTimer=3;
utils::Camera2D camera;
vf2d cameraTargetPos={};
bool missionCompleted=false;
float waitToContinueTimer=0;
float missionCompletedTimer=0;
};
class Stage1:public Scenario{
public:
Stage1(VirusAttack*game);
void Start()override;
void Update()override;
void Draw()override;
};
#define SetupStage(StageClass) \
class StageClass:public Scenario{ \
public: \
StageClass(VirusAttack*game); \
void Start()override; \
void Update()override; \
bool MissionCompleted()override; \
void Draw()override; \
void NextLevel()override; \
};
SetupStage(Stage1)
SetupStage(Stage2)
SetupStage(Stage3)
SetupStage(Stage4)
SetupStage(Stage5)
SetupStage(Stage6)
SetupStage(Stage7)
SetupStage(Stage8)

@ -189,6 +189,7 @@ RAMBank::RAMBank(PixelGameEngine*pge,vf2d pos,std::map<Image,std::unique_ptr<Ren
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;
}
void RAMBank::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherUnits){
@ -973,3 +974,7 @@ bool Unit::IsAttached(){
Unit*Unit::GetBuildUnit(){
return buildTransformUnit.get();
}
bool Unit::IsRAMBank(){
return isRAMBank;
}

@ -97,6 +97,7 @@ public:
void SaveMemory();
bool IsPlatform();
bool IsAttached();
bool IsRAMBank();
Unit*GetBuildUnit();
Marker health={};
Marker range={};
@ -135,6 +136,7 @@ protected:
bool isPlatform=false;
std::unique_ptr<Unit>buildTransformUnit;
float buildTime=0;
bool isRAMBank=false;
private:
Renderable targetingLine;
Renderable attackingLine;

@ -5,7 +5,7 @@
#define AUDIO_SOURCE_IMPLEMENTATION
#define OLC_PGEX_QUICKGUI
//#define SPLASH_ENABLED
#define SPLASH_ENABLED
#ifdef SPLASH_ENABLED
#define OLC_PGEX_SPLASHSCREEN
#endif
@ -64,6 +64,8 @@ void VirusAttack::InitializeImages(){
LoadImage(SEGMENT_BAR,"assets/segmentBar.png",false,false);
LoadImage(HOODED_FIGURE,"assets/hooded_figure.png");
LoadImage(SPOOK_HOODED_FIGURE,"assets/spook_hooded_figure.png");
LoadImage(RESTART,"assets/restart.png");
LoadImage(RESTART_HOVER,"assets/restartHover.png");
}
void VirusAttack::InitializeLevelData(){
@ -71,6 +73,7 @@ void VirusAttack::InitializeLevelData(){
{
//Stage 1 data.
LevelName stage=STAGE1;
levelData[stage].name=stage;
levelData[stage].cameraStart={96,96};
levelData[stage].worldZoom={1,1};
levelData[stage].scenario=scenarios[0];
@ -93,12 +96,13 @@ void VirusAttack::InitializeLevelData(){
{
//Stage 2 data.
LevelName stage=STAGE2;
levelData[stage].name=stage;
levelData[stage].cameraStart={96,96};
levelData[stage].worldZoom={1,1};
levelData[stage].size={16,16};
levelData[stage].scenario=scenarios[1];
levelData[stage].levelColor=DARK_GREEN;
levelData[stage].bgm=Sound::COSMOS;
levelData[stage].bgm=Sound::GRAVITY;
levelData[stage].player_starting_resources={10,10,10,10,10};
levelData[stage].enemy_starting_resources={0,0,0,0,0};
{
@ -129,6 +133,7 @@ bool VirusAttack::OnUserCreate(){
memoryAllocatorBox.Initialize(CONSTANT::MEMORY_ALLOCATOR_BOX_DISPLAY_STRING,{},CONSTANT::MEMORY_ALLOCATOR_BOX_HEADER_STRING);
memoryAllocatorBox.SetVisible(false);
platformCreationBox.SetVisible(false);
restartBox.SetVisible(false);
IMAGES[MINIMAP_OUTLINE]=std::make_unique<Renderable>();
IMAGES[MINIMAP_OUTLINE]->Create(64,64);
@ -212,6 +217,8 @@ void VirusAttack::LoadLevel(LevelName level){
}
void VirusAttack::InitializeGUIs(){
restartButton=new QuickGUI::TransparentImageButton(restartManager,*IMAGES[RESTART],*IMAGES[RESTART_HOVER],{1,1},{float(ScreenWidth()-32),12.f},{28,28});
unitCreationList.colNormal = olc::DARK_GREEN;
unitCreationList.colHover = olc::GREEN;
unitCreationList.colClick = olc::YELLOW;
@ -233,11 +240,22 @@ void VirusAttack::InitializeGUIs(){
unitCreationList.DisplayAllControls(false);
platformCreationList.DisplayAllControls(false);
campaignStartButton=new QuickGUI::TransparentButton(mainMenu,"Start Campaign",{float(ScreenWidth()/2)-120.f,80+47.5f*0+10},{240,24},CONSTANT::INCREASE_VALUE_COLOR);
audioToggleButton=new QuickGUI::TransparentButton(mainMenu,"Audio: On",{float(ScreenWidth()/2)-120.f,80+47.5f*1+10},{240,24},CONSTANT::INCREASE_VALUE_COLOR);
difficultyToggleButton=new QuickGUI::TransparentButton(mainMenu,"Difficulty: Normal",{float(ScreenWidth()/2)-120.f,80+47.5f*2+10},{240,24},CONSTANT::INCREASE_VALUE_COLOR);
exitGameButton=new QuickGUI::TransparentButton(mainMenu,"Exit Game",{float(ScreenWidth()/2)-120.f,80+47.5f*3+10},{240,24},CONSTANT::INCREASE_VALUE_COLOR);
}
void VirusAttack::InitializeScenarios(){
scenarios.emplace_back(new Stage1(this));
scenarios.emplace_back(new Stage1(this));
scenarios.emplace_back(new Stage2(this));
scenarios.emplace_back(new Stage3(this));
scenarios.emplace_back(new Stage4(this));
scenarios.emplace_back(new Stage5(this));
scenarios.emplace_back(new Stage6(this));
scenarios.emplace_back(new Stage7(this));
scenarios.emplace_back(new Stage8(this));
}
void VirusAttack::InitializeSounds(){
@ -285,8 +303,9 @@ bool VirusAttack::UnitCreationClickHandled(){
CheckClick(MemoryGuard,memoryGuardButton,IsPlatform)
return false;
}
#define EnableAndHoverCheck(UnitClass,Button,box) \
Button->Enable(CanAfford(player_resources,UnitClass::resourceCost)); \
#define EnableAndHoverCheck(UnitClass,Button,box,limited) \
Button->Enable(CanAfford(player_resources,UnitClass::resourceCost)&&(!limited||limited&&!limitedBuildOptions)); \
if(limited&&!limitedBuildOptions){Button->bVisible=false;} \
if(Button->bHover){ \
box.Initialize(UnitClass::unitDescription, GetMousePos(), UnitClass::unitName,nullptr,{120,36},nullptr,UnitClass::resourceCost); \
hovering=true; \
@ -301,13 +320,13 @@ void VirusAttack::UpdateUnitCreationListGUI(bool allocatorSelected){
unitCreationList.DisplayAllControls(allocatorSelected);
bool hovering=false;
EnableAndHoverCheck(LeftShifter,leftShifterButton,unitCreationBox)
EnableAndHoverCheck(RightShifter,rightShifterButton,unitCreationBox)
EnableAndHoverCheck(BitRestorer,bitRestorerButton,unitCreationBox)
EnableAndHoverCheck(MemorySwapper,memorySwapperButton,unitCreationBox)
EnableAndHoverCheck(BitRestorer,bitRestorerButton,unitCreationBox)
EnableAndHoverCheck(Corrupter,corrupterButton,unitCreationBox)
EnableAndHoverCheck(_Platform,platformButton,unitCreationBox)
EnableAndHoverCheck(LeftShifter,leftShifterButton,unitCreationBox,false)
EnableAndHoverCheck(RightShifter,rightShifterButton,unitCreationBox,false)
EnableAndHoverCheck(BitRestorer,bitRestorerButton,unitCreationBox,true)
EnableAndHoverCheck(MemorySwapper,memorySwapperButton,unitCreationBox,true)
EnableAndHoverCheck(BitRestorer,bitRestorerButton,unitCreationBox,true)
EnableAndHoverCheck(Corrupter,corrupterButton,unitCreationBox,true)
EnableAndHoverCheck(_Platform,platformButton,unitCreationBox,true)
if(!hovering){
unitCreationBox.SetVisible(false);
@ -319,10 +338,10 @@ void VirusAttack::UpdateUnitCreationListGUI(bool allocatorSelected){
void VirusAttack::UpdatePlatformCreationListGUI(bool platformSelected){
platformCreationList.DisplayAllControls(platformSelected);
bool hovering=false;
EnableAndHoverCheck(RAMBank,ramBankButton,platformCreationBox)
EnableAndHoverCheck(Refresher,refresherButton,platformCreationBox)
EnableAndHoverCheck(Turret,turretButton,platformCreationBox)
EnableAndHoverCheck(MemoryGuard,memoryGuardButton,platformCreationBox)
EnableAndHoverCheck(RAMBank,ramBankButton,platformCreationBox,false)
EnableAndHoverCheck(Refresher,refresherButton,platformCreationBox,true)
EnableAndHoverCheck(Turret,turretButton,platformCreationBox,true)
EnableAndHoverCheck(MemoryGuard,memoryGuardButton,platformCreationBox,true)
if(!hovering){
platformCreationBox.SetVisible(false);
@ -649,12 +668,24 @@ void VirusAttack::RenderCollectionPoints(CollectionPoint*cp){
bool VirusAttack::OnUserUpdate(float fElapsedTime){
UpdateMatrixTexture(fElapsedTime);
switch(state){
#pragma region MAIN_MENU
case GameState::MAIN_MENU:{
mainMenu.Update(this);
mainMenu.DrawDecal(this);
}break;
#pragma endregion
#pragma region GAMEPLAY
case GameState::GAMEPLAY:{
if(playerInControl){
HandleDraggingSelection();
HandleRightClickMove();
HandlePanAndZoom(fElapsedTime);
HandleMinimapClick();
}
restartManager.Update(this);
HandleRestartButton(fElapsedTime);
PerformLevelTransition(fElapsedTime);
currentLevel->scenario->_Update();
AL.vecPos=game.ScreenToWorld(GetScreenSize()/2);
AL.fSoundFXVolume=std::min(1.f,game.GetWorldScale().x);
@ -755,10 +786,13 @@ bool VirusAttack::OnUserUpdate(float fElapsedTime){
unitCreationList.DrawDecal(this);
platformCreationList.DrawDecal(this);
restartManager.DrawDecal(this);
DrawSystemMemoryBar(fElapsedTime);
DrawResourceBar(fElapsedTime);
if(guideEnabled){
DrawDecal({float(ScreenWidth()-74-IMAGES[GUIDE]->Sprite()->width*0.75),float(ScreenHeight()+6-IMAGES[GUIDE]->Sprite()->height*0.75)},IMAGES[GUIDE]->Decal(),{0.75,0.75});
}
DrawMinimap();
currentLevel->scenario->_Draw();
@ -788,6 +822,16 @@ bool VirusAttack::OnUserUpdate(float fElapsedTime){
}
}
}
DrawPartialDecal({0,0},GetScreenSize(),IMAGES[MATRIX]->Decal(),randomBackgroundOffset+game.GetWorldOffset()*(vf2d{32,32}/vf2d(GetScreenSize()))*game.GetWorldScale(),{32,32},Pixel{currentLevel->levelColor.r,currentLevel->levelColor.g,currentLevel->levelColor.b,uint8_t(levelForegroundFade*255)}/2);
}break;
#pragma endregion
#pragma region COMPLETED
case GameState::COMPLETED:{
DrawPartialDecal({0,0},GetScreenSize(),IMAGES[MATRIX]->Decal(),randomBackgroundOffset+game.GetWorldOffset()*(vf2d{32,32}/vf2d(GetScreenSize()))*game.GetWorldScale(),{32,32},Pixel{currentLevel->levelColor.r,currentLevel->levelColor.g,currentLevel->levelColor.b,164}/2);
}break;
#pragma endregion
}
return true;
}
@ -1031,6 +1075,45 @@ bool VirusAttack::OnUserDestroy(){
return true;
}
void VirusAttack::PerformLevelTransition(float fElapsedTime){
if(levelToLoad!=currentLevel->name||reloadLevel){
levelForegroundFade=std::min(1.f,levelForegroundFade+fElapsedTime);
if(levelForegroundFade>=1){
LoadLevel(levelToLoad);
reloadLevel=false;
}
}else
if(levelForegroundFade>0){
levelForegroundFade=std::max(0.f,levelForegroundFade-fElapsedTime);
}
}
void VirusAttack::RestartLevel(){
reloadLevel=true;
}
void VirusAttack::HandleRestartButton(float fElapsedTime){
if(restartButton->bHover){
restartBox.Initialize("Click and hold to restart the level.",GetMousePos()+vf2d{0,10},"Restart Level",nullptr,{72,1});
restartBox.SetVisible(true);
if(restartButton->bPressed){
restartButtonHeldDown=true;
}
if(restartButtonHeldDown){
restartButtonHoldTime+=fElapsedTime;
if(restartButtonHoldTime>=CONSTANT::RESTART_BUTTON_HOLD_TIME){
RestartLevel();
restartButtonHeldDown=false;
restartButtonHoldTime=0;
}
}
}else{
restartBox.SetVisible(false);
restartButtonHeldDown=false;
restartButtonHoldTime=0;
}
}
int main()
{
VirusAttack app;

@ -5,6 +5,7 @@
#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"
@ -15,6 +16,7 @@
#include "Resources.h"
#include "Textbox.h"
#include "Level.h"
#include "GameState.h"
class Scenario;
@ -28,6 +30,13 @@ class VirusAttack : public olc::PixelGameEngine
{
friend class Scenario;
friend class Stage1;
friend class Stage2;
friend class Stage3;
friend class Stage4;
friend class Stage5;
friend class Stage6;
friend class Stage7;
friend class Stage8;
private:
#ifdef SPLASH_ENABLED
SplashScreen splash;
@ -52,11 +61,18 @@ private:
TileTransformedView game;
Textbox unitCreationBox,testBox,memoryAllocatorBox,platformCreationBox;
Textbox unitCreationBox,testBox,memoryAllocatorBox,platformCreationBox,restartBox;
Level*currentLevel;
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;
@ -87,6 +103,14 @@ private:
float memoryChangeTimer=2;
bool unitMetersGreyedOut=false; //If true, all but health meters show up as dark grey.
bool playerInControl=true;
float levelForegroundFade=0;
LevelName levelToLoad;
bool limitedBuildOptions=false;
bool guideEnabled=true;
bool reloadLevel=false;
bool restartButtonHeldDown=false;
float restartButtonHoldTime=0;
GameState state=GameState::MAIN_MENU;
std::string objective="";
@ -122,6 +146,9 @@ private:
void DrawSystemMemoryBar(float fElapsedTime);
void CalculateUsedMemory();
void InitializeScenarios();
void PerformLevelTransition(float fElapsedTime);
void RestartLevel();
void HandleRestartButton(float fElapsedTime);
public:
VirusAttack();

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 772 B

@ -143,6 +143,7 @@
<ClInclude Include="Constant.h" />
<ClInclude Include="DeathAnimation.h" />
<ClInclude Include="DebuffIcon.h" />
<ClInclude Include="GameState.h" />
<ClInclude Include="Image.h" />
<ClInclude Include="Level.h" />
<ClInclude Include="MemoryType.h" />

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

@ -252,6 +252,31 @@ 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
{
@ -290,6 +315,27 @@ 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:
@ -750,8 +796,9 @@ 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();
@ -866,6 +913,40 @@ 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)
@ -893,6 +974,43 @@ 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 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));
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));
return true;
}

@ -180,6 +180,7 @@ 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);
@ -633,6 +634,11 @@ 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);

Loading…
Cancel
Save