* switched to shader version

This commit is contained in:
end 2016-09-28 03:33:01 +02:00
commit d2d8039589
11 changed files with 167 additions and 62 deletions

View file

@ -11,9 +11,13 @@
#include "state/player.hpp" #include "state/player.hpp"
#include "state/planet.hpp" #include "state/planet.hpp"
#include "state/ship.hpp" #include "state/ship.hpp"
#include "state/explosion.hpp"
class GameWindow : public endofthejedi::GLWindow { class GameWindow : public endofthejedi::GLWindow {
private: private:
Game m_game;
endofthejedi::Renderer m_renderer;
protected: protected:
void init() override { void init() override {
glClearColor(0.5f, 0.6f, 0.7f, 1.0f); glClearColor(0.5f, 0.6f, 0.7f, 1.0f);
@ -37,7 +41,7 @@ class GameWindow : public endofthejedi::GLWindow {
} }
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/*
for (const game::Planet *planet : m_game.state()->planets) { for (const game::Planet *planet : m_game.state()->planets) {
drawPlanet(planet->position, planet->radius); drawPlanet(planet->position, planet->radius);
} }
@ -46,6 +50,10 @@ class GameWindow : public endofthejedi::GLWindow {
drawTrace(trace); drawTrace(trace);
} }
for (const game::Explosion *explosion : m_game.state()->explosions) {
drawExplosion(explosion);
}
for (const game::Ship *ship : m_game.state()->ships) { for (const game::Ship *ship : m_game.state()->ships) {
drawShip(ship->position); drawShip(ship->position);
} }
@ -55,6 +63,8 @@ class GameWindow : public endofthejedi::GLWindow {
drawMissile(missile->position); drawMissile(missile->position);
} }
} }
*/
m_renderer.render(m_game.state());
} }
void resize() override { glViewport(0, 0, getwidth(), getheight()); } void resize() override { glViewport(0, 0, getwidth(), getheight()); }
@ -77,9 +87,7 @@ class GameWindow : public endofthejedi::GLWindow {
32); 32);
} }
void drawMissile(const glm::vec2 &pos) void drawMissile(const glm::vec2 &pos) {
{
glm::vec3 color = glm::vec3(1.0, 1.0, 0.3); 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); m_renderer.drawCircle(pos.x, pos.y, 0.01, color.x, color.y, color.z, 6);
} }
@ -93,11 +101,18 @@ class GameWindow : public endofthejedi::GLWindow {
} }
} }
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: public:
GameWindow(unsigned int width, unsigned int height) GameWindow(unsigned int width, unsigned int height)
: endofthejedi::GLWindow(width, height) {} : endofthejedi::GLWindow(width, height) {}
private:
Game m_game;
endofthejedi::Renderer m_renderer;
}; };

View file

@ -42,12 +42,12 @@ bool endofthejedi::Shader::checkShader(GLuint shader) {
GLint len = 0; GLint len = 0;
GLint result = 0; GLint result = 0;
glGetProgramiv(m_program, GL_LINK_STATUS, &result); glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &len); glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
if (len > 1) { if (len > 1) {
char *error = (char *)malloc(len); char *error = (char *)malloc(len+1);
glGetShaderInfoLog(shader, 0, &len, error); glGetShaderInfoLog(shader, 0, &len, error);
std::string str(error); std::string str(error, error + len);
std::cout << str << "\n"; std::cout << str << "\n";
} }
std::cout << "checked shader" std::cout << "checked shader"
@ -71,3 +71,7 @@ void endofthejedi::Shader::load(std::string path, GLenum shadertype) {
check(); check();
glDeleteShader(cheddar); glDeleteShader(cheddar);
} }
GLuint endofthejedi::Shader::location(std::string name) {
return glGetUniformLocation(m_program, name.c_str());
}

View file

@ -43,8 +43,9 @@ class VAO {
class Shader { class Shader {
private: private:
GLuint m_program; GLuint m_program;
bool check(); bool check();
bool checkShader(GLuint shader); bool checkShader(GLuint shader);
protected: protected:
public: public:
Shader(); Shader();
@ -52,6 +53,7 @@ class Shader {
void bind(); void bind();
void unbind(); void unbind();
void load(std::string data, GLenum shadertype); void load(std::string data, GLenum shadertype);
GLuint location(std::string name);
}; };
} }

View file

