adding really nice explosion (in simple renderer)

This commit is contained in:
Andreas Ortmann 2016-09-27 21:16:55 +02:00
parent 2b85397674
commit cc17c10e1f
7 changed files with 106 additions and 42 deletions

View file

@ -11,6 +11,7 @@
#include "state/player.hpp"
#include "state/planet.hpp"
#include "state/ship.hpp"
#include "state/explosion.hpp"
class GameWindow : public endofthejedi::GLWindow {
private:
@ -46,6 +47,10 @@ protected:
drawTrace(trace);
}
for (const game::Explosion *explosion : m_game.state()->explosions) {
drawExplosion(explosion);
}
for (const game::Ship *ship : m_game.state()->ships) {
drawShip(ship->position);
}
@ -78,7 +83,6 @@ protected:
}
void drawMissile(const glm::vec2 &pos)
{
glm::vec3 color = glm::vec3(1.0, 1.0, 0.3);
m_renderer.drawCircle(pos.x, pos.y, 0.01, color.x, color.y, color.z, 6);
@ -92,6 +96,17 @@ protected:
}
}
void drawExplosion(const game::Explosion *explosion)
{
// TODO: transparent
// TODO: with glow in the middle
float r = explosion->maxRadius * (explosion->age / explosion->maxAge);
// TODO: transparency?
glm::vec3 color = glm::vec3(1.0, 0.9, 0.1);
m_renderer.drawCircle(explosion->position.x, explosion->position.y, r, color.x, color.y, color.z, 64);
}
public:
GameWindow(unsigned int width, unsigned int height)
: endofthejedi::GLWindow(width, height) {}

View file

@ -2,31 +2,32 @@
#include <glm/vec2.hpp>
#include "util.hpp"
#include "missile_hit_type.hpp"
namespace game {
/**
* Explosion: just an effect which looks good.
*/
class Explosion {
public:
enum class Kind {
MissileExplodesInSpace, // missile explode in free space
MissileAgainstPlanet, // explosion of missile when it hits a planet
MissileAgainstShip // bigger explosion: missile hits a ship which explodes with it
};
Explosion(const glm::vec2 &pos, Kind kind, float maxAge=1.0)
: position(pos), kind(kind), age(0.0), maxAge(maxAge)
Explosion(const glm::vec2 &pos, Hit hit, float maxAge=1.0)
: hit(hit)
, position(pos)
, age(0.0)
, maxAge(maxAge * (1.0 + 0.1*util::randf_0_1()))
, maxRadius(0.05)
{
}
const Kind kind; // kind of the explosion
const Hit hit; // kind of the explosion depends on the hit type
const glm::vec2 position; // position where it starts
float age; // age (in seconsd) of the explosion
// age (in seconds) when the explosion is not visible
// anymore and will disappear afterwards
const float maxAge;
const float maxRadius; // current radius depends on time.
};
}
#endif

View file

