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.
220 lines
4.4 KiB
220 lines
4.4 KiB
#define OLC_PGE_APPLICATION
|
|
#include "olcPixelGameEngine.h"
|
|
|
|
struct Rect{
|
|
int x,y,w,h;
|
|
};
|
|
|
|
class Enemy{
|
|
olc::vf2d pos;
|
|
Rect*sprite;
|
|
int health;
|
|
public:
|
|
Enemy(olc::vi2d pos,Rect*sprite,int health=1)
|
|
:pos(pos),sprite(sprite),health(health){};
|
|
olc::vf2d GetPos(){
|
|
return pos;
|
|
}
|
|
olc::vi2d GetSprPos(){
|
|
return {sprite->x,sprite->y};
|
|
}
|
|
olc::vi2d GetSprSize(){
|
|
return {sprite->w,sprite->h};
|
|
}
|
|
void Hurt(int damage=1){
|
|
health-=damage;
|
|
}
|
|
bool IsAlive(){
|
|
return health>0;
|
|
}
|
|
void Move(olc::vi2d moveAmt){
|
|
pos+=moveAmt;
|
|
}
|
|
olc::Pixel GetColor(){
|
|
if(health>1){
|
|
return {255,96,96};
|
|
} else {
|
|
return olc::GREEN;
|
|
}
|
|
}
|
|
};
|
|
|
|
class Player{
|
|
olc::vf2d pos;
|
|
Rect*sprite;
|
|
float lastShootTime=0;
|
|
public:
|
|
Player(olc::vi2d pos,Rect*sprite)
|
|
:pos(pos),sprite(sprite){}
|
|
olc::vf2d GetPos(){
|
|
return pos;
|
|
}
|
|
olc::vi2d GetSprPos(){
|
|
return {sprite->x,sprite->y};
|
|
}
|
|
olc::vi2d GetSprSize(){
|
|
return {sprite->w,sprite->h};
|
|
}
|
|
void Update(float fElapsedTime){
|
|
lastShootTime=std::max(lastShootTime-fElapsedTime,0.f);
|
|
}
|
|
bool CanShoot(){
|
|
return lastShootTime==0;
|
|
}
|
|
void OnShoot(){
|
|
lastShootTime=0.5;
|
|
}
|
|
void Move(olc::vf2d moveAmt){
|
|
pos+=moveAmt;
|
|
}
|
|
};
|
|
|
|
class Bullet{
|
|
olc::vf2d pos;
|
|
bool alive=true;
|
|
public:
|
|
Bullet(olc::vi2d pos)
|
|
:pos(pos){}
|
|
olc::vf2d GetPos(){
|
|
return pos;
|
|
}
|
|
void Update(float fElapsedTime){
|
|
pos+={0,-72*fElapsedTime};
|
|
}
|
|
bool CollidesWith(Enemy&enemy){
|
|
float dist2=pow(enemy.GetPos().x+enemy.GetSprSize().x-pos.x,2)+pow(enemy.GetPos().y+enemy.GetSprSize().y-pos.y,2);
|
|
return dist2<64;
|
|
}
|
|
void KillBullet(){
|
|
alive=false;
|
|
}
|
|
bool IsAlive(){
|
|
return alive||pos.y<0;
|
|
}
|
|
};
|
|
|
|
// Override base class with your custom functionality
|
|
class ShooterExample : public olc::PixelGameEngine
|
|
{
|
|
public:
|
|
ShooterExample()
|
|
{
|
|
// Name your application
|
|
sAppName = "Shooter Example";
|
|
}
|
|
|
|
public:
|
|
olc::Renderable spriteSheet;
|
|
Rect enemyA={5,21, 11,9};
|
|
Rect enemyB={19,22, 12,6};
|
|
Rect enemyC={34,20, 11,8};
|
|
Rect ship={35,6, 11,7};
|
|
|
|
std::vector<Enemy>enemies;
|
|
std::vector<Bullet>bullets;
|
|
|
|
Player player{{ScreenWidth()/2,ScreenHeight()-36},&ship};
|
|
int alienShift=0;
|
|
bool movingRight=true;
|
|
float lastShiftTime=0;
|
|
|
|
bool OnUserCreate() override
|
|
{
|
|
spriteSheet.Load("8-bit Aliens.png");
|
|
|
|
olc::vf2d alienOffset={24,38};
|
|
for (int y=0;y<4;y++){
|
|
for (int x=0;x<12;x++){
|
|
switch(rand()%3){
|
|
case 0:{
|
|
Enemy enemy{alienOffset+olc::vi2d{x*16,y*12},&enemyA};
|
|
enemies.push_back(enemy);
|
|
}break;
|
|
case 1:{
|
|
Enemy enemy{alienOffset+olc::vi2d{x*16,y*12},&enemyB};
|
|
enemies.push_back(enemy);
|
|
}break;
|
|
case 2:{
|
|
Enemy enemy{alienOffset+olc::vi2d{x*16,y*12},&enemyC,2};
|
|
enemies.push_back(enemy);
|
|
}break;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool OnUserUpdate(float fElapsedTime) override
|
|
{
|
|
//Update Game Objects
|
|
player.Update(fElapsedTime);
|
|
|
|
for(Bullet&b:bullets){
|
|
b.Update(fElapsedTime);
|
|
}
|
|
|
|
lastShiftTime+=fElapsedTime;
|
|
if(lastShiftTime>0.8){
|
|
lastShiftTime-=0.8;
|
|
if(abs(alienShift)>=3){
|
|
alienShift+=movingRight?-1:1;
|
|
movingRight=!movingRight;
|
|
for(Enemy&e:enemies){
|
|
e.Move({0,12});
|
|
}
|
|
} else
|
|
if(movingRight){
|
|
alienShift++;
|
|
for(Enemy&e:enemies){
|
|
e.Move({12,0});
|
|
}
|
|
} else {
|
|
alienShift--;
|
|
for(Enemy&e:enemies){
|
|
e.Move({-12,0});
|
|
}
|
|
}
|
|
}
|
|
|
|
if(GetKey(olc::SPACE).bHeld){
|
|
if(player.CanShoot()){
|
|
player.OnShoot();
|
|
bullets.push_back({player.GetPos()+player.GetSprSize()});
|
|
}
|
|
}
|
|
if(GetKey(olc::LEFT).bHeld){
|
|
player.Move({-48*fElapsedTime,0});
|
|
}
|
|
if(GetKey(olc::RIGHT).bHeld){
|
|
player.Move({48*fElapsedTime,0});
|
|
}
|
|
|
|
// Called once per frame, draws random coloured pixels
|
|
Clear(olc::BLACK);
|
|
for(Enemy&e:enemies){
|
|
for(Bullet&b:bullets){
|
|
if(!b.IsAlive())continue;
|
|
if(b.CollidesWith(e)){
|
|
e.Hurt();
|
|
b.KillBullet();
|
|
}
|
|
DrawLineDecal(b.GetPos(),b.GetPos()+olc::vi2d{0,-4},olc::WHITE);
|
|
}
|
|
DrawPartialDecal(e.GetPos()+e.GetSprSize()/2,e.GetSprSize(),spriteSheet.Decal(),e.GetSprPos(),e.GetSprSize(),e.GetColor());
|
|
}
|
|
|
|
DrawPartialDecal(player.GetPos()+player.GetSprSize()/2,player.GetSprSize(),spriteSheet.Decal(),player.GetSprPos(),player.GetSprSize());
|
|
|
|
enemies.erase(std::remove_if(enemies.begin(),enemies.end(),[](Enemy&e){return !e.IsAlive();}),enemies.end());
|
|
bullets.erase(std::remove_if(bullets.begin(),bullets.end(),[](Bullet&b){return !b.IsAlive();}),bullets.end());
|
|
return true;
|
|
}
|
|
};
|
|
|
|
int main()
|
|
{
|
|
ShooterExample demo;
|
|
if (demo.Construct(256, 240, 4, 4))
|
|
demo.Start();
|
|
return 0;
|
|
} |