#define OLC_PGE_APPLICATION #include "olcPixelGameEngine.h" using namespace olc; #define PI 3.14159 // Override base class with your custom functionality class SmartPointerExample : public olc::PixelGameEngine { struct DamageNumber{ vf2d pos; int dmg; float timer=0; bool dead=false; float stopTimer=0; void Update(SmartPointerExample*pge, float fElapsedTime){ if(stopTimer>0){ stopTimer-=fElapsedTime; } else { timer-=fElapsedTime; pos.y-=12*fElapsedTime; } if(timer<=0){ dead=true; } } }; std::shared_ptr CreateDamageNumber(vf2d pos,int dmg){ std::shared_ptr ptr=std::make_shared(pos,dmg,2); damageNumbers.push_back(ptr); return ptr; }; struct Object{ vf2d pos; Renderable&r; Pixel col; float radius; float dir; vf2d spd; bool friendly=false; bool dead=false; int health=100; float invulnTimer=0; const float friction=100; std::shared_ptrptrDamageNumber=nullptr; Object(vf2d pos,Renderable&r,Pixel col,float radius,float dir) :pos(pos),r(r),col(col),radius(radius),dir(dir){}; virtual void Collision(SmartPointerExample*pge,Object&collisionObj){}; void InternalUpdate(SmartPointerExample*pge,float fElapsedTime){ pos+=spd*fElapsedTime; pos.x=std::max(0.f,std::min(float(pge->ScreenWidth()),pos.x)); pos.y=std::max(0.f,std::min(float(pge->ScreenHeight()),pos.y)); if(spd.x>0){ spd.x=std::max(0.f,spd.x-friction*fElapsedTime); } else { spd.x=std::min(0.f,spd.x+friction*fElapsedTime); } if(spd.y>0){ spd.y=std::max(0.f,spd.y-friction*fElapsedTime); } else { spd.y=std::min(0.f,spd.y+friction*fElapsedTime); } if(spd.x!=0||spd.y!=0){ vf2d normSpd = spd.norm(); dir=atan2(normSpd.y,normSpd.x); } if(health<=0){ dead=true; } invulnTimer=std::max(0.f,invulnTimer-fElapsedTime); } virtual void Update(SmartPointerExample * pge, float fElapsedTime){} virtual void Draw(SmartPointerExample*pge){ pge->DrawRotatedDecal(pos,r.Decal(),dir,r.Sprite()->Size()/2,{1,1},col); }; }; struct Player:Object{ Player(vf2d pos,Renderable&r,Pixel col,float radius,float dir) :Object(pos,r,col,radius,dir){ friendly=true; } void Collision(SmartPointerExample*pge,Object&collisionObj)override{ if(!collisionObj.friendly&&collisionObj.invulnTimer==0){ collisionObj.health-=10; collisionObj.invulnTimer=0.5; if(collisionObj.ptrDamageNumber!=nullptr){ if(collisionObj.ptrDamageNumber->stopTimer>0||collisionObj.ptrDamageNumber->timer>=1.0){ collisionObj.ptrDamageNumber->dmg+=10; collisionObj.ptrDamageNumber->stopTimer=0.5; } else { std::shared_ptr ptrDamageNumber = pge->CreateDamageNumber(collisionObj.pos,10); collisionObj.ptrDamageNumber=ptrDamageNumber; } } else { std::shared_ptr ptrDamageNumber = pge->CreateDamageNumber(collisionObj.pos,10); collisionObj.ptrDamageNumber=ptrDamageNumber; } } } void Update(SmartPointerExample*pge,float fElapsedTime)override{ if(pge->GetKey(UP).bHeld){ spd.y=-32; } if(pge->GetKey(DOWN).bHeld){ spd.y=32; } if(pge->GetKey(RIGHT).bHeld){ spd.x=32; } if(pge->GetKey(LEFT).bHeld){ spd.x=-32; } } }; struct Enemy:Object{ Enemy(vf2d pos,Renderable&r,Pixel col,float radius,float dir) :Object(pos,r,col,radius,dir){ friendly=false; } }; std::vector>objects; std::vector>damageNumbers; public: SmartPointerExample() { // Name your application sAppName = "Smart Pointer Example"; } Renderable player_img; public: bool OnUserCreate() override { player_img.Load("assets/player.png"); // Called once at the start, so create things here objects.push_back(std::make_unique(vf2d{32,32},player_img,GREEN,8,0)); objects.push_back(std::make_unique(vf2d{64,128},player_img,DARK_RED,8,PI/2)); objects.push_back(std::make_unique(vf2d{96,164},player_img,DARK_RED,8,1.75*PI)); objects.push_back(std::make_unique(vf2d{32,196},player_img,DARK_RED,8,1.25*PI)); objects.push_back(std::make_unique(vf2d{72,220},player_img,DARK_RED,8,PI/8)); return true; } bool OnUserUpdate(float fElapsedTime) override { for(auto&ptrO:objects){ Object*o=ptrO.get(); for(auto&ptrO2:objects){ Object*o2=ptrO2.get(); if(o!=o2){ auto dist = [&](vf2d pos1,vf2d pos2){return sqrt(pow(pos1.x-pos2.x,2)+pow(pos1.y-pos2.y,2));}; if(dist(o->pos,o2->pos)radius+o2->radius){ o->Collision(this,*o2); o2->Collision(this,*o); } } } o->Update(this,fElapsedTime); o->InternalUpdate(this,fElapsedTime); o->Draw(this); } for(auto&ptrDamageNumber:damageNumbers){ ptrDamageNumber->Update(this,fElapsedTime); DrawStringDecal(ptrDamageNumber->pos,std::to_string(ptrDamageNumber->dmg),RED); } std::erase_if(objects,[&](auto&ptrO){return ptrO->dead;}); std::erase_if(damageNumbers,[&](auto&ptrDamageNumber){return ptrDamageNumber->dead;}); return true; } }; int main() { SmartPointerExample demo; if (demo.Construct(256, 240, 4, 4)) demo.Start(); return 0; }