@ -49,7 +49,7 @@ namespace game {
if (dist <= planet->radius) {
// TODO: collect all hits and return the first one only
// TODO: find exact hit position!
return Missile::Event(position, Missile::HitObject::HitPlanet);
return Missile::Event(position, Hit::Planet);
}
dist *= 20.0;
@ -77,7 +77,7 @@ namespace game {
// check if distance to center of the universe is getting too big
float distToCenter = glm::length(position);
if (distToCenter > state->maxMissileDistance()) {
return Missile::Event(position, Missile::HitObject::LeftUniverse);
return Missile::Event(position, Hit::BorderOfUniverse);
}
return Missile::Event(position);

View file

@ -3,6 +3,8 @@
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include "missile_hit_type.hpp"
namespace game {
class State;
class Ship;
@ -15,36 +17,29 @@ namespace game {
// trace then belongs to the player.
class Missile {
public:
enum class HitObject {
Nothing,
HitPlayer,
HitPlanet,
// HitMissile,
LeftUniverse
};
// missile advances to pos. if hit != Nothing, it hits something and
// stops existing afterwards.
class Event {
public:
Event(const glm::vec2 &pos) : Event(pos, HitObject::Nothing)
Event(const glm::vec2 &pos) : Event(pos, Hit::Nothing)
{
}
Event(const glm::vec2 &pos, HitObject hit)
: hit(hit), pos(pos)
Event(const glm::vec2 &pos, Hit hit)
: hit(hit), position(pos)
{
}
Event(const glm::vec2 &pos, int playerIdKiller, int playerIdVictim)
: Event(pos, HitObject::HitPlayer)
: Event(pos, Hit::Ship)
{
this->playerIdKiller = playerIdKiller;
this->playerIdVictim = playerIdVictim;
}
HitObject hit;
glm::vec2 pos;
Hit hit;
glm::vec2 position;
int playerIdKiller;
int playerIdVictim;

View file

@ -0,0 +1,19 @@
#pragma once
namespace game {
/*
* A missile can hit different objects the type says which one.
* Used in various places so extra file for this.
*/
enum class Hit {
Nothing,
Ship,
Planet,
// TODO could be needed for really fancy explosions because
// this is cool and should noh happen very often
// AgainstMissile,
BorderOfUniverse
};
}

View file

@ -6,6 +6,7 @@
#include <glm/vec3.hpp>
#include <glm/gtx/norm.hpp>
#include "missile_hit_type.hpp"
#include "object.hpp"
#include "missile.hpp"
#include "player.hpp"
@ -13,6 +14,7 @@
#include "ship.hpp"
#include "commands.hpp"
#include "trace.hpp"
#include "explosion.hpp"
#include "util.hpp"
@ -162,26 +164,25 @@ namespace game {
//std::cout<<"missile: " << (long unsigned int) missile << std::endl;
const Missile::Event evt = missile->advance(this, dt);
missile->trace->addPointFromMissile();
const bool isHit = (evt.hit != Hit::Nothing);
// TODO:
// spawn just if the path differs
missile->trace->addPointFromMissile(isHit); // force point if missile gets destroyed a
if (evt.hit == Missile::HitObject::Nothing) {
if (!isHit) {
i++;
} else {
switch(evt.hit) {
case Missile::HitObject::HitPlanet:
case Hit::Planet:
//std::cout<<"hit Planet" << std::endl;
break;
case Missile::HitObject::HitPlayer:
case Hit::Ship:
//std::cout<<"hit Player" << std::endl;
playerKillsPlayer(playerForId(evt.playerIdKiller), playerForId(evt.playerIdVictim));
break;
case Missile::HitObject::LeftUniverse:
case Hit::BorderOfUniverse:
//std::cout<<"missile left the universe." << std::endl;
break;
@ -189,6 +190,8 @@ namespace game {
break;
}
addExplosionFromHit(&evt);
player->missiles.erase(player->missiles.begin() + i);
delete(missile);
//std::cout<<std::endl;
@ -200,16 +203,32 @@ namespace game {
}
}
void State::advanceExplosions(float dt)
{
size_t i=0;
while(i < explosions.size()) {
Explosion *explosion = explosions[i];
explosion->age += dt;
if (explosion->age >= explosion->maxAge) {
delete(explosion);
explosions.erase(explosions.begin()+i);
continue;
}
i++;
}
}
void State::advance(float dt)
{
//std::cout<<"advance ship spawns" << std::endl;
advancePlayerShipSpawns(dt);
//std::cout<<"advance commands" << std::endl;
advanceExplosions(dt);
advancePlayerCommands(dt);
//std::cout<<"advance missiles" << std::endl;
advancePlayerMissiles(dt);
}
Player *State::playerForId(int playerId)
@ -270,4 +289,13 @@ namespace game {
{
traces.push_back(trace);
}
void State::addExplosionFromHit(const Missile::Event *evt)
{
if (evt->hit == Hit::Nothing || evt->hit == Hit::BorderOfUniverse) {
return;
}
explosions.push_back(new Explosion(evt->position, evt->hit));
}
}

View file

@ -7,14 +7,16 @@
#include <glm/vec2.hpp>
#include "missile.hpp"
namespace game {
// forward declarations
class Command;
class Missile;
class Player;
class Planet;
class Ship;
class Trace;
class Explosion;
class State {
public:
@ -61,10 +63,11 @@ namespace game {
// Game items which should be rendered are here:
// (access missiles by iterating over player's missiles attribute)
std::vector<Planet*> planets;
std::vector<Ship*> ships;
std::vector<Player*> players;
std::vector<Trace*> traces;
std::vector<Planet*> planets;
std::vector<Ship*> ships;
std::vector<Player*> players;
std::vector<Trace*> traces;
std::vector<Explosion*> explosions;
private:
/*************************************************************************/
@ -73,6 +76,9 @@ namespace game {
void playerKillsPlayer(Player *killer, Player *victim);
void addExplosionFromHit(const Missile::Event *evt);
void advanceExplosions(float dt);
void advancePlayerShipSpawns(float dt);
void advancePlayerCommands(float dt);
void advancePlayerMissiles(float dt);