Merge branch 'end'
This commit is contained in:
commit
74b4573c3a
19 changed files with 663 additions and 265 deletions
|
@ -10,8 +10,10 @@ set(GAME_SRC
|
||||||
glclasses.cpp
|
glclasses.cpp
|
||||||
renderer.cpp
|
renderer.cpp
|
||||||
game_window.cpp
|
game_window.cpp
|
||||||
triangle_window.cpp
|
renderer_simple.cpp
|
||||||
|
renderer_shader.cpp
|
||||||
session.cpp
|
session.cpp
|
||||||
|
|
||||||
util.cpp
|
util.cpp
|
||||||
game.cpp
|
game.cpp
|
||||||
state/object.cpp
|
state/object.cpp
|
||||||
|
@ -29,6 +31,8 @@ set(GAME_HEADERS
|
||||||
opengl.hpp
|
opengl.hpp
|
||||||
glclasses.hpp
|
glclasses.hpp
|
||||||
renderer.hpp
|
renderer.hpp
|
||||||
|
renderer_simple.hpp
|
||||||
|
renderer_shader.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
|
@ -39,7 +39,7 @@ bool Game::cycle(float dt)
|
||||||
total += dt;
|
total += dt;
|
||||||
|
|
||||||
float spawnInterval = 0.1;
|
float spawnInterval = 0.1;
|
||||||
while(acc > spawnInterval) {
|
while (acc > spawnInterval) {
|
||||||
acc -= spawnInterval;
|
acc -= spawnInterval;
|
||||||
|
|
||||||
float angle = 2.0 * M_PI * util::randf_0_1();
|
float angle = 2.0 * M_PI * util::randf_0_1();
|
||||||
|
@ -57,19 +57,20 @@ bool Game::cycle(float dt)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//std::cout<<"adding dt: " << dt << std::endl;
|
// std::cout<<"adding dt: " << dt << std::endl;
|
||||||
m_time_for_next_step += dt;
|
m_time_for_next_step += dt;
|
||||||
|
|
||||||
int steps = 0;
|
int steps = 0;
|
||||||
while(m_time_for_next_step >= m_time_step) {
|
while (m_time_for_next_step >= m_time_step) {
|
||||||
//std::cout<<"time now: " << m_time_for_next_step << std::endl;
|
// std::cout<<"time now: " << m_time_for_next_step << std::endl;
|
||||||
m_time_for_next_step -= m_time_step;
|
m_time_for_next_step -= m_time_step;
|
||||||
|
|
||||||
m_state->advance(m_time_step);
|
m_state->advance(m_time_step);
|
||||||
steps++;
|
steps++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//std::cout << m_time_for_next_step << " s remaining time, " << steps << " steps taken." << std::endl;
|
// std::cout << m_time_for_next_step << " s remaining time, " << steps << "
|
||||||
|
// steps taken." << std::endl;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "state/state.hpp"
|
#include "state/state.hpp"
|
||||||
|
|
||||||
class Game {
|
class Game {
|
||||||
public:
|
public:
|
||||||
Game();
|
Game();
|
||||||
|
|
||||||
// main method of the game. run this regulary
|
// main method of the game. run this regulary
|
||||||
|
@ -13,7 +13,7 @@ public:
|
||||||
// for rendering
|
// for rendering
|
||||||
game::State *state() const { return m_state; }
|
game::State *state() const { return m_state; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
game::State *m_state;
|
game::State *m_state;
|
||||||
|
|
||||||
float m_time_for_next_step;
|
float m_time_for_next_step;
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include "opengl.hpp"
|
#include "opengl.hpp"
|
||||||
#include "renderer.hpp"
|
#include "renderer.hpp"
|
||||||
|
#include "renderer_simple.hpp"
|
||||||
|
#include "renderer_shader.hpp"
|
||||||
|
|
||||||
#include "game.hpp"
|
#include "game.hpp"
|
||||||
|
|
||||||
|
@ -14,8 +16,11 @@
|
||||||
#include "state/explosion.hpp"
|
#include "state/explosion.hpp"
|
||||||
|
|
||||||
class GameWindow : public endofthejedi::GLWindow {
|
class GameWindow : public endofthejedi::GLWindow {
|
||||||
private:
|
private:
|
||||||
protected:
|
Game* m_game;
|
||||||
|
endofthejedi::RendererSimple m_renderer;
|
||||||
|
|
||||||
|
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);
|
||||||
resize();
|
resize();
|
||||||
|
@ -24,95 +29,29 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
void render(double time) override {
|
void render(double time) override {
|
||||||
//static bool once = false;
|
// static bool once = false;
|
||||||
//if (!once) {
|
// if (!once) {
|
||||||
// once = true;
|
// once = true;
|
||||||
// for (int i=0; i<1000; i++) {
|
// for (int i=0; i<1000; i++) {
|
||||||
// m_game->cycle(time);
|
// m_game->cycle(time);
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
if (!m_game->cycle(static_cast<float>(time/1000000000.0))) {
|
if (!m_game->cycle(static_cast<float>(time / 1000000000.0))) {
|
||||||
std::cout<<"stopping the game..." << std::endl;
|
std::cout << "stopping the game..." << std::endl;
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
m_renderer.render(m_game->state());
|
||||||
drawPlanet(planet->position, planet->radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const game::Trace *trace : m_game->state()->traces) {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const game::Player *player : m_game->state()->players) {
|
|
||||||
for (const game::Missile *missile : player->missiles) {
|
|
||||||
drawMissile(missile->position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize() override { glViewport(0, 0, getwidth(), getheight()); }
|
void resize() override { glViewport(0, 0, getwidth(), getheight()); }
|
||||||
|
|
||||||
void drawShip(const glm::vec2 &pos)
|
public:
|
||||||
{
|
GameWindow(unsigned int width, unsigned int height, Game *ptr)
|
||||||
//std::cout<<"draw ship @ " << pos.x << ", " << pos.y << std::endl;
|
: endofthejedi::GLWindow(width, height) {
|
||||||
glm::vec3 color = glm::vec3(0.2, 1.0, 0.3);
|
m_game = ptr;
|
||||||
|
|
||||||
float radius = m_game->state()->shipRadius();
|
|
||||||
|
|
||||||
m_renderer.drawCircle(pos.x, pos.y, radius, color.x, color.y, color.z, 12);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawPlanet(const glm::vec2 &pos, float radius)
|
|
||||||
{
|
|
||||||
glm::vec3 color = glm::vec3(0.7, 0.1, 0.2);
|
|
||||||
|
|
||||||
//std::cout<<"draw planet @ " << pos.x << ", " << pos.y << std::endl;
|
|
||||||
m_renderer.drawCircle(pos.x, pos.y, radius, color.x, color.y, color.z, 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawTrace(const game::Trace *trace)
|
|
||||||
{
|
|
||||||
for (const game::Trace::TracePoint &p : trace->points) {
|
|
||||||
glm::vec3 color = glm::vec3(0.1, 0.3, 1.0) / (1.0f + 500.0f*p.speed);
|
|
||||||
m_renderer.drawCircle(p.position.x, p.position.y, 0.005, color.x, color.y, color.z, 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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, Game* game)
|
|
||||||
: endofthejedi::GLWindow(width, height) { m_game = game; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Game *m_game;
|
|
||||||
endofthejedi::Renderer m_renderer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#include "glclasses.hpp"
|
#include "glclasses.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
endofthejedi::VAO::VAO() { glGenVertexArrays(1, &m_name); }
|
endofthejedi::VAO::VAO() { glGenVertexArrays(1, &m_name); }
|
||||||
|
|
||||||
endofthejedi::VAO::~VAO() { glDeleteVertexArrays(1, &m_name); }
|
endofthejedi::VAO::~VAO() { glDeleteVertexArrays(1, &m_name); }
|
||||||
|
@ -9,31 +12,66 @@ void endofthejedi::VAO::bind() { glBindVertexArray(m_name); }
|
||||||
void endofthejedi::VAO::fill(GLuint index, GLint size, GLenum type,
|
void endofthejedi::VAO::fill(GLuint index, GLint size, GLenum type,
|
||||||
GLboolean normalized, GLsizei stride,
|
GLboolean normalized, GLsizei stride,
|
||||||
const GLvoid *pointer) {
|
const GLvoid *pointer) {
|
||||||
glEnableVertexAttribArray(index);
|
glEnableVertexAttribArray(index);
|
||||||
glVertexAttribPointer(index, size, GL_FLOAT, normalized, stride, pointer);
|
glVertexAttribPointer(index, size, GL_FLOAT, normalized, stride, pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
endofthejedi::Shader::Shader() {
|
endofthejedi::Shader::Shader() { m_program = glCreateProgram(); }
|
||||||
m_program = glCreateProgram();
|
|
||||||
}
|
|
||||||
|
|
||||||
endofthejedi::Shader::~Shader() {}
|
endofthejedi::Shader::~Shader() {}
|
||||||
|
|
||||||
void endofthejedi::Shader::bind() {
|
bool endofthejedi::Shader::check() {
|
||||||
glUseProgram(m_program);
|
GLint len = 0;
|
||||||
|
GLint result = 0;
|
||||||
|
|
||||||
|
glGetProgramiv(m_program, GL_LINK_STATUS, &result);
|
||||||
|
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &len);
|
||||||
|
if (len > 1) {
|
||||||
|
char *error = (char *)malloc(len);
|
||||||
|
glGetProgramInfoLog(m_program, len, NULL, error);
|
||||||
|
std::string str(error);
|
||||||
|
std::cout << str << "\n";
|
||||||
|
}
|
||||||
|
std::cout << "checked program"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
return (bool)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void endofthejedi::Shader::unbind() {
|
bool endofthejedi::Shader::checkShader(GLuint shader) {
|
||||||
glUseProgram(0);
|
GLint len = 0;
|
||||||
|
GLint result = 0;
|
||||||
|
|
||||||
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
|
||||||
|
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
|
||||||
|
if (len > 1) {
|
||||||
|
char *error = (char *)malloc(len+1);
|
||||||
|
glGetShaderInfoLog(shader, 0, &len, error);
|
||||||
|
std::string str(error, error + len);
|
||||||
|
std::cout << str << "\n";
|
||||||
|
}
|
||||||
|
std::cout << "checked shader"
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
return (bool)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void endofthejedi::Shader::bind() { glUseProgram(m_program); }
|
||||||
|
|
||||||
|
void endofthejedi::Shader::unbind() { glUseProgram(0); }
|
||||||
|
|
||||||
void endofthejedi::Shader::load(std::string path, GLenum shadertype) {
|
void endofthejedi::Shader::load(std::string path, GLenum shadertype) {
|
||||||
GLuint cheddar = glCreateShader(shadertype);
|
GLuint cheddar = glCreateShader(shadertype);
|
||||||
const char* cheddardata = path.c_str();
|
const char *cheddardata = path.c_str();
|
||||||
glShaderSource(cheddar, 1, &cheddardata, NULL);
|
glShaderSource(cheddar, 1, &cheddardata, NULL);
|
||||||
glCompileShader(cheddar);
|
glCompileShader(cheddar);
|
||||||
glAttachShader(m_program, cheddar);
|
checkShader(cheddar);
|
||||||
glLinkProgram(m_program);
|
glAttachShader(m_program, cheddar);
|
||||||
glDeleteShader(cheddar);
|
glLinkProgram(m_program);
|
||||||
|
check();
|
||||||
|
glDeleteShader(cheddar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLuint endofthejedi::Shader::location(std::string name) {
|
||||||
|
return glGetUniformLocation(m_program, name.c_str());
|
||||||
|
}
|
||||||
|
|
|
@ -8,51 +8,57 @@
|
||||||
namespace endofthejedi {
|
namespace endofthejedi {
|
||||||
|
|
||||||
template <GLenum T> class BufferObject {
|
template <GLenum T> class BufferObject {
|
||||||
private:
|
private:
|
||||||
GLuint m_name;
|
GLuint m_name;
|
||||||
GLvoid* m_mappointer;
|
GLvoid *m_mappointer;
|
||||||
protected:
|
|
||||||
public:
|
protected:
|
||||||
BufferObject();
|
public:
|
||||||
~BufferObject();
|
BufferObject();
|
||||||
void bind();
|
~BufferObject();
|
||||||
void bind(GLuint index, GLintptr offset = 0, GLsizeiptr size = 0);
|
void bind();
|
||||||
void fill(GLenum usage, GLsizei size = 0, GLvoid* data = NULL);
|
void bind(GLuint index, GLintptr offset = 0, GLsizeiptr size = 0);
|
||||||
void subfill(GLintptr offset, GLsizei size, const GLvoid* data);
|
void fill(GLenum usage, GLsizei size = 0, GLvoid *data = NULL);
|
||||||
void map(GLenum access);
|
void subfill(GLintptr offset, GLsizei size, const GLvoid *data);
|
||||||
void unmap();
|
void map(GLenum access);
|
||||||
|
void unmap();
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef BufferObject<GL_ARRAY_BUFFER> VBO;
|
typedef BufferObject<GL_ARRAY_BUFFER> VBO;
|
||||||
typedef BufferObject<GL_ELEMENT_ARRAY_BUFFER> IBO;
|
typedef BufferObject<GL_ELEMENT_ARRAY_BUFFER> IBO;
|
||||||
|
|
||||||
class VAO {
|
class VAO {
|
||||||
private:
|
private:
|
||||||
GLuint m_name;
|
GLuint m_name;
|
||||||
protected:
|
|
||||||
public:
|
protected:
|
||||||
VAO();
|
public:
|
||||||
~VAO();
|
VAO();
|
||||||
void bind();
|
~VAO();
|
||||||
void fill(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride = 0, const GLvoid* pointer = NULL);
|
void bind();
|
||||||
|
void fill(GLuint index, GLint size, GLenum type, GLboolean normalized,
|
||||||
|
GLsizei stride = 0, const GLvoid *pointer = NULL);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Shader {
|
class Shader {
|
||||||
private:
|
private:
|
||||||
GLuint m_program;
|
GLuint m_program;
|
||||||
protected:
|
bool check();
|
||||||
public:
|
bool checkShader(GLuint shader);
|
||||||
Shader();
|
|
||||||
~Shader();
|
|
||||||
void bind();
|
|
||||||
void unbind();
|
|
||||||
void load(std::string data, GLenum shadertype);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
public:
|
||||||
|
Shader();
|
||||||
|
~Shader();
|
||||||
|
void bind();
|
||||||
|
void unbind();
|
||||||
|
void load(std::string data, GLenum shadertype);
|
||||||
|
GLuint location(std::string name);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TBufferObject_(pre, post) \
|
#define TBufferObject_(pre, post) \
|
||||||
template <GLenum T> pre endofthejedi::BufferObject<T>::post
|
template <GLenum T> pre endofthejedi::BufferObject<T>::post
|
||||||
#define TBufferObject(...) TBufferObject_(__VA_ARGS__)
|
#define TBufferObject(...) TBufferObject_(__VA_ARGS__)
|
||||||
|
|
||||||
TBufferObject(, BufferObject)() { glGenBuffers(1, &m_name); }
|
TBufferObject(, BufferObject)() { glGenBuffers(1, &m_name); }
|
||||||
|
@ -62,22 +68,22 @@ TBufferObject(, ~BufferObject)() { glDeleteBuffers(1, &m_name); }
|
||||||
TBufferObject(void, bind)() { glBindBuffer(T, m_name); }
|
TBufferObject(void, bind)() { glBindBuffer(T, m_name); }
|
||||||
|
|
||||||
TBufferObject(void, bind)(GLuint index, GLintptr offset, GLsizeiptr size) {
|
TBufferObject(void, bind)(GLuint index, GLintptr offset, GLsizeiptr size) {
|
||||||
// todo
|
// todo
|
||||||
}
|
}
|
||||||
|
|
||||||
TBufferObject(void, fill)(GLenum usage, GLsizei size, GLvoid *data) {
|
TBufferObject(void, fill)(GLenum usage, GLsizei size, GLvoid *data) {
|
||||||
glBufferData(T, size, data, usage);
|
glBufferData(T, size, data, usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
TBufferObject(void, subfill)(GLintptr offset, GLsizei size,
|
TBufferObject(void, subfill)(GLintptr offset, GLsizei size,
|
||||||
const GLvoid *data) {
|
const GLvoid *data) {
|
||||||
glBufferSubData(T, offset, size, data);
|
glBufferSubData(T, offset, size, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
TBufferObject(void, map)(GLenum access) {
|
TBufferObject(void, map)(GLenum access) {
|
||||||
// todo
|
// todo
|
||||||
}
|
}
|
||||||
|
|
||||||
TBufferObject(void, unmap)() {
|
TBufferObject(void, unmap)() {
|
||||||
// todo
|
// todo
|
||||||
}
|
}
|
||||||
|
|
125
game/opengl.cpp
125
game/opengl.cpp
|
@ -3,100 +3,101 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include "options.hpp"
|
||||||
|
|
||||||
#define UNUSED(foo) (void)foo;
|
#define UNUSED(foo) (void) foo;
|
||||||
|
|
||||||
timespec diff(timespec start, timespec end) {
|
timespec diff(timespec start, timespec end) {
|
||||||
timespec result;
|
timespec result;
|
||||||
if ((end.tv_nsec - start.tv_nsec) < 0) {
|
if ((end.tv_nsec - start.tv_nsec) < 0) {
|
||||||
result.tv_sec = end.tv_sec - start.tv_sec - 1;
|
result.tv_sec = end.tv_sec - start.tv_sec - 1;
|
||||||
result.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
|
result.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
|
||||||
} else {
|
} else {
|
||||||
result.tv_sec = end.tv_sec - start.tv_sec;
|
result.tv_sec = end.tv_sec - start.tv_sec;
|
||||||
result.tv_nsec = end.tv_nsec - start.tv_nsec;
|
result.tv_nsec = end.tv_nsec - start.tv_nsec;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
endofthejedi::GLWindow::GLWindow(unsigned int width, unsigned int height)
|
endofthejedi::GLWindow::GLWindow(unsigned int width, unsigned int height)
|
||||||
: m_width(width), m_height(height) {
|
: m_width(width), m_height(height) {
|
||||||
m_display = XOpenDisplay(NULL);
|
m_display = XOpenDisplay(NULL);
|
||||||
|
|
||||||
if (m_display == NULL) {
|
if (m_display == NULL) {
|
||||||
throw std::runtime_error("XOpenDisplay NULL");
|
throw std::runtime_error("XOpenDisplay NULL");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_rootwnd = DefaultRootWindow(m_display);
|
m_rootwnd = DefaultRootWindow(m_display);
|
||||||
|
|
||||||
m_visualinfo = glXChooseVisual(m_display, 0, m_attributes);
|
m_visualinfo = glXChooseVisual(m_display, 0, m_attributes);
|
||||||
|
|
||||||
if (m_visualinfo == NULL) {
|
if (m_visualinfo == NULL) {
|
||||||
throw std::runtime_error("glXChooseVisual NULL");
|
throw std::runtime_error("glXChooseVisual NULL");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_colormap =
|
m_colormap =
|
||||||
XCreateColormap(m_display, m_rootwnd, m_visualinfo->visual, AllocNone);
|
XCreateColormap(m_display, m_rootwnd, m_visualinfo->visual, AllocNone);
|
||||||
|
|
||||||
m_swa.colormap = m_colormap;
|
m_swa.colormap = m_colormap;
|
||||||
m_swa.event_mask = ExposureMask | KeyPressMask;
|
m_swa.event_mask = ExposureMask | KeyPressMask;
|
||||||
|
|
||||||
m_window = XCreateWindow(
|
m_window = XCreateWindow(
|
||||||
m_display, m_rootwnd, 0, 0, width, height, 0, m_visualinfo->depth,
|
m_display, m_rootwnd, 0, 0, width, height, 0, m_visualinfo->depth,
|
||||||
InputOutput, m_visualinfo->visual, CWColormap | CWEventMask, &m_swa);
|
InputOutput, m_visualinfo->visual, CWColormap | CWEventMask, &m_swa);
|
||||||
|
|
||||||
m_atomWmDeleteWindow = XInternAtom(m_display, "WM_DELETE_WINDOW", False);
|
m_atomWmDeleteWindow = XInternAtom(m_display, "WM_DELETE_WINDOW", False);
|
||||||
XSetWMProtocols(m_display, m_window, &m_atomWmDeleteWindow, 1);
|
XSetWMProtocols(m_display, m_window, &m_atomWmDeleteWindow, 1);
|
||||||
|
|
||||||
XMapWindow(m_display, m_window);
|
XMapWindow(m_display, m_window);
|
||||||
XStoreName(m_display, m_window, "NAME");
|
XStoreName(m_display, m_window, "NAME");
|
||||||
|
|
||||||
m_glcontext = glXCreateContext(m_display, m_visualinfo, NULL, GL_TRUE);
|
m_glcontext = glXCreateContext(m_display, m_visualinfo, NULL, GL_TRUE);
|
||||||
|
|
||||||
XSync(m_display, False);
|
XSync(m_display, False);
|
||||||
|
|
||||||
glXMakeCurrent(m_display, m_window, m_glcontext);
|
glXMakeCurrent(m_display, m_window, m_glcontext);
|
||||||
|
|
||||||
std::cout << "GL Renderer: " << glGetString(GL_RENDERER) << "\n";
|
std::cout << "GL Renderer: " << glGetString(GL_RENDERER) << "\n";
|
||||||
std::cout << "GL Version: " << glGetString(GL_VERSION) << "\n";
|
std::cout << "GL Version: " << glGetString(GL_VERSION) << "\n";
|
||||||
std::cout << "GLSL Version: " << glGetString(GL_SHADING_LANGUAGE_VERSION)
|
std::cout << "GLSL Version: " << glGetString(GL_SHADING_LANGUAGE_VERSION)
|
||||||
<< "\n";
|
<< "\n";
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
XClearWindow(m_display, m_window);
|
XClearWindow(m_display, m_window);
|
||||||
XMapRaised(m_display, m_window);
|
XMapRaised(m_display, m_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
endofthejedi::GLWindow::~GLWindow() {
|
endofthejedi::GLWindow::~GLWindow() {
|
||||||
glXMakeCurrent(m_display, None, NULL);
|
glXMakeCurrent(m_display, None, NULL);
|
||||||
glXDestroyContext(m_display, m_glcontext);
|
glXDestroyContext(m_display, m_glcontext);
|
||||||
XFree(m_visualinfo);
|
XFree(m_visualinfo);
|
||||||
XDestroyWindow(m_display, m_window);
|
XDestroyWindow(m_display, m_window);
|
||||||
XCloseDisplay(m_display);
|
XCloseDisplay(m_display);
|
||||||
}
|
}
|
||||||
|
|
||||||
void endofthejedi::GLWindow::handleevents() {
|
void endofthejedi::GLWindow::handleevents() {
|
||||||
if (XPending(m_display) > 0) {
|
if (XPending(m_display) > 0) {
|
||||||
XEvent xev;
|
XEvent xev;
|
||||||
XNextEvent(m_display, &xev);
|
XNextEvent(m_display, &xev);
|
||||||
handle(xev);
|
handle(xev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void endofthejedi::GLWindow::handle(XEvent event) {
|
void endofthejedi::GLWindow::handle(XEvent event) {
|
||||||
if (event.type == Expose) {
|
if (event.type == Expose) {
|
||||||
XWindowAttributes attribs;
|
XWindowAttributes attribs;
|
||||||
XGetWindowAttributes(m_display, m_window, &attribs);
|
XGetWindowAttributes(m_display, m_window, &attribs);
|
||||||
m_width = attribs.width;
|
m_width = attribs.width;
|
||||||
m_height = attribs.height;
|
m_height = attribs.height;
|
||||||
resize();
|
resize();
|
||||||
} else if (event.type == ClientMessage) {
|
} else if (event.type == ClientMessage) {
|
||||||
if (event.xclient.data.l[0] == m_atomWmDeleteWindow) {
|
if (event.xclient.data.l[0] == m_atomWmDeleteWindow) {
|
||||||
stop();
|
stop();
|
||||||
|
}
|
||||||
|
} else if (event.type == DestroyNotify) {
|
||||||
|
stop();
|
||||||
}
|
}
|
||||||
} else if (event.type == DestroyNotify) {
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void endofthejedi::GLWindow::swap() { glXSwapBuffers(m_display, m_window); }
|
void endofthejedi::GLWindow::swap() { glXSwapBuffers(m_display, m_window); }
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <X11/X.h>
|
#include <X11/X.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
|
234
game/raycaster.fs
Normal file
234
game/raycaster.fs
Normal file
|
@ -0,0 +1,234 @@
|
||||||
|
R"raw_string(
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
struct intersection
|
||||||
|
{
|
||||||
|
bool intersected;
|
||||||
|
vec3 point;
|
||||||
|
vec3 normal;
|
||||||
|
vec3 color;
|
||||||
|
float reflection;
|
||||||
|
int idx;
|
||||||
|
//todo different types
|
||||||
|
};
|
||||||
|
|
||||||
|
varying vec2 outvertex;
|
||||||
|
|
||||||
|
//settings
|
||||||
|
uniform float aspectratio;
|
||||||
|
uniform float time;
|
||||||
|
uniform int supersamples;
|
||||||
|
uniform int reflections;
|
||||||
|
uniform bool shadows;
|
||||||
|
uniform vec3 backgroundcolor;
|
||||||
|
|
||||||
|
//light
|
||||||
|
uniform vec3 l_position;
|
||||||
|
uniform float l_radius;
|
||||||
|
|
||||||
|
//spheres
|
||||||
|
//todo ubo?
|
||||||
|
uniform int s_length;
|
||||||
|
uniform vec3 s_positions[100];
|
||||||
|
uniform float s_radii[100];
|
||||||
|
uniform vec4 s_colors[100];
|
||||||
|
uniform float s_reflections[100];
|
||||||
|
|
||||||
|
const float PI = 3.14159265359;
|
||||||
|
|
||||||
|
//din = german industrial normal
|
||||||
|
float light_diffuse(vec3 pos, vec3 din)
|
||||||
|
{
|
||||||
|
vec3 l_dir = normalize(l_position - pos);
|
||||||
|
return max(dot(l_dir, din), 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
//adapted from https://wiki.delphigl.com/index.php/shader_ConeVolumeShadow
|
||||||
|
float light_shadow(vec3 pos)
|
||||||
|
{
|
||||||
|
float s = 1.0f;
|
||||||
|
|
||||||
|
for(int l = 0; l < s_length; l++)
|
||||||
|
{
|
||||||
|
vec3 s_pos = s_positions[l];
|
||||||
|
float s_rad = s_radii[l];
|
||||||
|
|
||||||
|
// project fragment (pos) on the cone axis => F_
|
||||||
|
vec3 nvLO = s_pos - l_position;
|
||||||
|
float dLO = length(nvLO);
|
||||||
|
nvLO /= dLO;
|
||||||
|
vec3 vLF = pos - l_position;
|
||||||
|
float dLF_ = dot(vLF, nvLO);
|
||||||
|
if (dLF_ < dLO) {
|
||||||
|
// fragment before occluder => no shadow
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
vec3 F_ = l_position + dLF_ * nvLO;
|
||||||
|
float rF = distance(F_, pos);
|
||||||
|
|
||||||
|
// compute outer and inner radius at F_
|
||||||
|
float rF_outer = (s_rad + l_radius) * (dLF_ / dLO) - l_radius;
|
||||||
|
if (rF >= rF_outer) {
|
||||||
|
// outside the outer cone => no shadow
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
float rF_inner = (s_rad - l_radius) * (dLF_ / dLO) + l_radius;
|
||||||
|
if (rF_inner >= rF) {
|
||||||
|
// inside the inner cone => full shadow
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
else if (rF_inner >= 0.0 || rF >= -rF_inner) {
|
||||||
|
// soft shadow, linear interpolation
|
||||||
|
s *= (rF - rF_inner) / (rF_outer - rF_inner);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// light from both sides of the occluder
|
||||||
|
s *= (-2.0*rF_inner) / (rF_outer - rF_inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
intersection intersect_sphere(vec3 r_pos, vec3 r_dir, vec3 s_pos, float s_rad, inout float minimum)
|
||||||
|
{
|
||||||
|
intersection result = intersection(false,vec3(0.0f, 0.0f, 0.0f),
|
||||||
|
vec3(0.0f, 0.0f, 0.0f),
|
||||||
|
vec3(0.0f, 0.0f, 0.0f), 0.0f, -1);
|
||||||
|
|
||||||
|
vec3 v = r_pos - s_pos;
|
||||||
|
float a = dot(r_pos, r_pos);
|
||||||
|
float b = dot(v, r_dir);
|
||||||
|
float c = dot(v, v) - (s_rad * s_rad);
|
||||||
|
float d = b * b - c;
|
||||||
|
|
||||||
|
if(d >= 0)
|
||||||
|
{
|
||||||
|
float w1 = -b - sqrt(d);
|
||||||
|
float w2 = -b + sqrt(d);
|
||||||
|
|
||||||
|
if(w1 > 0.0f || w2 > 0.0f)
|
||||||
|
{
|
||||||
|
float w = min(w1, w2);
|
||||||
|
float o = max(w1, w2);
|
||||||
|
|
||||||
|
if(w1 <= 0.0f)
|
||||||
|
w = w2;
|
||||||
|
else
|
||||||
|
if(w2 <= 0.0f)
|
||||||
|
w = w1;
|
||||||
|
|
||||||
|
if(w < minimum)
|
||||||
|
{
|
||||||
|
minimum = w;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return intersection(false,vec3(0.0f, 0.0f, 0.0f),
|
||||||
|
vec3(0.0f, 0.0f, 0.0f),
|
||||||
|
vec3(0.0f, 0.0f, 0.0f), 0.0f, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 p = r_pos + (w * r_dir);
|
||||||
|
result.intersected = true;
|
||||||
|
result.point = p;
|
||||||
|
result.normal = normalize((p - s_pos) / s_rad);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
intersection intersect(vec3 r_pos, vec3 r_dir, int idx)
|
||||||
|
{
|
||||||
|
intersection result = intersection(false,vec3(0.0f, 0.0f, 0.0f),
|
||||||
|
vec3(0.0f, 0.0f, 0.0f),
|
||||||
|
vec3(0.0f, 0.0f, 0.0f), 0.0f, -1);
|
||||||
|
float minimum = 1000.0f;
|
||||||
|
|
||||||
|
for(int l = 0; l < s_length; l++)
|
||||||
|
{
|
||||||
|
if(idx == l)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float maximum;
|
||||||
|
|
||||||
|
intersection r = intersect_sphere(r_pos, r_dir, s_positions[l], s_radii[l], minimum);
|
||||||
|
if(r.intersected)
|
||||||
|
{
|
||||||
|
r.color = s_colors[l].rgb;
|
||||||
|
r.idx = l;
|
||||||
|
r.reflection = s_reflections[l];
|
||||||
|
|
||||||
|
result = r;
|
||||||
|
}
|
||||||
|
//todo other geometric objects
|
||||||
|
//todo handle min with other geometric objects
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 cast_ray(vec3 r_pos, vec3 r_pixel)
|
||||||
|
{
|
||||||
|
vec3 r_dir = normalize(r_pixel - r_pos);
|
||||||
|
|
||||||
|
vec3 color = backgroundcolor;
|
||||||
|
|
||||||
|
intersection i = intersection(false,vec3(0.0f, 0.0f, 0.0f),
|
||||||
|
vec3(0.0f, 0.0f, 0.0f),
|
||||||
|
vec3(0.0f, 0.0f, 0.0f), 0.0f, -1);
|
||||||
|
|
||||||
|
vec3 p = r_pos;
|
||||||
|
vec3 d = r_dir;
|
||||||
|
int idx = -1;
|
||||||
|
|
||||||
|
for(int bounce = 0; bounce < reflections; bounce++)
|
||||||
|
{
|
||||||
|
intersection i = intersect(p,d, idx);
|
||||||
|
|
||||||
|
if(i.intersected)
|
||||||
|
{
|
||||||
|
float l_factor = light_diffuse(i.point, i.normal);
|
||||||
|
|
||||||
|
if(shadows && l_factor > 0.004f)
|
||||||
|
{
|
||||||
|
l_factor *= light_shadow(i.point);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bounce == 0)
|
||||||
|
{
|
||||||
|
color = i.color * l_factor;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color = mix(color, color * i.color * l_factor, i.reflection);
|
||||||
|
}
|
||||||
|
|
||||||
|
//d = 2*(dot(p, i.normal))*i.normal - p;
|
||||||
|
d = reflect(-p, i.normal);
|
||||||
|
p = i.point;
|
||||||
|
idx = i.idx;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 rp = outvertex;
|
||||||
|
rp.x = rp.x * aspectratio;
|
||||||
|
vec4 outcolor = vec4(cast_ray(vec3(0.0f, 0.0f, 1.0f), vec3(rp, 0.0f)), 0.0f);
|
||||||
|
for(int supersample = 1; supersample < supersamples; supersample++)
|
||||||
|
{
|
||||||
|
outcolor = mix(outcolor, vec4(cast_ray(vec3(sin(supersample * PI/supersamples)/200, cos(supersample * PI/supersamples)/200, 1.0f), vec3(rp, 0.0f)), 0.0f), 0.5f);
|
||||||
|
}
|
||||||
|
gl_FragColor = outcolor;
|
||||||
|
}
|
||||||
|
|
||||||
|
)raw_string"
|
13
game/raycaster.vs
Normal file
13
game/raycaster.vs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
R"raw_string(
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
attribute vec2 invertex;
|
||||||
|
varying vec2 outvertex;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position.xy = invertex;
|
||||||
|
gl_Position.zw = vec2(0.0f, 1.0);
|
||||||
|
outvertex = invertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
)raw_string"
|
|
@ -1,18 +1,4 @@
|
||||||
#include "renderer.hpp"
|
#include "renderer.hpp"
|
||||||
|
|
||||||
endofthejedi::Renderer::Renderer() {
|
void endofthejedi::Renderer::render(const game::State *state) {
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
endofthejedi::Renderer::~Renderer() {}
|
|
||||||
|
|
||||||
void endofthejedi::Renderer::drawCircle(float x, float y, float radius, float r, float g, float b, int numSides)
|
|
||||||
{
|
|
||||||
glBegin(GL_TRIANGLE_FAN);
|
|
||||||
glColor3f(r,g,b);
|
|
||||||
glVertex2f(x, y); // center of circle
|
|
||||||
for (int i = 0; i <= numSides; i++) {
|
|
||||||
glVertex2f(x + (radius * cos(i * 2 * M_PI / numSides)), y + (radius * sin(i * 2 * M_PI / numSides)));
|
|
||||||
}
|
|
||||||
glEnd();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,21 +5,15 @@
|
||||||
#include <epoxy/gl.h>
|
#include <epoxy/gl.h>
|
||||||
#include <epoxy/glx.h>
|
#include <epoxy/glx.h>
|
||||||
|
|
||||||
#include "glclasses.hpp"
|
#include "game.hpp"
|
||||||
|
|
||||||
namespace endofthejedi {
|
namespace endofthejedi {
|
||||||
|
|
||||||
class Renderer {
|
class Renderer {
|
||||||
private:
|
private:
|
||||||
VBO m_vbo;
|
protected:
|
||||||
VAO m_vao;
|
public:
|
||||||
Shader m_shader;
|
virtual void render(const game::State *state);
|
||||||
protected:
|
|
||||||
public:
|
|
||||||
Renderer();
|
|
||||||
~Renderer();
|
|
||||||
void drawCircle(float x, float y, float radius, float r,
|
|
||||||
float g, float b, int numSides=12);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
75
game/renderer_shader.cpp
Normal file
75
game/renderer_shader.cpp
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#include "renderer_shader.hpp"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "glm/glm.hpp"
|
||||||
|
#include "glm/vec2.hpp"
|
||||||
|
#include "glm/vec3.hpp"
|
||||||
|
#include "glm/gtc/type_ptr.hpp"
|
||||||
|
|
||||||
|
endofthejedi::RendererShader::RendererShader() {
|
||||||
|
m_shader.load(vss, GL_VERTEX_SHADER);
|
||||||
|
m_shader.load(fss, GL_FRAGMENT_SHADER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void endofthejedi::RendererShader::render(const game::State *state) {
|
||||||
|
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, -5.0f));
|
||||||
|
radii.push_back(planet->radius);
|
||||||
|
colors.push_back(glm::vec4(1.0f, 0.0f, 0.0f, 0.5f));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const game::Ship *ship : state->ships) {
|
||||||
|
positions.push_back(glm::vec3(ship->position, -3.0f));
|
||||||
|
radii.push_back(ship->radius);
|
||||||
|
colors.push_back(glm::vec4(1.0f, 0.0f, 0.0f, 0.5f));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const game::Player *player : state->players) {
|
||||||
|
for (const game::Missile *missile : player->missiles) {
|
||||||
|
positions.push_back(glm::vec3(missile->position, -3.0f));
|
||||||
|
radii.push_back(0.01f);
|
||||||
|
colors.push_back(glm::vec4(1.0f, 0.0f, 0.0f, 0.5f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &pos : positions) {
|
||||||
|
pos.x *= 5;
|
||||||
|
pos.y *= 5;
|
||||||
|
}
|
||||||
|
for (auto &rad : radii) {
|
||||||
|
rad *= 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
for (const game::Trace *trace : state->traces) {
|
||||||
|
positions.push_back(glm::vec3(trace->position, -3.0f));
|
||||||
|
radii.push_back(trace->radius);
|
||||||
|
colors.push_back(glm::vec4(0.0f, 1.0f, 0.0f, 0.5f));
|
||||||
|
}*/
|
||||||
|
|
||||||
|
glUniform1f(m_shader.location("aspectratio"), 1.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();
|
||||||
|
}
|
30
game/renderer_shader.hpp
Normal file
30
game/renderer_shader.hpp
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
static const char *vss =
|
||||||
|
#include "raycaster.vs"
|
||||||
|
;
|
||||||
|
static const char *fss =
|
||||||
|
#include "raycaster.fs"
|
||||||
|
;
|
||||||
|
|
||||||
|
#include "renderer.hpp"
|
||||||
|
|
||||||
|
#include "glclasses.hpp"
|
||||||
|
#include "game.hpp"
|
||||||
|
#include "state/planet.hpp"
|
||||||
|
#include "state/trace.hpp"
|
||||||
|
#include "state/player.hpp"
|
||||||
|
#include "state/ship.hpp"
|
||||||
|
|
||||||
|
namespace endofthejedi {
|
||||||
|
|
||||||
|
class RendererShader : Renderer {
|
||||||
|
private:
|
||||||
|
Shader m_shader;
|
||||||
|
protected:
|
||||||
|
public:
|
||||||
|
RendererShader();
|
||||||
|
void render(const game::State *state) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
79
game/renderer_simple.cpp
Normal file
79
game/renderer_simple.cpp
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
#include "renderer_simple.hpp"
|
||||||
|
|
||||||
|
void endofthejedi::RendererSimple::drawCircle(float x, float y, float radius,
|
||||||
|
float r, float g, float b,
|
||||||
|
int numSides) {
|
||||||
|
glBegin(GL_TRIANGLE_FAN);
|
||||||
|
glColor3f(r, g, b);
|
||||||
|
glVertex2f(x, y); // center of circle
|
||||||
|
for (int i = 0; i <= numSides; i++) {
|
||||||
|
glVertex2f(x + (radius * cos(i * 2 * M_PI / numSides)),
|
||||||
|
y + (radius * sin(i * 2 * M_PI / numSides)));
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void endofthejedi::RendererSimple::drawShip(const glm::vec2 &pos,
|
||||||
|
float radius) {
|
||||||
|
// std::cout<<"draw ship @ " << pos.x << ", " << pos.y << std::endl;
|
||||||
|
glm::vec3 color = glm::vec3(0.2, 1.0, 0.3);
|
||||||
|
|
||||||
|
drawCircle(pos.x, pos.y, radius, color.x, color.y, color.z, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
void endofthejedi::RendererSimple::drawPlanet(const glm::vec2 &pos,
|
||||||
|
float radius) {
|
||||||
|
glm::vec3 color = glm::vec3(0.7, 0.1, 0.2);
|
||||||
|
|
||||||
|
// std::cout<<"draw planet @ " << pos.x << ", " << pos.y << std::endl;
|
||||||
|
drawCircle(pos.x, pos.y, radius, color.x, color.y, color.z, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
void endofthejedi::RendererSimple::drawMissile(const glm::vec2 &pos) {
|
||||||
|
glm::vec3 color = glm::vec3(1.0, 1.0, 0.3);
|
||||||
|
drawCircle(pos.x, pos.y, 0.01, color.x, color.y, color.z, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void endofthejedi::RendererSimple::drawTrace(const game::Trace *trace) {
|
||||||
|
for (const game::Trace::TracePoint &p : trace->points) {
|
||||||
|
glm::vec3 color = glm::vec3(0.1, 0.3, 1.0) / (1.0f + 500.0f * p.speed);
|
||||||
|
drawCircle(p.position.x, p.position.y, 0.005, color.x, color.y, color.z,
|
||||||
|
3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void endofthejedi::RendererSimple::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);
|
||||||
|
drawCircle(explosion->position.x, explosion->position.y, r, color.x,
|
||||||
|
color.y, color.z, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
void endofthejedi::RendererSimple::render(const game::State *state) {
|
||||||
|
for (const game::Planet *planet : state->planets) {
|
||||||
|
drawPlanet(planet->position, planet->radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const game::Trace *trace : state->traces) {
|
||||||
|
drawTrace(trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const game::Explosion *explosion : state->explosions) {
|
||||||
|
drawExplosion(explosion);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const game::Ship *ship : state->ships) {
|
||||||
|
drawShip(ship->position, ship->radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const game::Player *player : state->players) {
|
||||||
|
for (const game::Missile *missile : player->missiles) {
|
||||||
|
drawMissile(missile->position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
game/renderer_simple.hpp
Normal file
33
game/renderer_simple.hpp
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "renderer.hpp"
|
||||||
|
|
||||||
|
#include "glclasses.hpp"
|
||||||
|
|
||||||
|
#include "game.hpp"
|
||||||
|
#include "state/trace.hpp"
|
||||||
|
#include "state/object.hpp"
|
||||||
|
#include "state/missile.hpp"
|
||||||
|
#include "state/player.hpp"
|
||||||
|
#include "state/planet.hpp"
|
||||||
|
#include "state/ship.hpp"
|
||||||
|
#include "state/explosion.hpp"
|
||||||
|
|
||||||
|
namespace endofthejedi {
|
||||||
|
|
||||||
|
class RendererSimple : Renderer {
|
||||||
|
private:
|
||||||
|
void drawCircle(float x, float y, float radius, float r, float g, float b,
|
||||||
|
int numSides = 12);
|
||||||
|
void drawShip(const glm::vec2 &pos, float radius);
|
||||||
|
void drawPlanet(const glm::vec2 &pos, float radius);
|
||||||
|
void drawMissile(const glm::vec2 &pos);
|
||||||
|
void drawTrace(const game::Trace *trace);
|
||||||
|
void drawExplosion(const game::Explosion *explosion);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
public:
|
||||||
|
void render(const game::State *state) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#define ASIO_STANDALONE
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "opengl.hpp"
|
|
||||||
|
|
||||||
class TriangleWindow : public endofthejedi::GLWindow {
|
|
||||||
private:
|
|
||||||
protected:
|
|
||||||
void init() override {
|
|
||||||
glClearColor(0.5f, 0.6f, 0.7f, 1.0f);
|
|
||||||
resize();
|
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
|
||||||
}
|
|
||||||
void render(double time) override {
|
|
||||||
(void) time;
|
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
glBegin(GL_TRIANGLES);
|
|
||||||
glColor3f(1.0f, 0.0f, 0.0f);
|
|
||||||
glVertex3f(0.0f, -1.0f, 0.0f);
|
|
||||||
glColor3f(0.0f, 1.0f, 0.0f);
|
|
||||||
glVertex3f(-1.0f, 1.0f, 0.0f);
|
|
||||||
glColor3f(0.0f, 0.0f, 1.0f);
|
|
||||||
glVertex3f(1.0f, 1.0f, 0.0f);
|
|
||||||
glEnd();
|
|
||||||
}
|
|
||||||
void resize() override { glViewport(0, 0, getwidth(), getheight()); }
|
|
||||||
|
|
||||||
public:
|
|
||||||
TriangleWindow(unsigned int width, unsigned int height)
|
|
||||||
: endofthejedi::GLWindow(width, height)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
Loading…
Reference in a new issue