* KREBOLAIDS

This commit is contained in:
end 2016-09-27 20:56:17 +02:00
commit 7a42e49c2c
16 changed files with 568 additions and 245 deletions

View file

@ -1,4 +1,9 @@
Klassische Kepler Kriege Klassische Kepler Kriege
=== ========================
Game based on NewtonWars (https://github.com/Draradech/NewtonWars), rewritten in C++ with some more fancy OpenGL shitz. Game based on NewtonWars (https://github.com/Draradech/NewtonWars), rewritten in C++ with some more fancy OpenGL shitz.
dependencies
------------
libepoxy-dev

View file

@ -10,7 +10,6 @@ set(GAME_SRC
glclasses.cpp glclasses.cpp
renderer.cpp renderer.cpp
game_window.cpp game_window.cpp
triangle_window.cpp
util.cpp util.cpp
game.cpp game.cpp

View file

@ -6,8 +6,7 @@
#include <cmath> #include <cmath>
Game::Game() Game::Game() {
{
// advance simulation with 100 Hz // advance simulation with 100 Hz
m_time_step = 1.0 / 100.0; m_time_step = 1.0 / 100.0;
m_time_for_next_step = 0.0; m_time_for_next_step = 0.0;
@ -19,16 +18,15 @@ Game::Game()
m_state->addPlayer(1); m_state->addPlayer(1);
m_state->addPlayer(2); m_state->addPlayer(2);
m_state->addPlayer(3); m_state->addPlayer(3);
//m_state->addPlayer(2); // m_state->addPlayer(2);
} }
bool Game::cycle(float dt) bool Game::cycle(float dt) {
{
static float acc = 0.0; static float acc = 0.0;
acc += dt; acc += dt;
float spawnInterval = 0.1; float spawnInterval = 0.1;
while(acc > spawnInterval) { while (acc > spawnInterval) {
acc -= spawnInterval; acc -= spawnInterval;
float a = 2.0 * M_PI * util::randf_0_1(); float a = 2.0 * M_PI * util::randf_0_1();
@ -38,27 +36,28 @@ bool Game::cycle(float dt)
#if 1 #if 1
if (dt >= 10.0) { if (dt >= 10.0) {
//std::cout<<"time to big: " << dt << std::endl; // std::cout<<"time to big: " << dt << std::endl;
dt = m_time_step; dt = m_time_step;
} }
//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;
#else #else
(void) dt; (void)dt;
m_state->advance(dt); m_state->advance(dt);

View file

@ -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
const game::State *state() const { return m_state; } const 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;

View file

@ -12,8 +12,8 @@
#include "state/ship.hpp" #include "state/ship.hpp"
class GameWindow : public endofthejedi::GLWindow { class GameWindow : public endofthejedi::GLWindow {
private: private:
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);
resize(); resize();
@ -22,16 +22,16 @@ 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();
} }
@ -54,36 +54,35 @@ protected:
void resize() override { glViewport(0, 0, getwidth(), getheight()); } void resize() override { glViewport(0, 0, getwidth(), getheight()); }
void drawShip(const glm::vec2 &pos) void drawShip(const glm::vec2 &pos) {
{ // std::cout<<"draw ship @ " << pos.x << ", " << pos.y << std::endl;
//std::cout<<"draw ship @ " << pos.x << ", " << pos.y << std::endl;
glm::vec3 color = glm::vec3(0.2, 1.0, 0.3); glm::vec3 color = glm::vec3(0.2, 1.0, 0.3);
float radius = m_game.state()->shipRadius(); float radius = m_game.state()->shipRadius();
m_renderer.drawCircle(pos.x, pos.y, radius, color.x, color.y, color.z, 12); m_renderer.drawCircle(pos.x, pos.y, radius, color.x, color.y, color.z,
12);
} }
void drawPlanet(const glm::vec2 &pos, float radius) void drawPlanet(const glm::vec2 &pos, float radius) {
{
glm::vec3 color = glm::vec3(0.7, 0.1, 0.2); glm::vec3 color = glm::vec3(0.7, 0.1, 0.2);
//std::cout<<"draw planet @ " << pos.x << ", " << pos.y << std::endl; // 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); m_renderer.drawCircle(pos.x, pos.y, radius, color.x, color.y, color.z,
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.005, color.x, color.y, color.z, 5); m_renderer.drawCircle(pos.x, pos.y, 0.005, color.x, color.y, color.z,
5);
} }
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: private:
Game m_game; Game m_game;
endofthejedi::Renderer m_renderer; endofthejedi::Renderer m_renderer;
}; };

View file

@ -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,44 @@ 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";
}
return (bool)result;
} }
void endofthejedi::Shader::unbind() { bool endofthejedi::Shader::checkShader() { return false; }
glUseProgram(0);
} 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); glAttachShader(m_program, cheddar);
glLinkProgram(m_program); glLinkProgram(m_program);
glDeleteShader(cheddar); glDeleteShader(cheddar);
check();
} }

