diff --git a/assets/font_shadow.png b/assets/font_shadow.png new file mode 100644 index 0000000..530cb33 Binary files /dev/null and b/assets/font_shadow.png differ diff --git a/assets/highlight_button.png b/assets/highlight_button.png new file mode 100644 index 0000000..a5542e9 Binary files /dev/null and b/assets/highlight_button.png differ diff --git a/src/FloatingText.cpp b/src/FloatingText.cpp index 9871921..16cd97f 100644 --- a/src/FloatingText.cpp +++ b/src/FloatingText.cpp @@ -73,14 +73,8 @@ void FloatingText::Draw(TransformedView&tv){ uint8_t alpha{uint8_t(util::lerp(0U,255U,lifetime/4.f))}; - HamsterGame::Game().SetZ(0.014f); - for(int y:std::ranges::iota_view(-1,2)){ - for(int x:std::ranges::iota_view(-1,2)){ - tv.DrawRotatedStringDecal(pos+vi2d{x,y},text,0.f,strSize/2,{0,0,0,alpha},scale); - } - } HamsterGame::Game().SetZ(0.015f); - tv.DrawRotatedStringDecal(pos,text,0.f,strSize/2,{currentCol.r,currentCol.g,currentCol.b,uint8_t(currentCol.a*(alpha/255.f))},scale); + tv.DrawShadowRotatedStringDecal(pos,text,0.f,strSize/2,{currentCol.r,currentCol.g,currentCol.b,uint8_t(currentCol.a*(alpha/255.f))},{0,0,0,alpha},scale); HamsterGame::Game().SetZ(0.f); } void FloatingText::CreateFloatingText(const vf2d&pos,const std::string&text,const std::vector&colorCycle,const vf2d&scale){ diff --git a/src/Hamster.cpp b/src/Hamster.cpp index 8f39ad2..00a6c59 100644 --- a/src/Hamster.cpp +++ b/src/Hamster.cpp @@ -393,23 +393,11 @@ void Hamster::DrawOverlay(){ if(GetPlayer().HasPowerup(Powerup::JET)&&!GetPlayer().hamsterJet.has_value()){ const std::string readyText{"READY!"}; const vi2d textSize{HamsterGame::Game().GetTextSize(readyText)}; - for(int y:std::ranges::iota_view(-1,2)){ - for(int x:std::ranges::iota_view(-1,2)){ - if(x==0&&y==0)continue; - HamsterGame::Game().DrawRotatedStringDecal(jetDisplayOffset+vf2d{48.f,116.f}+vi2d{x,y},readyText,0.f,textSize/2,fmod(GetPlayer().readyFlashTimer,1.5f)<=0.75f?DARK_RED:BLACK); - } - } - HamsterGame::Game().DrawRotatedStringDecal(jetDisplayOffset+vf2d{48.f,116.f},readyText,0.f,textSize/2,GREEN); + HamsterGame::Game().DrawShadowRotatedStringDecal(jetDisplayOffset+vf2d{48.f,116.f},readyText,0.f,textSize/2,GREEN,fmod(GetPlayer().readyFlashTimer,1.5f)<=0.75f?DARK_RED:BLACK); HamsterGame::Game().DrawDecal(HamsterGame::SCREEN_FRAME.pos+vf2d{HamsterGame::SCREEN_FRAME.size.x,0.f},HamsterGame::GetGFX("fuelmeter.png").Decal()); const std::string launchText{"(SPACE)x2\nto Launch!"}; const vi2d launchTextSize{HamsterGame::Game().GetTextSize(launchText)}; - for(int y:std::ranges::iota_view(-1,2)){ - for(int x:std::ranges::iota_view(-1,2)){ - if(x==0&&y==0)continue; - HamsterGame::Game().DrawRotatedStringDecal(jetDisplayOffset+vf2d{48.f,224.f}+vi2d{x,y},launchText,0.f,launchTextSize/2,BLACK); - } - } - HamsterGame::Game().DrawRotatedStringDecal(jetDisplayOffset+vf2d{48.f,224.f},launchText,0.f,launchTextSize/2,WHITE); + HamsterGame::Game().DrawShadowRotatedStringDecal(jetDisplayOffset+vf2d{48.f,224.f},launchText,0.f,launchTextSize/2,WHITE,BLACK); }else{ HamsterGame::Game().DrawPartialDecal(HamsterGame::SCREEN_FRAME.pos+vf2d{HamsterGame::SCREEN_FRAME.size.x,0.f},HamsterGame::GetGFX("fuelmeter.png").Decal(),{0,0},{96,200}); } @@ -425,12 +413,7 @@ void Hamster::DrawOverlay(){ if(fmod(HamsterGame::Game().GetRuntime(),2.f)<1.f&&GetPlayer().boostCounter>i)HamsterGame::Game().DrawDecal(HamsterGame::SCREEN_FRAME.pos+vf2d{i*16.f+4.f,HamsterGame::SCREEN_FRAME.size.y-18.f},HamsterGame::GetGFX("boost_outline.png").Decal(),{0.125f,0.125f},GetPlayer().boostCounter>i?WHITE:BLACK); else HamsterGame::Game().DrawDecal(HamsterGame::SCREEN_FRAME.pos+vf2d{i*16.f+4.f,HamsterGame::SCREEN_FRAME.size.y-18.f},HamsterGame::GetGFX("boost.png").Decal(),{0.125f,0.125f},GetPlayer().boostCounter>i?WHITE:BLACK); } - for(int y:std::ranges::iota_view(-1,2)){ - for(int x:std::ranges::iota_view(-1,2)){ - HamsterGame::Game().DrawStringDecal(HamsterGame::SCREEN_FRAME.pos+vf2d{3*16.f+8.f,HamsterGame::SCREEN_FRAME.size.y-12.f}+vi2d{x,y},"\"R\" - BOOST",fmod(HamsterGame::Game().GetRuntime(),2.f)<1.f?RED:BLACK); - } - } - HamsterGame::Game().DrawStringDecal(HamsterGame::SCREEN_FRAME.pos+vf2d{3*16.f+8.f,HamsterGame::SCREEN_FRAME.size.y-12.f},"\"R\" - BOOST",YELLOW); + HamsterGame::Game().DrawShadowStringDecal(HamsterGame::SCREEN_FRAME.pos+vf2d{3*16.f+8.f,HamsterGame::SCREEN_FRAME.size.y-12.f},"\"R\" - BOOST",YELLOW,fmod(HamsterGame::Game().GetRuntime(),2.f)<1.f?RED:BLACK); } } diff --git a/src/HamsterAI.cpp b/src/HamsterAI.cpp index 9b0b4d1..9087ecb 100644 --- a/src/HamsterAI.cpp +++ b/src/HamsterAI.cpp @@ -58,19 +58,9 @@ void HamsterAI::DrawOverlay(){ if(recordingMode){ if(HamsterGame::Game().IsTextEntryEnabled()){ std::string displayStr{std::format("{}\n{}","0=SMART 1=NORMAL 2=DUMB",HamsterGame::Game().TextEntryGetString())}; - for(int y:std::ranges::iota_view(-1,2)){ - for(int x:std::ranges::iota_view(-1,2)){ - HamsterGame::Game().DrawStringDecal({2.f+x,2.f+y},displayStr,BLACK); - } - } - HamsterGame::Game().DrawStringDecal({2.f,2.f},displayStr,YELLOW); + HamsterGame::Game().DrawShadowStringDecal({2.f,2.f},displayStr,YELLOW,BLACK); }else if(fmod(HamsterGame::Game().GetRuntime(),1.f)<0.5f){ - for(int y:std::ranges::iota_view(-1,2)){ - for(int x:std::ranges::iota_view(-1,2)){ - HamsterGame::Game().DrawStringDecal({2.f+x,2.f+y},"RECORDING",BLACK); - } - } - HamsterGame::Game().DrawStringDecal({2.f,2.f},"RECORDING",RED); + HamsterGame::Game().DrawShadowStringDecal({2.f,2.f},"RECORDING",RED,BLACK); } } } diff --git a/src/HamsterGame.cpp b/src/HamsterGame.cpp index afd4436..745442e 100644 --- a/src/HamsterGame.cpp +++ b/src/HamsterGame.cpp @@ -57,7 +57,6 @@ bool HamsterGame::OnUserCreate(){ if(i==360){radarCircle.push_back(vf2d{cos(angle),sin(angle)}*43+vf2d{43,44});} radarCircle.push_back(vf2d{cos(angle),sin(angle)}*43+vf2d{43,44}); } - radar=ViewPort{radarCircle,{5.f,8.f}}; for(int i:std::ranges::iota_view(0,8)){ waterTiles.emplace_back(); @@ -280,13 +279,8 @@ void HamsterGame::DrawGame(){ SetDecalMode(DecalMode::NORMAL); DrawPartialDecal({drawX,drawY},GetGFX("gametiles.png").Decal(),powerupSubimageRect.pos,powerupSubimageRect.size); SetDecalMode(DecalMode::ADDITIVE); - for(int y:std::ranges::iota_view(-1,2)){ - for(int x:std::ranges::iota_view(-1,2)){ - DrawRotatedStringDecal(vf2d{drawX+16.f,drawY+32.f}+vi2d{x,y},powerupName,0.f,powerupTextSize/2,CYAN,{0.5f,1.f}); - } - } SetDecalMode(DecalMode::NORMAL); - DrawRotatedStringDecal({drawX+16.f,drawY+32.f},powerupName,0.f,powerupTextSize/2,VERY_DARK_BLUE,{0.5f,1.f}); + DrawShadowRotatedStringDecal({drawX+16.f,drawY+32.f},powerupName,0.f,powerupTextSize/2,VERY_DARK_BLUE,CYAN,{0.5f,1.f}); }else{ DrawPartialDecal({drawX,drawY},GetGFX("gametiles.png").Decal(),powerupSubimageRect.pos,powerupSubimageRect.size,{1.f,1.f},VERY_DARK_GREY); DrawRotatedStringDecal({drawX+16.f,drawY+32.f},powerupName,0.f,powerupTextSize/2,DARK_GREY,{0.5f,1.f}); @@ -316,13 +310,7 @@ void HamsterGame::DrawGame(){ if(speedometerDisplayAmt>=180)speedometerCol=RED; else if(speedometerDisplayAmt>=120)speedometerCol=YELLOW; else if(speedometerDisplayAmt>=80)speedometerCol=GREEN; - for(int y:std::ranges::iota_view(-1,2)){ - for(int x:std::ranges::iota_view(-1,2)){ - if(x==0&&y==0)continue; - DrawStringDecal(SCREEN_FRAME.pos+SCREEN_FRAME.size-speedometerStrSize-vf2d{4.f,4.f}+vi2d{x,y},speedometerStr,BLACK); - } - } - DrawStringDecal(SCREEN_FRAME.pos+SCREEN_FRAME.size-speedometerStrSize-vf2d{4.f,4.f},speedometerStr,speedometerCol); + DrawShadowStringDecal(SCREEN_FRAME.pos+SCREEN_FRAME.size-speedometerStrSize-vf2d{4.f,4.f},speedometerStr,speedometerCol,BLACK); DrawDecal({2.f,4.f},GetGFX("radar.png").Decal()); DrawRadar(); leaderboard.Draw(*this); @@ -536,8 +524,7 @@ void HamsterGame::DrawRadar(){ }; const auto DeferRenderingBasedOnPosition=[this,&icon](const vf2d&pos,const IconType powerupIcon,const uint8_t iconAlpha){ - if(geom2d::intersects(geom2d::circle{{43.f+5.f,44.f+8.f},43},geom2d::rect{pos-vf2d{16.f,16.f},{32.f,32.f}}).size()>0)radar.DrawPartialRotatedDecal(pos,GetGFX("radaricons.png").Decal(),0.f,{8.f,8.f},icon.at(powerupIcon).pos,icon.at(powerupIcon).size,{1.f,1.f},{255,255,255,iconAlpha}); - else if(geom2d::contains(geom2d::circle{{43.f+5.f,44.f+8.f},43},geom2d::rect{pos-vf2d{8.f,8.f},{16.f,16.f}}))DrawPartialRotatedDecal(pos+vf2d{5.f,8.f},GetGFX("radaricons.png").Decal(),0.f,{8.f,8.f},icon.at(powerupIcon).pos,icon.at(powerupIcon).size,{1.f,1.f},{255,255,255,iconAlpha}); + if(geom2d::contains(geom2d::circle{{43.f+5.f,44.f+8.f},43},geom2d::rect{pos-vf2d{8.f,8.f},{16.f,16.f}}))DrawPartialRotatedDecal(pos+vf2d{5.f,8.f},GetGFX("radaricons.png").Decal(),0.f,{8.f,8.f},icon.at(powerupIcon).pos,icon.at(powerupIcon).size,{1.f,1.f},{255,255,255,iconAlpha}); }; for(const Powerup&powerup:Powerup::GetPowerups()){ diff --git a/src/HamsterGame.h b/src/HamsterGame.h index 3c58a77..cf89e75 100644 --- a/src/HamsterGame.h +++ b/src/HamsterGame.h @@ -140,7 +140,6 @@ private: vf2d cloudSpd{}; vf2d cloudOffset{}; float speedometerDisplayAmt{0.f}; - ViewPort radar; void DrawRadar(); float radarScale{36.f}; std::vectorwaterTiles; diff --git a/src/HamsterLeaderboard.cpp b/src/HamsterLeaderboard.cpp index d10d12f..58bc19b 100644 --- a/src/HamsterLeaderboard.cpp +++ b/src/HamsterLeaderboard.cpp @@ -100,12 +100,7 @@ void HamsterLeaderboard::Draw(HamsterGame&game){ Pixel blinkCol{DARK_RED}; if(playerPlacement==1)blinkCol=CYAN; else if(playerPlacement<=3)blinkCol=DARK_GREEN; - for(int y:std::ranges::iota_view(-1,2)){ - for(int x:std::ranges::iota_view(-1,2)){ - game.DrawRotatedStringPropDecal(progressBarBottomPos+vf2d{-4.f,8.f}+vi2d{x,y},placementStr,0.f,{},BLACK,{3.f,3.f}); - } - } - game.DrawRotatedStringPropDecal(progressBarBottomPos+vf2d{-4.f,8.f},placementStr,0.f,{},blinkCol,{3.f,3.f}); + game.DrawShadowRotatedStringPropDecal(progressBarBottomPos+vf2d{-4.f,8.f},placementStr,0.f,{},blinkCol,BLACK,{3.f,3.f}); } } diff --git a/src/Menu.cpp b/src/Menu.cpp index a06ff43..9b890b0 100644 --- a/src/Menu.cpp +++ b/src/Menu.cpp @@ -150,7 +150,7 @@ void Menu::Draw(HamsterGame&game,const MenuType menu,const vi2d pos){ game.border.Draw(); }break; case MAIN_MENU:{ - game.FillRectDecal(pos,game.SCREEN_FRAME.size,{}); + game.DrawPartialDecal(vi2d{pos},game.SCREEN_FRAME.size,game.GetGFX("background1.png").Decal(),vf2d{}+int(game.GetRuntime()*4),game.SCREEN_FRAME.size); game.DrawRotatedDecal(pos,game.GetGFX("button.png").Decal(),0.f,game.GetGFX("button.png").Sprite()->Size()/2); game.border.Draw(); }break; diff --git a/src/Menu.h b/src/Menu.h index 7050db4..3d36735 100644 --- a/src/Menu.h +++ b/src/Menu.h @@ -41,6 +41,9 @@ All rights reserved. class HamsterGame; class Menu{ + class Button{ + std::string buttonText; + }; enum MenuType{ INITIALIZE, TITLE_SCREEN, diff --git a/src/TODO.txt b/src/TODO.txt index db6741b..42b6c59 100644 --- a/src/TODO.txt +++ b/src/TODO.txt @@ -177,6 +177,8 @@ Race Countdown timer sound Menu Select/Back Sound +Loading Screen + ========================== Stages VI - XII: 7 Stages (1 hour each, 7 hours total) Menu Navigations (3 hours) diff --git a/src/olcPGEX_TransformedView.h b/src/olcPGEX_TransformedView.h index e97075d..09d35c3 100644 --- a/src/olcPGEX_TransformedView.h +++ b/src/olcPGEX_TransformedView.h @@ -196,6 +196,12 @@ namespace olc void DrawRotatedStringDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); void DrawRotatedStringPropDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, 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.0f, 1.0f }); + 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.0f, 1.0f }); + + void DrawShadowRotatedStringDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::Pixel col = olc::WHITE, const olc::Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f }); + void DrawShadowRotatedStringPropDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::Pixel col = olc::WHITE, const olc::Pixel shadowCol = olc::BLACK, 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); void DrawRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col = olc::WHITE); @@ -662,6 +668,16 @@ namespace olc pge->DrawStringPropDecal(WorldToScreen(pos), sText, col, scale * m_vWorldScale * m_vRecipPixel,GFX3DTransform::TRANSFORM_REQUIRED); } + void TransformedView::DrawShadowStringDecal(const olc::vf2d & pos, const std::string & sText, const olc::Pixel col, const olc::Pixel shadowCol, const olc::vf2d & scale) + { + pge->DrawStringDecal(WorldToScreen(pos), sText, col, scale * m_vWorldScale * m_vRecipPixel,GFX3DTransform::TRANSFORM_REQUIRED); + } + + void TransformedView::DrawShadowStringPropDecal(const olc::vf2d & pos, const std::string & sText, const olc::Pixel col, const olc::Pixel shadowCol, const olc::vf2d & scale ) + { + pge->DrawShadowStringPropDecal(WorldToScreen(pos), sText, col,shadowCol, scale * m_vWorldScale * m_vRecipPixel,GFX3DTransform::TRANSFORM_REQUIRED); + } + void TransformedView::FillRectDecal(const olc::vf2d & pos, const olc::vf2d & size, const olc::Pixel col) { pge->FillRectDecal(WorldToScreen(pos), (size * m_vWorldScale).ceil(), col,GFX3DTransform::TRANSFORM_REQUIRED); @@ -712,6 +728,12 @@ namespace olc void TransformedView::DrawRotatedStringPropDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center, const olc::Pixel col, const olc::vf2d& scale){ pge->DrawRotatedStringPropDecal(WorldToScreen(pos),sText,fAngle,center,col,scale*m_vWorldScale*m_vRecipPixel,GFX3DTransform::TRANSFORM_REQUIRED); } + void TransformedView::DrawShadowRotatedStringDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center, const olc::Pixel col, const olc::Pixel shadowCol, const olc::vf2d& scale){ + pge->DrawShadowRotatedStringDecal(WorldToScreen(pos),sText,fAngle,center,col,shadowCol,scale*m_vWorldScale*m_vRecipPixel,GFX3DTransform::TRANSFORM_REQUIRED); + } + void TransformedView::DrawShadowRotatedStringPropDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center, const olc::Pixel col, const olc::Pixel shadowCol, const olc::vf2d& scale){ + pge->DrawShadowRotatedStringPropDecal(WorldToScreen(pos),sText,fAngle,center,col,shadowCol,scale*m_vWorldScale*m_vRecipPixel,GFX3DTransform::TRANSFORM_REQUIRED); + } #if defined (OLC_PGEX_SHADER) diff --git a/src/olcPixelGameEngine.h b/src/olcPixelGameEngine.h index 5015b59..babaf51 100644 --- a/src/olcPixelGameEngine.h +++ b/src/olcPixelGameEngine.h @@ -1148,8 +1148,10 @@ namespace olc void DrawRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::vf2d& scale = { 1.0f,1.0f }, const olc::Pixel& tint = olc::WHITE,const GFX3DTransform transform=GFX3DTransform::NO_TRANSFORM); 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,const GFX3DTransform transform=GFX3DTransform::NO_TRANSFORM); // Draws a multiline string as a decal, with tiniting and scaling - void DrawStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f },const GFX3DTransform transform=GFX3DTransform::NO_TRANSFORM); - void DrawStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f },const GFX3DTransform transform=GFX3DTransform::NO_TRANSFORM); + void DrawStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }, const GFX3DTransform transform=GFX3DTransform::NO_TRANSFORM); + void DrawStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }, const GFX3DTransform transform=GFX3DTransform::NO_TRANSFORM); + void DrawShadowStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f }, const GFX3DTransform transform=GFX3DTransform::NO_TRANSFORM); + void DrawShadowStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f }, const GFX3DTransform transform=GFX3DTransform::NO_TRANSFORM); // Draws a single shaded filled rectangle as a decal void DrawRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col = olc::WHITE,const GFX3DTransform transform=GFX3DTransform::NO_TRANSFORM); void FillRectDecal(const olc::vf2d& pos, const olc::vf2d& size, const olc::Pixel col = olc::WHITE,const GFX3DTransform transform=GFX3DTransform::NO_TRANSFORM); @@ -1167,6 +1169,8 @@ namespace olc void DrawLineDecal(const olc::vf2d& pos1, const olc::vf2d& pos2, Pixel p = olc::WHITE,const GFX3DTransform transform=GFX3DTransform::NO_TRANSFORM); void DrawRotatedStringDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f },const GFX3DTransform transform=GFX3DTransform::NO_TRANSFORM); void DrawRotatedStringPropDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f },const GFX3DTransform transform=GFX3DTransform::NO_TRANSFORM); + void DrawShadowRotatedStringDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const GFX3DTransform transform=GFX3DTransform::NO_TRANSFORM); + void DrawShadowRotatedStringPropDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::Pixel col = olc::WHITE, const Pixel shadowCol = olc::BLACK, const olc::vf2d& scale = { 1.0f, 1.0f },const GFX3DTransform transform=GFX3DTransform::NO_TRANSFORM); // Clears entire draw target to Pixel void Clear(Pixel p); // Clears the rendering back buffer @@ -1257,6 +1261,7 @@ namespace olc int nFrameCount = 0; bool bSuspendTextureTransfer = false; Renderable fontRenderable; + Renderable shadowFontRenderable; std::vector vLayers; uint8_t nTargetLayer = 0; uint32_t nLastFPS = 0; @@ -3417,6 +3422,29 @@ namespace olc } } } + void PixelGameEngine::DrawShadowStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const GFX3DTransform transform) + { + olc::vf2d spos = { 0.0f, 0.0f }; + for (auto c : sText) + { + if (c == '\n') + { + spos.x = 0; spos.y += 8.0f * scale.y; + } + else if (c == '\t') + { + spos.x += 8.0f * float(nTabSizeInSpaces) * scale.x; + } + else + { + int32_t ox = (c - 32) % 16; + int32_t oy = (c - 32) / 16; + DrawPartialDecal(pos + spos - 1, shadowFontRenderable.Decal(), {float(ox) * 10.0f, float(oy) * 10.0f}, {10.0f, 10.0f}, scale, shadowCol,transform); + DrawPartialDecal(pos + spos, fontRenderable.Decal(), {float(ox) * 8.0f, float(oy) * 8.0f}, {8.0f, 8.0f}, scale, col,transform); + spos.x += 8.0f * scale.x; + } + } + } void PixelGameEngine::DrawStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const olc::vf2d& scale,const GFX3DTransform transform) { @@ -3440,6 +3468,29 @@ namespace olc } } } + void PixelGameEngine::DrawShadowStringPropDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const GFX3DTransform transform) + { + olc::vf2d spos = { 0.0f, 0.0f }; + for (auto c : sText) + { + if (c == '\n') + { + spos.x = 0; spos.y += 8.0f * scale.y; + } + else if (c == '\t') + { + spos.x += 8.0f * float(nTabSizeInSpaces) * scale.x; + } + else + { + int32_t ox = (c - 32) % 16; + int32_t oy = (c - 32) / 16; + DrawPartialDecal(pos + spos - 1, shadowFontRenderable.Decal(), { float(ox) * 10.0f + float(vFontSpacing[c - 32].x), float(oy) * 10.0f }, { float(vFontSpacing[c - 32].y)+2.f, 10.0f }, scale, shadowCol,transform); + DrawPartialDecal(pos + spos, fontRenderable.Decal(), { float(ox) * 8.0f + float(vFontSpacing[c - 32].x), float(oy) * 8.0f }, { float(vFontSpacing[c - 32].y), 8.0f }, scale, col,transform); + spos.x += float(vFontSpacing[c - 32].y) * scale.x; + } + } + } // Thanks Oso-Grande/Sopadeoso For these awesom and stupidly clever Text Rotation routines... duh XD void PixelGameEngine::DrawRotatedStringDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center, const Pixel col, const olc::vf2d& scale,const GFX3DTransform transform) { @@ -3486,6 +3537,54 @@ namespace olc } } } + // Thanks Oso-Grande/Sopadeoso For these awesom and stupidly clever Text Rotation routines... duh XD + void PixelGameEngine::DrawShadowRotatedStringDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const GFX3DTransform transform) + { + olc::vf2d spos = center; + for (auto c : sText) + { + if (c == '\n') + { + spos.x = center.x; spos.y -= 8.0f; + } + else if (c == '\t') + { + spos.x += 8.0f * float(nTabSizeInSpaces) * scale.x; + } + else + { + int32_t ox = (c - 32) % 16; + int32_t oy = (c - 32) / 16; + DrawPartialRotatedDecal(pos-scale, shadowFontRenderable.Decal(), fAngle, spos, { float(ox) * 10.0f, float(oy) * 10.0f }, { 10.0f, 10.0f }, scale, shadowCol,transform); + DrawPartialRotatedDecal(pos, fontRenderable.Decal(), fAngle, spos, { float(ox) * 8.0f, float(oy) * 8.0f }, { 8.0f, 8.0f }, scale, col,transform); + spos.x -= 8.0f; + } + } + } + + void PixelGameEngine::DrawShadowRotatedStringPropDecal(const olc::vf2d& pos, const std::string& sText, const float fAngle, const olc::vf2d& center, const Pixel col, const Pixel shadowCol, const olc::vf2d& scale,const GFX3DTransform transform) + { + olc::vf2d spos = center; + for (auto c : sText) + { + if (c == '\n') + { + spos.x = center.x; spos.y -= 8.0f; + } + else if (c == '\t') + { + spos.x += 8.0f * float(nTabSizeInSpaces) * scale.x; + } + else + { + int32_t ox = (c - 32) % 16; + int32_t oy = (c - 32) / 16; + DrawPartialRotatedDecal(pos-scale, shadowFontRenderable.Decal(), fAngle, spos, { float(ox) * 10.0f + float(vFontSpacing[c - 32].x), float(oy) * 10.0f }, { float(vFontSpacing[c - 32].y)+2.f, 10.0f }, scale, shadowCol,transform); + DrawPartialRotatedDecal(pos, fontRenderable.Decal(), fAngle, spos, { float(ox) * 8.0f + float(vFontSpacing[c - 32].x), float(oy) * 8.0f }, { float(vFontSpacing[c - 32].y), 8.0f }, scale, col,transform); + spos.x -= float(vFontSpacing[c - 32].y); + } + } + } olc::vi2d PixelGameEngine::GetTextSize(const std::string& s) { @@ -4159,6 +4258,7 @@ namespace olc data += "?P9PL020O`<`N3R0@E4HC7b0@ET