You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
SmarterPointerExample/SmartPointerExample/SmartPointerExample.cpp

188 lines
5.1 KiB

#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<DamageNumber> CreateDamageNumber(vf2d pos,int dmg){
std::shared_ptr<DamageNumber> ptr=std::make_shared<DamageNumber>(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_ptr<DamageNumber>ptrDamageNumber=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<std::unique_ptr<Object>>objects;
std::vector<std::shared_ptr<DamageNumber>>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<Player>(vf2d{32,32},player_img,GREEN,8,0));
objects.push_back(std::make_unique<Enemy>(vf2d{64,128},player_img,DARK_RED,8,PI/2));
objects.push_back(std::make_unique<Enemy>(vf2d{96,164},player_img,DARK_RED,8,1.75*PI));
objects.push_back(std::make_unique<Enemy>(vf2d{32,196},player_img,DARK_RED,8,1.25*PI));
objects.push_back(std::make_unique<Enemy>(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)<o->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;
}