View file

@ -8,51 +8,55 @@
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();
Shader(); protected:
~Shader(); public:
void bind(); Shader();
void unbind(); ~Shader();
void load(std::string data, GLenum shadertype); void bind();
}; void unbind();
void load(std::string data, GLenum shadertype);
};
} }
#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 +66,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
} }

View file

@ -1,12 +1,62 @@
#include "opengl.hpp" #include "opengl.hpp"
#include <iostream> #include <iostream>
#include <getopt.h>
#include "game_window.hpp" #include "game_window.hpp"
#include "options.hpp"
int main(int argc, const char *argv[]) {
GameWindow window(500, 500); using namespace std;
window.set_maxfps(60.0);
window.loop(); int main(int argc, char *argv[]) {
window.stop();
char c;
static struct option long_options[] =
{
/* These options set a flag. */
// {"verbose", no_argument, &verbose_flag, 1},
// {"brief", no_argument, &verbose_flag, 0},
/* These options dont set a flag.
We distinguish them by their indices. */
// {"add", no_argument, 0, 'a'},
// {"append", no_argument, 0, 'b'},
// {"delete", required_argument, 0, 'd'},
// {"create", required_argument, 0, 'c'},
{"fps", no_argument, 0, 'f'},
{0, 0, 0, 0}
};
int option_index = 0;
while(1){
c = getopt_long (argc, argv, "abc:d:f",
long_options, &option_index);
if (c == -1)
break;
switch (c)
{
case 'f':
SET_FLAG(SHOW_FPS,true);
break;
/*case 'c':
cvalue = optarg;
break;
*/
case '?':
/* getopt_long already printed an error message. */
break;
default:
abort();
}
}
GameWindow window(500, 500);
window.set_maxfps(60.0);
window.loop();
window.stop();
} }

234
game/main.fs Normal file
View 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/main.vs Normal file
View 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"

View file

