Add in resource gain overhead indicators.
This commit is contained in:
parent
ca39790119
commit
4b1cc3043a
@ -9,3 +9,31 @@ void DebuffIcon::Draw(TileTransformedView&game){
|
||||
game.DrawRotatedDecal(pos,icon->Decal(),0,icon->Sprite()->Size()/2,{1,1},{255,255,255,uint8_t((lifetime/CONSTANT::DEBUFFICON_LIFETIME)*255)});
|
||||
game.DrawRotatedDecal(pos+vf2d{4,-4},redXIcon->Decal(),0,icon->Sprite()->Size()/2,{1,1},{255,255,255,uint8_t((lifetime/CONSTANT::DEBUFFICON_LIFETIME)*255)});
|
||||
}
|
||||
|
||||
void ResourceGainIcon::Update(float fElapsedTime){
|
||||
pos.y-=6*fElapsedTime;
|
||||
lifetime-=fElapsedTime;
|
||||
}
|
||||
|
||||
void ResourceGainIcon::Draw(TileTransformedView&game){
|
||||
Pixel col;
|
||||
switch(type){
|
||||
case HEALTH:{
|
||||
col=CONSTANT::HEALTH_COLOR;
|
||||
}break;
|
||||
case RANGE:{
|
||||
col=CONSTANT::RANGE_COLOR;
|
||||
}break;
|
||||
case ATKSPD:{
|
||||
col=CONSTANT::ATKSPD_COLOR;
|
||||
}break;
|
||||
case MOVESPD:{
|
||||
col=CONSTANT::MOVESPD_COLOR;
|
||||
}break;
|
||||
case PROCEDURE:{
|
||||
col=CONSTANT::PROCEDURE_COLOR;
|
||||
}break;
|
||||
}
|
||||
game.DrawRotatedDecal(pos,icon->Decal(),0,icon->Sprite()->Size()/2,{1,1},{col.r,col.g,col.b,uint8_t((lifetime/CONSTANT::DEBUFFICON_LIFETIME)*255)});
|
||||
game.DrawShadowStringDecal(pos-vf2d{-2,-2},"+1",col);
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
#include "olcPixelGameEngine.h"
|
||||
#include "olcPGEX_TransformedView.h"
|
||||
#include "Constant.h"
|
||||
#include "MemoryType.h"
|
||||
|
||||
struct DebuffIcon{
|
||||
Renderable*icon;
|
||||
@ -11,3 +12,12 @@ struct DebuffIcon{
|
||||
void Update(float fElapsedTime);
|
||||
void Draw(TileTransformedView&game);
|
||||
};
|
||||
|
||||
struct ResourceGainIcon{
|
||||
Renderable*icon;
|
||||
MemoryType type;
|
||||
vf2d pos;
|
||||
float lifetime=CONSTANT::DEBUFFICON_LIFETIME;
|
||||
void Update(float fElapsedTime);
|
||||
void Draw(TileTransformedView&game);
|
||||
};
|
@ -91,7 +91,9 @@ Stage 3:
|
||||
I'll leave a guide by the map in case your memory betrays you.
|
||||
(Guide Enabled)
|
||||
(New Scenario Objective:
|
||||
-Defeat all enemy units)
|
||||
-Defeat all units)
|
||||
(Upon uncovering units and going near them)
|
||||
Oh oops, I guess there were no viruses in this sector. Let's move on then.
|
||||
|
||||
Stage 4:
|
||||
(Start with 3 of the yellow resource)
|
||||
@ -110,31 +112,22 @@ Stage 5:
|
||||
(New Scenario Objective:
|
||||
-Defeat all enemy units)
|
||||
|
||||
Stage 6:
|
||||
(New Scenario Objective:
|
||||
-Defeat all enemy units)
|
||||
...
|
||||
|
||||
Stage 7:
|
||||
I see you have a few new tricks up your sleeve hacker.
|
||||
Don't think it'll be that easy to get through this one...
|
||||
(New Scenario Objective:
|
||||
-Defeat all enemy units)
|
||||
|
||||
Stage 8:
|
||||
You need to cease all operations, you are causing more harm than good.
|
||||
(New Scenario Objective:
|
||||
-Defeat all enemy units)
|
||||
|
||||
Tutorial
|
||||
(Grey out non-important bars)
|
||||
|
||||
Level 1: Basic Unit and Controls, move units towards enemy unit
|
||||
Level 2: Introduce another Unit
|
||||
Level 3:
|
||||
Level 4:
|
||||
Level 5:
|
||||
Level 6:
|
||||
|
||||
(Introduce one unit at a time)
|
||||
|
||||
Memory Limits
|
||||
|
||||
Minimap
|
||||
Pause / Slow down time (Hotkeys to speed up/slow down time)
|
||||
|
||||
Stage 1
|
||||
Stage 2
|
||||
Stage 3
|
||||
Stage 4
|
||||
Stage 5 - Hacking a Network
|
||||
|
||||
|
||||
Potential Songs:
|
||||
|
@ -8,6 +8,10 @@ enum LevelName{
|
||||
STAGE2,
|
||||
STAGE3,
|
||||
STAGE4,
|
||||
STAGE5,
|
||||
STAGE6,
|
||||
STAGE7,
|
||||
STAGE8,
|
||||
};
|
||||
|
||||
struct UnitData{
|
||||
@ -31,4 +35,5 @@ struct Level{
|
||||
Sound bgm=Sound::COSMOS;
|
||||
vf2d cameraStart={96,96};
|
||||
vf2d worldZoom={1,1};
|
||||
Pixel levelColor=DARK_GREEN;
|
||||
};
|
@ -91,9 +91,11 @@ void MemorySwapper::Attack(Unit&victim,std::vector<std::shared_ptr<Unit>>&otherU
|
||||
if(victim.moveSpd.index<lowestInd){lowest=&victim.moveSpd;lowestInd=lowest->index;}
|
||||
if(victim.procedure.index<lowestInd){lowest=&victim.procedure;lowestInd=lowest->index;}
|
||||
|
||||
if(lowest!=nullptr){
|
||||
order.push_back(lowest);
|
||||
lowest->index=9999999;
|
||||
}
|
||||
}
|
||||
std::reverse(order.begin(),order.end());
|
||||
int i=0;
|
||||
int marker=0;
|
||||
@ -637,7 +639,7 @@ void Unit::_RunAI(PixelGameEngine*pge){
|
||||
RunAI(pge);
|
||||
}
|
||||
|
||||
void Unit::_Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS,Resources&player_resources,Resources&enemy_resources,std::vector<std::unique_ptr<Unit>>&queuedUnits,std::array<float,5>&resourceGainTimer){
|
||||
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::map<Image,std::unique_ptr<Renderable>>&IMAGES){
|
||||
if(!target.expired()){
|
||||
auto ptrTarget=target.lock();
|
||||
if(!InRange(ptrTarget)&&CanMove()){
|
||||
@ -687,6 +689,7 @@ void Unit::_Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SO
|
||||
resourceGainTimer[4]=2;
|
||||
}break;
|
||||
}
|
||||
resourceGainIcons.push_back({IMAGES[RESOURCE].get(),attachedPoint.lock()->type,GetPos()});
|
||||
}
|
||||
}
|
||||
|
||||
@ -967,3 +970,7 @@ void Unit::SaveMemory(){
|
||||
bool Unit::IsPlatform(){
|
||||
return isPlatform&&attachedPoint.expired()&&buildTime<=0;
|
||||
}
|
||||
|
||||
bool Unit::IsAttached(){
|
||||
return !attachedPoint.expired();
|
||||
}
|
@ -71,7 +71,7 @@ public:
|
||||
bool GhostInFogOfWar();
|
||||
void HideGhost();
|
||||
vf2d GetGhostPos();
|
||||
void _Update(PixelGameEngine*pge,std::map<Sound,std::unique_ptr<Audio>>&SOUNDS,Resources&player_resources,Resources&enemy_resources,std::vector<std::unique_ptr<Unit>>&queuedUnits,std::array<float,5>&resourceGainTimer);
|
||||
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::map<Image,std::unique_ptr<Renderable>>&IMAGES);
|
||||
bool IsMoveable();
|
||||
void DrawRangeIndicator(PixelGameEngine*pge,TileTransformedView&game,std::map<Image,std::unique_ptr<Renderable>>&IMAGES);
|
||||
bool CanInteractWithEnemies();
|
||||
@ -96,6 +96,7 @@ public:
|
||||
bool IsGuarded();
|
||||
void SaveMemory();
|
||||
bool IsPlatform();
|
||||
bool IsAttached();
|
||||
Marker health={};
|
||||
Marker range={};
|
||||
Marker atkSpd={};
|
||||
|
@ -65,14 +65,19 @@ void VirusAttack::InitializeImages(){
|
||||
|
||||
void VirusAttack::InitializeLevelData(){
|
||||
#pragma region Stage 1
|
||||
//Stage 1 data.
|
||||
levelData[STAGE1].size={64,64};
|
||||
levelData[STAGE1].bgm=Sound::BOSS2;
|
||||
levelData[STAGE1].player_starting_resources={50,50,50,50,50};
|
||||
levelData[STAGE1].enemy_starting_resources={0,0,0,0,0};
|
||||
{
|
||||
std::vector<UnitData>&units=levelData[STAGE1].unitPlacement;
|
||||
std::vector<CPData>&collectionPoints=levelData[STAGE1].cpPlacement;
|
||||
//Stage 1 data.
|
||||
LevelName stage=STAGE1;
|
||||
levelData[stage].cameraStart={96,96};
|
||||
levelData[stage].worldZoom={1,1};
|
||||
levelData[stage].levelColor=DARK_RED;
|
||||
levelData[stage].size={64,64};
|
||||
levelData[stage].bgm=Sound::BOSS2;
|
||||
levelData[stage].player_starting_resources={50,50,50,50,50};
|
||||
levelData[stage].enemy_starting_resources={0,0,0,0,0};
|
||||
{
|
||||
std::vector<UnitData>&units=levelData[stage].unitPlacement;
|
||||
std::vector<CPData>&collectionPoints=levelData[stage].cpPlacement;
|
||||
|
||||
units.push_back({UnitType::LeftShifter,vf2d{128,128},true});
|
||||
units.push_back({UnitType::RightShifter,vf2d{129,129},true});
|
||||
@ -96,21 +101,28 @@ void VirusAttack::InitializeLevelData(){
|
||||
units.push_back({UnitType::RightShifter,vf2d{360,300},false});
|
||||
units.push_back({UnitType::RightShifter,vf2d{361,300},false});
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
#pragma region Stage 2
|
||||
//Stage 2 data.
|
||||
levelData[STAGE2].size={16,16};
|
||||
levelData[STAGE2].bgm=Sound::COSMOS;
|
||||
levelData[STAGE2].player_starting_resources={10,10,10,10,10};
|
||||
levelData[STAGE2].enemy_starting_resources={0,0,0,0,0};
|
||||
{
|
||||
std::vector<UnitData>&units=levelData[STAGE2].unitPlacement;
|
||||
std::vector<CPData>&collectionPoints=levelData[STAGE2].cpPlacement;
|
||||
//Stage 2 data.
|
||||
LevelName stage=STAGE2;
|
||||
levelData[stage].cameraStart={96,96};
|
||||
levelData[stage].worldZoom={1,1};
|
||||
levelData[stage].size={16,16};
|
||||
levelData[stage].levelColor=DARK_GREEN;
|
||||
levelData[stage].bgm=Sound::COSMOS;
|
||||
levelData[stage].player_starting_resources={10,10,10,10,10};
|
||||
levelData[stage].enemy_starting_resources={0,0,0,0,0};
|
||||
{
|
||||
std::vector<UnitData>&units=levelData[stage].unitPlacement;
|
||||
std::vector<CPData>&collectionPoints=levelData[stage].cpPlacement;
|
||||
|
||||
units.push_back({UnitType::RAMBank,vf2d{134,134},true});
|
||||
|
||||
units.push_back({UnitType::RAMBank,vf2d{1200,1200},false});
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
}
|
||||
|
||||
@ -203,6 +215,8 @@ void VirusAttack::LoadLevel(LevelName level){
|
||||
for(auto&cp:selectedLevel.cpPlacement){
|
||||
collectionPoints.push_back(std::make_unique<CollectionPoint>(this,cp.pos,cp.rot,*IMAGES[MEMORY_COLLECTION_POINT],cp.type));
|
||||
}
|
||||
|
||||
randomBackgroundOffset={util::random(128),util::random(128)};
|
||||
}
|
||||
|
||||
void VirusAttack::InitializeGUIs(){
|
||||
@ -471,11 +485,35 @@ void VirusAttack::DrawMinimap(){
|
||||
SetDrawTarget(IMAGES[MINIMAP_OUTLINE]->Sprite());
|
||||
Clear(BLANK);
|
||||
DrawRect((game.GetWorldOffset()/worldPixelSize*64),viewingTilesPct*64/game.GetWorldScale());
|
||||
for(auto&cp:collectionPoints){
|
||||
Pixel col;
|
||||
switch(cp->type){
|
||||
case HEALTH:{
|
||||
col=CONSTANT::HEALTH_COLOR;
|
||||
}break;
|
||||
case ATKSPD:{
|
||||
col=CONSTANT::ATKSPD_COLOR;
|
||||
}break;
|
||||
case MOVESPD:{
|
||||
col=CONSTANT::MOVESPD_COLOR;
|
||||
}break;
|
||||
case RANGE:{
|
||||
col=CONSTANT::RANGE_COLOR;
|
||||
}break;
|
||||
case PROCEDURE:{
|
||||
col=CONSTANT::PROCEDURE_COLOR;
|
||||
}break;
|
||||
}
|
||||
FillCircle(cp->pos/worldPixelSize*64-vf2d{1,0},1,col);
|
||||
DrawCircle(cp->pos/worldPixelSize*64-vf2d{1,0},1,BLACK);
|
||||
}
|
||||
for(auto&u:units){
|
||||
vf2d squareSize=u->GetUnitSize()/vf2d(WORLD_SIZE);
|
||||
squareSize.x=std::round(std::max(1.f,squareSize.x));
|
||||
squareSize.y=std::round(std::max(1.f,squareSize.y));
|
||||
FillRect(u->GetGhostPos()/worldPixelSize*64-squareSize,squareSize*2,u->IsFriendly()?GREEN:RED);
|
||||
float colorMult=1;
|
||||
if(u->IsAttached()){colorMult=0.5;}
|
||||
FillRect(u->GetGhostPos()/worldPixelSize*64-squareSize,squareSize*2,(u->IsFriendly()?GREEN:RED)*colorMult);
|
||||
}
|
||||
IMAGES[MINIMAP_OUTLINE]->Decal()->Update();
|
||||
SetDrawTarget(nullptr);
|
||||
@ -647,7 +685,7 @@ bool VirusAttack::OnUserUpdate(float fElapsedTime){
|
||||
}
|
||||
}
|
||||
u->AttemptAttack(u,closestUnit,units,debuffIcons,IMAGES);
|
||||
u->_Update(this,SOUNDS,player_resources,enemy_resources,queuedUnits,resourceGainTimer);
|
||||
u->_Update(this,SOUNDS,player_resources,enemy_resources,queuedUnits,resourceGainTimer,resourceGainIcons,IMAGES);
|
||||
}
|
||||
|
||||
std::erase_if(units,[&](std::shared_ptr<Unit>u){
|
||||
@ -666,7 +704,8 @@ bool VirusAttack::OnUserUpdate(float fElapsedTime){
|
||||
|
||||
queuedUnits.clear();
|
||||
|
||||
game.DrawPartialDecal({0,0},WORLD_SIZE*CONSTANT::TILE_SIZE,IMAGES[TILE]->Decal(),{0,0},WORLD_SIZE*CONSTANT::TILE_SIZE,DARK_GREEN);
|
||||
DrawPartialDecal({0,0},GetScreenSize(),IMAGES[MATRIX]->Decal(),randomBackgroundOffset,{32,32},Pixel{currentLevel->levelColor.r,currentLevel->levelColor.g,currentLevel->levelColor.b,164}/2);
|
||||
game.DrawPartialDecal({0,0},WORLD_SIZE*CONSTANT::TILE_SIZE,IMAGES[TILE]->Decal(),{0,0},WORLD_SIZE*CONSTANT::TILE_SIZE,currentLevel->levelColor);
|
||||
|
||||
for(auto&u:units){
|
||||
u->DrawRangeIndicator(this,game,IMAGES);
|
||||
@ -699,7 +738,13 @@ bool VirusAttack::OnUserUpdate(float fElapsedTime){
|
||||
icon.Draw(game);
|
||||
}
|
||||
|
||||
for(ResourceGainIcon&icon:resourceGainIcons){
|
||||
icon.Update(fElapsedTime);
|
||||
icon.Draw(game);
|
||||
}
|
||||
|
||||
std::erase_if(debuffIcons,[](DebuffIcon&icon){return icon.lifetime<=0;});
|
||||
std::erase_if(resourceGainIcons,[](ResourceGainIcon&icon){return icon.lifetime<=0;});
|
||||
|
||||
for(auto&u:units){
|
||||
u->_DrawHud(game,IMAGES);
|
||||
@ -765,7 +810,7 @@ void VirusAttack::RenderFogOfWar(){
|
||||
for(int y=game.GetTopLeftTile().y/96-1;y<=game.GetBottomRightTile().y/96+1;y++){
|
||||
for(int x=game.GetTopLeftTile().x/96-1;x<=game.GetBottomRightTile().x/96+1;x++){
|
||||
if(TileManager::visibleTiles.count(vi2d{x,y})==0){
|
||||
if(x>=0&&y>=0&&x<=WORLD_SIZE.x*CONSTANT::TILE_SIZE.x&&y<=WORLD_SIZE.y*CONSTANT::TILE_SIZE.y){
|
||||
if(x>=0&&y>=0&&x<WORLD_SIZE.x/4&&y<WORLD_SIZE.y/4){
|
||||
game.FillRectDecal(vf2d{float(x),float(y)}*96,{96,96},{0,0,0,128});
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ private:
|
||||
std::vector<std::shared_ptr<CollectionPoint>>collectionPoints;
|
||||
std::vector<std::unique_ptr<DeathAnimation>>deathAnimations;
|
||||
std::vector<DebuffIcon>debuffIcons;
|
||||
std::vector<ResourceGainIcon>resourceGainIcons;
|
||||
|
||||
std::map<Image,std::unique_ptr<Renderable>>IMAGES;
|
||||
std::map<Sound,std::unique_ptr<Audio>>SOUNDS;
|
||||
@ -69,6 +70,8 @@ private:
|
||||
std::vector<Letter>activeLetters;
|
||||
std::array<float,5>resourceGainTimer={0};
|
||||
|
||||
vf2d randomBackgroundOffset;
|
||||
|
||||
vf2d startingDragPos=CONSTANT::UNSELECTED;
|
||||
void HandleDraggingSelection();
|
||||
void DrawSelectionRectangle();
|
||||
|
@ -179,6 +179,7 @@ namespace olc
|
||||
void DrawPartialRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale = { 1.0f, 1.0f }, const olc::Pixel& tint = olc::WHITE);
|
||||
// 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 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);
|
||||
@ -627,6 +628,11 @@ namespace olc
|
||||
pge->DrawStringDecal(WorldToScreen(pos), sText, col, scale * m_vWorldScale * m_vRecipPixel);
|
||||
}
|
||||
|
||||
void TransformedView::DrawShadowStringDecal(const olc::vf2d & pos, const std::string & sText, const olc::Pixel col, const olc::Pixel shadowCol, const olc::vf2d & scale, const float shadowSizeFactor)
|
||||
{
|
||||
pge->DrawShadowStringDecal(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…
x
Reference in New Issue
Block a user