@ -7,18 +7,51 @@ static const char *fss =
#include "main.fs" #include "main.fs"
; ;
#include <vector>
#include "glm/glm.hpp"
#include "glm/vec2.hpp"
#include "glm/vec3.hpp"
#include "glm/gtc/type_ptr.hpp"
endofthejedi::Renderer::Renderer() { endofthejedi::Renderer::Renderer() {
m_shader.load(vss, GL_VERTEX_SHADER); m_shader.load(vss, GL_VERTEX_SHADER);
m_shader.load(fss, GL_FRAGMENT_SHADER); m_shader.load(fss, GL_FRAGMENT_SHADER);
} }
endofthejedi::Renderer::~Renderer() {} endofthejedi::Renderer::~Renderer() {}
void endofthejedi::Renderer::render() { void endofthejedi::Renderer::render(const game::State *state) {
m_shader.bind(); m_shader.bind();
std::vector<glm::vec3> positions;
std::vector<glm::vec4> colors;
std::vector<GLfloat> radii;
std::vector<GLfloat> reflections;
for (const game::Planet *planet : state->planets) {
positions.push_back(glm::vec3(planet->position, -10.0f));
radii.push_back(planet->radius);
colors.push_back(glm::vec4(1.0f, 0.0f, 0.0f, 0.5f));
}
glUniform1f(m_shader.location("aspectratio"), 16.0f/9.0f);
glUniform1i(m_shader.location("reflections"), 1);
glUniform3f(m_shader.location("l_position"), 0.6f, 0.1f, 0.0f);
glUniform1f(m_shader.location("l_radius"), 1.0f);
glUniform3fv(m_shader.location("s_positions"), positions.size(),
glm::value_ptr(positions[0]));
glUniform4fv(m_shader.location("s_colors"), colors.size(),
glm::value_ptr(colors[0]));
glUniform1fv(m_shader.location("s_radii"), radii.size(), &radii[0]);
glUniform1i(m_shader.location("s_length"), positions.size());
// render fullscreen quad with legacy opengl (too lazy, sorry)
glBegin(GL_QUADS);
glVertex2f(-1.0f, -1.0f);
glVertex2f(1.0f, -1.0f);
glVertex2f(1.0f, 1.0f);
glVertex2f(-1.0f, 1.0f);
glEnd();
} }
void endofthejedi::Renderer::drawCircle(float x, float y, float radius, float r, void endofthejedi::Renderer::drawCircle(float x, float y, float radius, float r,

View file

@ -6,20 +6,20 @@
#include <epoxy/glx.h> #include <epoxy/glx.h>
#include "glclasses.hpp" #include "glclasses.hpp"
#include "game.hpp"
#include "state/planet.hpp"
namespace endofthejedi { namespace endofthejedi {
class Renderer { class Renderer {
private: private:
VBO m_vbo;
VAO m_vao;
Shader m_shader; Shader m_shader;
protected: protected:
public: public:
Renderer(); Renderer();
~Renderer(); ~Renderer();
void render(); void render(const game::State* state);
void drawCircle(float x, float y, float radius, float r, float g, float b, void drawCircle(float x, float y, float radius, float r, float g, float b,
int numSides = 12); int numSides = 12);
}; };

View file

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

View file

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

View file

@ -3,6 +3,8 @@
#include <glm/vec2.hpp> #include <glm/vec2.hpp>
#include <glm/vec3.hpp> #include <glm/vec3.hpp>
#include "missile_hit_type.hpp"
namespace game { namespace game {
class State; class State;
class Ship; class Ship;
@ -15,36 +17,29 @@ namespace game {
// trace then belongs to the player. // trace then belongs to the player.
class Missile { class Missile {
public: public:
enum class HitObject {
Nothing,
HitPlayer,
HitPlanet,
// HitMissile,
LeftUniverse
};
// missile advances to pos. if hit != Nothing, it hits something and // missile advances to pos. if hit != Nothing, it hits something and
// stops existing afterwards. // stops existing afterwards.
class Event { class Event {
public: 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) Event(const glm::vec2 &pos, Hit hit)
: hit(hit), pos(pos) : hit(hit), position(pos)
{ {
} }
Event(const glm::vec2 &pos, int playerIdKiller, int playerIdVictim) Event(const glm::vec2 &pos, int playerIdKiller, int playerIdVictim)
: Event(pos, HitObject::HitPlayer) : Event(pos, Hit::Ship)
{ {
this->playerIdKiller = playerIdKiller; this->playerIdKiller = playerIdKiller;
this->playerIdVictim = playerIdVictim; this->playerIdVictim = playerIdVictim;
} }
HitObject hit; Hit hit;
glm::vec2 pos; glm::vec2 position;
int playerIdKiller; int playerIdKiller;
int playerIdVictim; 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/vec3.hpp>
#include <glm/gtx/norm.hpp> #include <glm/gtx/norm.hpp>
#include "missile_hit_type.hpp"
#include "object.hpp" #include "object.hpp"
#include "missile.hpp" #include "missile.hpp"
#include "player.hpp" #include "player.hpp"
@ -13,6 +14,7 @@
#include "ship.hpp" #include "ship.hpp"
#include "commands.hpp" #include "commands.hpp"
#include "trace.hpp" #include "trace.hpp"
#include "explosion.hpp"
#include "util.hpp" #include "util.hpp"
@ -43,7 +45,9 @@ namespace game {
} }
} while(glm::length(pos) < 0.2 && tries++ < 1000); } while(glm::length(pos) < 0.2 && tries++ < 1000);
planets.push_back(new Planet(pos, 0.03 + 0.07*util::randf_0_1())); pos.x *= 10;
pos.y *= 10;
planets.push_back(new Planet(pos, (0.03 + 0.07*util::randf_0_1()) * 10));
} }
} }
@ -162,26 +166,25 @@ namespace game {
//std::cout<<"missile: " << (long unsigned int) missile << std::endl; //std::cout<<"missile: " << (long unsigned int) missile << std::endl;
const Missile::Event evt = missile->advance(this, dt); const Missile::Event evt = missile->advance(this, dt);
missile->trace->addPointFromMissile(); const bool isHit = (evt.hit != Hit::Nothing);
// TODO: missile->trace->addPointFromMissile(isHit); // force point if missile gets destroyed a
// spawn just if the path differs
if (evt.hit == Missile::HitObject::Nothing) { if (!isHit) {
i++; i++;
} else { } else {
switch(evt.hit) { switch(evt.hit) {
case Missile::HitObject::HitPlanet: case Hit::Planet:
//std::cout<<"hit Planet" << std::endl; //std::cout<<"hit Planet" << std::endl;
break; break;
case Missile::HitObject::HitPlayer: case Hit::Ship:
//std::cout<<"hit Player" << std::endl; //std::cout<<"hit Player" << std::endl;
playerKillsPlayer(playerForId(evt.playerIdKiller), playerForId(evt.playerIdVictim)); playerKillsPlayer(playerForId(evt.playerIdKiller), playerForId(evt.playerIdVictim));
break; break;
case Missile::HitObject::LeftUniverse: case Hit::BorderOfUniverse:
//std::cout<<"missile left the universe." << std::endl; //std::cout<<"missile left the universe." << std::endl;
break; break;
@ -189,6 +192,8 @@ namespace game {
break; break;
} }
addExplosionFromHit(&evt);
player->missiles.erase(player->missiles.begin() + i); player->missiles.erase(player->missiles.begin() + i);
delete(missile); delete(missile);
//std::cout<<std::endl; //std::cout<<std::endl;
@ -200,16 +205,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) void State::advance(float dt)
{ {
//std::cout<<"advance ship spawns" << std::endl;
advancePlayerShipSpawns(dt); advancePlayerShipSpawns(dt);
//std::cout<<"advance commands" << std::endl; advanceExplosions(dt);
advancePlayerCommands(dt); advancePlayerCommands(dt);
//std::cout<<"advance missiles" << std::endl;
advancePlayerMissiles(dt); advancePlayerMissiles(dt);
} }
Player *State::playerForId(int playerId) Player *State::playerForId(int playerId)
@ -270,4 +291,13 @@ namespace game {
{ {
traces.push_back(trace); 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 <glm/vec2.hpp>
#include "missile.hpp"
namespace game { namespace game {
// forward declarations // forward declarations
class Command; class Command;
class Missile;
class Player; class Player;
class Planet; class Planet;
class Ship; class Ship;
class Trace; class Trace;
class Explosion;
class State { class State {
public: public:
@ -61,10 +63,11 @@ namespace game {
// Game items which should be rendered are here: // Game items which should be rendered are here:
// (access missiles by iterating over player's missiles attribute) // (access missiles by iterating over player's missiles attribute)
std::vector<Planet*> planets; std::vector<Planet*> planets;
std::vector<Ship*> ships; std::vector<Ship*> ships;
std::vector<Player*> players; std::vector<Player*> players;
std::vector<Trace*> traces; std::vector<Trace*> traces;
std::vector<Explosion*> explosions;
private: private:
/*************************************************************************/ /*************************************************************************/
@ -73,6 +76,9 @@ namespace game {
void playerKillsPlayer(Player *killer, Player *victim); void playerKillsPlayer(Player *killer, Player *victim);
void addExplosionFromHit(const Missile::Event *evt);
void advanceExplosions(float dt);
void advancePlayerShipSpawns(float dt); void advancePlayerShipSpawns(float dt);
void advancePlayerCommands(float dt); void advancePlayerCommands(float dt);
void advancePlayerMissiles(float dt); void advancePlayerMissiles(float dt);