#define OLC_PGE_APPLICATION #define OLC_SOUNDWAVE #define OLC_PGEX_TRANSFORMEDVIEW #include "olcUTIL_Geometry2D.h" #include "TileManager.h" #include "VirusAttack.h" VirusAttack::VirusAttack() { // Name your application sAppName = "olcCodeJam 2023 Entry"; } bool VirusAttack::OnUserCreate(){ game.Initialise(GetScreenSize()); CONSTANT::VIRUS_IMG1.Load("assets/unit.png"); CONSTANT::SELECTION_CIRCLE.Load("assets/selection_circle.png"); TILE.Load("assets/tile.png",nullptr,false,false); MINIMAP_HUD.Load("assets/minimap_hud.png"); OUTLINE.Load("assets/outline.png"); MINIMAP_OUTLINE.Create(64,64); units.push_back(std::make_unique(vf2d{32,32},CONSTANT::VIRUS_IMG1,true)); for(int i=0;i<10;i++){ if(rand()%2==0){ units.push_back(std::make_unique(vf2d{float(rand()%ScreenWidth()),float(rand()%ScreenHeight())},CONSTANT::VIRUS_IMG1,true)); } else { units.push_back(std::make_unique(vf2d{float(rand()%ScreenWidth()),float(rand()%ScreenHeight())},CONSTANT::VIRUS_IMG1,false)); } } return true; } void VirusAttack::HandleDraggingSelection(){ auto NotClickingOnMinimap=[&](){return !(GetMouseX()>=ScreenWidth()-64&&GetMouseY()>=ScreenHeight()-64);}; if(GetMouse(0).bPressed){ if(NotClickingOnMinimap()){ for(auto&u:units){ u->Deselect(); } if(startingDragPos==CONSTANT::UNSELECTED){ startingDragPos=GetWorldMousePos(); } } } if(GetMouse(0).bReleased&&startingDragPos!=CONSTANT::UNSELECTED){ vf2d endDragPos=GetWorldMousePos(); if(endDragPos.x selectionRegion(startingDragPos,endDragPos-startingDragPos); for(auto&u:units){ if(u->IsFriendly()){ if(geom2d::overlaps(selectionRegion,u->GetPos())){ u->Select(); } } } startingDragPos=CONSTANT::UNSELECTED; } } vf2d VirusAttack::GetWorldMousePos(){ return game.ScreenToWorld(GetMousePos()); } void VirusAttack::DrawSelectionRectangle(){ if(startingDragPos!=CONSTANT::UNSELECTED){ game.FillRectDecal(startingDragPos,GetWorldMousePos()-startingDragPos,{255,255,0,128}); } } void VirusAttack::HandleRightClickMove(){ if (GetMouse(1).bPressed){ bool selectedTarget=false; for(auto&u:units){ if(!u->IsFriendly()){ geom2d::rect unitRegion(u->GetPos()-u->GetUnitSize()/2,u->GetUnitSize()); if(geom2d::overlaps(unitRegion,GetWorldMousePos())){ for(auto&u2:units){ if(u2->IsFriendly()&&u2->IsSelected()){ u2->SetTargetUnit(u); } } selectedTarget=true; break; } } } if(!selectedTarget){ for(auto&u:units){ if(u->IsFriendly()&&u->IsSelected()){ u->SetTargetLocation(GetWorldMousePos()); } } } } } void VirusAttack::CollisionChecking(std::shared_ptru,std::shared_ptru2){ if(u!=u2&&geom2d::overlaps(geom2d::circle(u->GetPos(),u->GetUnitSize().x/2),geom2d::circle(u2->GetPos(),u2->GetUnitSize().x/2))){ geom2d::linecollisionLine(u->GetPos(),u2->GetPos()); float maxDist=u->GetUnitSize().x/2+u2->GetUnitSize().x/2; float dist=maxDist-collisionLine.length(); vf2d dir=collisionLine.vector().norm(); u->SetPos(u->GetPos()-dir*dist/2); u2->SetPos(u2->GetPos()+dir*dist/2); } } void VirusAttack::IdentifyClosestTarget(Unit*&closestUnit,float&closestDist,std::shared_ptru,std::shared_ptru2){ if(u->IsFriendly()!=u2->IsFriendly()){ geom2d::lineunitLine(u->GetPos(),u2->GetPos()); if(unitLine.length()Size(),MINIMAP_HUD.Decal(),{1,1}); vf2d minimapTL=GetScreenSize()-vf2d{64,64}; vi2d worldPixelSize=CONSTANT::WORLD_SIZE*CONSTANT::TILE_SIZE; vf2d viewingTilesPct=vf2d{float(ScreenWidth()),float(ScreenHeight())}/CONSTANT::TILE_SIZE/CONSTANT::WORLD_SIZE; SetDrawTarget(MINIMAP_OUTLINE.Sprite()); for(int y=0;y<64;y++){ for(int x=0;x<64;x++){ Draw(x,y,BLANK); } } DrawRect((game.GetWorldOffset()/worldPixelSize*64),viewingTilesPct*64/game.GetWorldScale()); for(auto&u:units){ FillRect(u->GetGhostPos()/worldPixelSize*64,vf2d{2,2}*u->GetUnitSize()/24,u->IsFriendly()?GREEN:RED); } MINIMAP_OUTLINE.Decal()->Update(); SetDrawTarget(nullptr); DrawDecal(minimapTL,MINIMAP_OUTLINE.Decal()); } void VirusAttack::HandlePanAndZoom(float fElapsedTime){ float speedScale=std::min(1.f,game.GetWorldScale().x); if(GetKey(A).bHeld){ game.MoveWorldOffset(vf2d{-256*fElapsedTime,0}/speedScale); } if(GetKey(W).bHeld){ game.MoveWorldOffset(vf2d{0,-256*fElapsedTime}/speedScale); } if(GetKey(S).bHeld){ game.MoveWorldOffset(vf2d{0,256*fElapsedTime}/speedScale); } if(GetKey(D).bHeld){ game.MoveWorldOffset(vf2d{256*fElapsedTime,0}/speedScale); } if(GetMouseWheel()>0){ if(game.GetWorldScale().x<2){ game.ZoomAtScreenPos(1.25,GetMousePos()); } } else if(GetMouseWheel()<0){ if(game.GetWorldScale().x>0.5){ game.ZoomAtScreenPos(0.75,GetMousePos()); } } } void VirusAttack::HandleMinimapClick(){ if(startingDragPos==CONSTANT::UNSELECTED&&GetMouse(0).bHeld&&GetMouseX()>=ScreenWidth()-64&&GetMouseY()>=ScreenHeight()-64){ vf2d minimapTL=GetScreenSize()-vf2d{64,64}; game.SetWorldOffset(vf2d(GetMousePos()-minimapTL)/64*CONSTANT::WORLD_SIZE*CONSTANT::TILE_SIZE-vf2d(GetScreenSize())/game.GetWorldScale()/2.f); } } bool VirusAttack::OnUserUpdate(float fElapsedTime){ HandleDraggingSelection(); HandleRightClickMove(); HandlePanAndZoom(fElapsedTime); HandleMinimapClick(); for(auto&tile:TileManager::visibleTiles){ tile.second-=fElapsedTime; } std::erase_if(TileManager::visibleTiles,[](std::pair key){return key.second<=0;}); for(auto&u:units){ Unit*closestUnit=nullptr; float closestDist=999999; for(auto&u2:units){ IdentifyClosestTarget(closestUnit,closestDist,u,u2); CollisionChecking(u,u2); } if(u->IsFriendly()){ for(int y=-1;y<2;y++){ for(int x=-1;x<2;x++){ TileManager::visibleTiles[u->GetPos()/24/4+vi2d(x,y)]=5; } } } u->AttemptAttack(closestUnit); u->Update(fElapsedTime); } for(auto&u:units){ if(!u->GhostInFogOfWar()&&u->InFogOfWar()){ u->HideGhost(); } } game.DrawPartialDecal({0,0},CONSTANT::WORLD_SIZE*CONSTANT::TILE_SIZE,TILE.Decal(),{0,0},CONSTANT::WORLD_SIZE*CONSTANT::TILE_SIZE,DARK_GREEN); for(auto&u:units){ u->Draw(game); } for(auto&u:units){ u->DrawHud(game); } DrawSelectionRectangle(); 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<=CONSTANT::WORLD_SIZE.x*CONSTANT::TILE_SIZE.x&&y<=CONSTANT::WORLD_SIZE.y*CONSTANT::TILE_SIZE.y){ game.FillRectDecal(vf2d{float(x),float(y)}*96,{96,96},{0,0,0,128}); } } } } DrawMinimap(); return true; } int main() { VirusAttack app; if (app.Construct(426, 320, 4, 4)) app.Start(); return 0; }