@ -3,136 +3,139 @@
#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); }
void endofthejedi::GLWindow::loop() { void endofthejedi::GLWindow::loop() {
m_running = true; m_running = true;
timespec prev;
timespec current;
clock_gettime(CLOCK_MONOTONIC_RAW, &prev);
clock_gettime(CLOCK_MONOTONIC_RAW, &current);
double delta = 0.0;
double sleeptime = 0.0;
while (m_running) {
handleevents();
render(delta);
swap();
if (m_maxfps > 0) {
sleeptime = ((1000000000.0/m_maxfps) - delta) + sleeptime;
if (sleeptime > 0.0) {
usleep((unsigned int)(sleeptime/1000.0));
sleeptime = sleeptime - (unsigned int)(sleeptime/1000.0);
}
}
timespec prev;
timespec current;
clock_gettime(CLOCK_MONOTONIC_RAW, &prev);
clock_gettime(CLOCK_MONOTONIC_RAW, &current); clock_gettime(CLOCK_MONOTONIC_RAW, &current);
delta = diff(prev, current).tv_nsec;
prev = current; double delta = 0.0;
if(delta > 0.0) { double sleeptime = 0.0;
m_fps = (1000000000.0/delta);
std::cout << m_fps << "\n"; while (m_running) {
handleevents();
render(delta);
swap();
if (m_maxfps > 0) {
sleeptime = ((1000000000.0 / m_maxfps) - delta) + sleeptime;
if (sleeptime > 0.0) {
usleep((unsigned int)(sleeptime / 1000.0));
sleeptime = sleeptime - (unsigned int)(sleeptime / 1000.0);
}
}
clock_gettime(CLOCK_MONOTONIC_RAW, &current);
delta = diff(prev, current).tv_nsec;
prev = current;
if (delta > 0.0) {
m_fps = (1000000000.0 / delta);
if (ISSET_FLAG(SHOW_FPS)) {
std::cout << m_fps << "\n";
}
}
} }
}
} }
void endofthejedi::GLWindow::stop() { m_running = false; } void endofthejedi::GLWindow::stop() { m_running = false; }

22
game/options.hpp Normal file
View file

@ -0,0 +1,22 @@
#pragma once
#define TEST_FLAG1 0
#define SHOW_FPS 1
#define TEST_FLAG2 2
//...
#define SET_FLAG(x,y) optionsFlags&=(~((1)<<x));optionsFlags|=((y&1)<<x)
#define ISSET_FLAG(x) (optionsFlags&((1)<<x))
uint64_t optionsFlags;
/*
* usage:
* SET_FLAG(SHOW_FPS,true);
*
* if(ISSET_FLAG(SHOW_FPS)){
* ...
* }
*/

View file

@ -1,18 +1,32 @@
#include "renderer.hpp" #include "renderer.hpp"
endofthejedi::Renderer::Renderer() { static const char *vss =
#include "main.vs"
;
static const char *fss =
#include "main.fs"
;
endofthejedi::Renderer::Renderer() {
m_shader.load(vss, GL_VERTEX_SHADER);
m_shader.load(fss, GL_FRAGMENT_SHADER);
} }
endofthejedi::Renderer::~Renderer() {} endofthejedi::Renderer::~Renderer() {}
void endofthejedi::Renderer::render() {
m_shader.bind();
}
void endofthejedi::Renderer::drawCircle(float x, float y, float radius, float r, void endofthejedi::Renderer::drawCircle(float x, float y, float radius, float r,
float g, float b, int numSides) { float g, float b, int numSides) {
glBegin(GL_TRIANGLE_FAN); glBegin(GL_TRIANGLE_FAN);
glVertex2f(x, y); // center of circle glVertex2f(x, y); // center of circle
for (int i = 0; i <= numSides; i++) { for (int i = 0; i <= numSides; i++) {
glColor3f(r,g,b); glColor3f(r, g, b);
glVertex2f(x + (radius * cos(i * 2 * M_PI / numSides)), y + (radius * sin(i * 2 * M_PI / numSides))); glVertex2f(x + (radius * cos(i * 2 * M_PI / numSides)),
} y + (radius * sin(i * 2 * M_PI / numSides)));
glEnd(); }
glEnd();
} }

View file

@ -10,16 +10,17 @@
namespace endofthejedi { namespace endofthejedi {
class Renderer { class Renderer {
private: private:
VBO m_vbo; VBO m_vbo;
VAO m_vao; VAO m_vao;
Shader m_shader; Shader m_shader;
protected:
public:
Renderer();
~Renderer();
void drawCircle(float x, float y, float radius, float r,
float g, float b, int numSides=12);
};
protected:
public:
Renderer();
~Renderer();
void render();
void drawCircle(float x, float y, float radius, float r, float g, float b,
int numSides = 12);
};
} }

View file

@ -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)
{
}
};