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.
188 lines
5.1 KiB
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;
|
|
} |