renamed renderer classes. fixed shooting taking rad instead of degrees as parameter.

This commit is contained in:
Andreas Ortmann 2016-09-28 11:35:56 +02:00
parent 74b4573c3a
commit c8288d7a25
14 changed files with 186 additions and 393 deletions

View file

@ -10,8 +10,9 @@ set(GAME_SRC
glclasses.cpp glclasses.cpp
renderer.cpp renderer.cpp
game_window.cpp game_window.cpp
renderer_simple.cpp renderer_polygon_2d.cpp
renderer_shader.cpp renderer_polygon_3d.cpp
renderer_ray_tracer.cpp
session.cpp session.cpp
util.cpp util.cpp
@ -27,20 +28,12 @@ set(GAME_SRC
state/state.cpp state/state.cpp
) )
set(GAME_HEADERS
opengl.hpp
glclasses.hpp
renderer.hpp
renderer_simple.hpp
renderer_shader.hpp
)
include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${OPENGL_INCLUDE_DIR}) include_directories(${OPENGL_INCLUDE_DIR})
include_directories(${CMAKE_SOURCE_DIR}/libs/glm/) include_directories(${CMAKE_SOURCE_DIR}/libs/glm/)
include_directories(${CMAKE_SOURCE_DIR}/libs/asio/asio/include/) include_directories(${CMAKE_SOURCE_DIR}/libs/asio/asio/include/)
add_executable(game ${GAME_SRC} ${GAME_HEADERS}) add_executable(game ${GAME_SRC})
setup_target(game) setup_target(game)
target_link_libraries(game X11 epoxy pthread) target_link_libraries(game X11 epoxy pthread)

View file

@ -2,8 +2,9 @@
#include "opengl.hpp" #include "opengl.hpp"
#include "renderer.hpp" #include "renderer.hpp"
#include "renderer_simple.hpp" #include "renderer_polygon_2d.hpp"
#include "renderer_shader.hpp" #include "renderer_polygon_3d.hpp"
#include "renderer_ray_tracer.hpp"
#include "game.hpp" #include "game.hpp"
@ -18,7 +19,9 @@
class GameWindow : public endofthejedi::GLWindow { class GameWindow : public endofthejedi::GLWindow {
private: private:
Game* m_game; Game* m_game;
endofthejedi::RendererSimple m_renderer; endofthejedi::RendererPolygon2d m_renderer;
//endofthejedi::RendererPolygon3d m_renderer;
//endofthejedi::RendererRayTracer m_renderer;
protected: protected:
void init() override { void init() override {
@ -29,14 +32,6 @@ class GameWindow : public endofthejedi::GLWindow {
} }
void render(double time) override { void render(double time) override {
// static bool once = false;
// if (!once) {
// once = true;
// for (int i=0; i<1000; i++) {
// 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();

View file

@ -8,100 +8,100 @@
namespace endofthejedi { namespace endofthejedi {
class GLWindow { class GLWindow {
private: private:
//X-related stuff //X-related stuff
Display* m_display; Display* m_display;
Window m_rootwnd; Window m_rootwnd;
GLint m_attributes[23] = GLint m_attributes[23] =
{ {
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
GLX_RED_SIZE, 8, GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8, GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8, GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8, GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, 24, GLX_DEPTH_SIZE, 24,
GLX_STENCIL_SIZE, 8, GLX_STENCIL_SIZE, 8,
GLX_DOUBLEBUFFER, True, GLX_DOUBLEBUFFER, True,
None None
};
XVisualInfo* m_visualinfo;
Colormap m_colormap;
XSetWindowAttributes m_swa;
Window m_window;
GLXContext m_glcontext;
XWindowAttributes m_gwa;
Atom m_atomWmDeleteWindow;
//End of X related stuff
unsigned int m_width;
unsigned int m_height;
double delta = 0.0;
double sleeptime = 0.0;
timespec prev;
timespec current;
//mainloop condition
bool m_running = false;
double m_fps;
//if maxfps = 0 there's no fps limit
double m_maxfps;
protected:
//ancestors shall override these methods
virtual void init();
//called by mainloop periodically
//time shall be used for timebased movement
virtual void render(double time);
//called by handle on window resize
virtual void resize();
//the ancestor should call the handle function in this class, too,
//as it handles the close calls & resizing
virtual void handle(XEvent event);
virtual void handleevents();
public:
//initializes the X Window & creates an OpenGL context
GLWindow(unsigned int width, unsigned int height);
~GLWindow();
//mainloop does event handling & calls render/swap
void poll();
void swap();
//stops the mainloop by setting m_running false
void stop();
bool running();
//getters
unsigned int getheight() const {
return m_height;
}
unsigned int getwidth() const {
return m_width;
}
double get_maxfps() const {
return m_maxfps;
}
double get_fps() const {
return m_fps;
}
bool get_running() const {
return m_running;
}
//setters
void set_maxfps(const double maxfps) {
m_maxfps = maxfps;
}
}; };
XVisualInfo* m_visualinfo;
Colormap m_colormap;
XSetWindowAttributes m_swa;
Window m_window;
GLXContext m_glcontext;
XWindowAttributes m_gwa;
Atom m_atomWmDeleteWindow;
//End of X related stuff
unsigned int m_width;
unsigned int m_height;
double delta = 0.0;
double sleeptime = 0.0;
timespec prev;
timespec current;
//mainloop condition
bool m_running = false;
double m_fps;
//if maxfps = 0 there's no fps limit
double m_maxfps;
protected:
//ancestors shall override these methods
virtual void init();
//called by mainloop periodically
//time shall be used for timebased movement
virtual void render(double time);
//called by handle on window resize
virtual void resize();
//the ancestor should call the handle function in this class, too,
//as it handles the close calls & resizing
virtual void handle(XEvent event);
virtual void handleevents();
public:
//initializes the X Window & creates an OpenGL context
GLWindow(unsigned int width, unsigned int height);
~GLWindow();
//mainloop does event handling & calls render/swap
void poll();
void swap();
//stops the mainloop by setting m_running false
void stop();
bool running();
//getters
unsigned int getheight() const {
return m_height;
}
unsigned int getwidth() const {
return m_width;
}
double get_maxfps() const {
return m_maxfps;
}
double get_fps() const {
return m_fps;
}
bool get_running() const {
return m_running;
}
//setters
void set_maxfps(const double maxfps) {
m_maxfps = maxfps;
}
};
} }

View file

@ -1,4 +1 @@
#include "renderer.hpp" #include "renderer.hpp"
void endofthejedi::Renderer::render(const game::State *state) {
}

View file

@ -9,11 +9,17 @@
namespace endofthejedi { namespace endofthejedi {
class Renderer { /**
private: * Base class for the render.
protected: *
public: * Implementations should render the whole scene (state) on the screen with
virtual void render(const game::State *state); * opengl.
}; */
class Renderer {
private:
protected:
public:
virtual void render(const game::State *state) = 0;
};
} }

View file

@ -1,75 +0,0 @@
#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();
}

View file

@ -1,30 +0,0 @@
#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;
};
}

View file

@ -1,79 +0,0 @@
#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);
}
}
}

View file

@ -1,33 +0,0 @@
#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;
};
}

View file

@ -8,31 +8,31 @@ using asio::ip::tcp;
class Server class Server
{ {
public: public:
Server(asio::io_service& io_service,game::State* s, short port) Server(asio::io_service& io_service,game::State* s, short port)
: acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)),
socket_(io_service) socket_(io_service)
{ {
state=s; state=s;
do_accept(); do_accept();
} }
private: private:
void do_accept() void do_accept()
{
acceptor_.async_accept(socket_,
[this](std::error_code ec)
{ {
if (!ec) acceptor_.async_accept(socket_,
{ [this](std::error_code ec)
std::make_shared<Session>(std::move(socket_),state)->start(); {
} if (!ec)
{
std::make_shared<Session>(std::move(socket_),state)->start();
}
do_accept(); do_accept();
}); });
} }
tcp::acceptor acceptor_; tcp::acceptor acceptor_;
tcp::socket socket_; tcp::socket socket_;
game::State* state; game::State* state;
}; };

View file

@ -11,24 +11,29 @@ using namespace std;
bool Session::parse(string s) bool Session::parse(string s)
{ {
s.erase(std::find_if(s.rbegin(), s.rend(), s.erase(std::find_if(s.rbegin(), s.rend(),
std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end()); std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
if(s.size()==1&&s[0]=='q'){ // TODO:
// from knoc:
// ALWAYS use commands here, no direct input!
// thats important!!!!
// TODO
if (s.size()==1&&s[0]=='q'){
//quit //quit
m_socket.close(); m_socket.close();
m_state->quitPlayer(m_pid); m_state->quitPlayer(m_pid);
return false; return false;
}else if(s.size()==1&&s[0]=='c'){ } else if (s.size()==1&&s[0]=='c') {
//clear //clear
m_state->clear(m_pid); m_state->clear(m_pid);
}else if(s.size()>=3&&s[0]=='n'&&s[1]==' '){ } else if (s.size()>=3&&s[0]=='n'&&s[1]==' ') {
//set name //set name
m_state->setName(m_pid, s.substr(2)); m_state->setName(m_pid, s.substr(2));
}else if(s.size()>=3&&s[0]=='v'&&s[1]==' '){ } else if (s.size()>=3&&s[0]=='v'&&s[1]==' ') {
//set speed //set speed
double speed = atof(s.substr(2).c_str()); double speed = atof(s.substr(2).c_str());
m_state->setSpeed(m_pid, speed); m_state->setSpeed(m_pid, speed);
}else{ } else {
//shoot //shoot
double angle = atof(s.c_str()); double angle = atof(s.c_str());
m_state->commandForPlayer(m_pid, new game::ShootCommand(angle)); m_state->commandForPlayer(m_pid, new game::ShootCommand(angle));
@ -41,36 +46,35 @@ void Session::start()
if(m_started) return; if(m_started) return;
m_started=true; m_started=true;
m_pid = m_state->addPlayer(); m_pid = m_state->addPlayer();
char hello[] = "\nUse \"n name\" to change name, \"v velocity\" to change velocity, \"c\" to clear past shots or \"q\" to close the connection.\nEverything else is interpreted as a shooting angle.\n\n> "; char hello[] = "\nWeclome to KlassischeKeplerKriege v0.1\n Use \"n name\" to change name, \"v velocity\" to change velocity, \"c\" to clear past shots or \"q\" to close the connection.\nEverything else is interpreted as a shooting angle.\n\n> ";
do_write(hello, strlen(hello)); do_write(hello, strlen(hello));
} }
void Session::do_read() void Session::do_read()
{ {
auto self(shared_from_this()); auto self(shared_from_this());
m_socket.async_read_some(asio::buffer(m_rcv_data, max_length), m_socket.async_read_some(
[this, self](std::error_code ec, std::size_t length) asio::buffer(m_rcv_data, max_length),
{ [this, self](std::error_code ec, std::size_t length)
if (!ec)
{ {
std::string s(m_rcv_data,length); if (!ec) {
if(parse(s)){ std::string s(m_rcv_data,length);
char c[]="> "; if(parse(s)){
do_write(c,strlen(c)); char c[]="> ";
do_write(c,strlen(c));
}
} }
} });
});
} }
void Session::do_write(char m_snd_data[], std::size_t length) void Session::do_write(char m_snd_data[], std::size_t length)
{ {
auto self(shared_from_this()); auto self(shared_from_this());
asio::async_write(m_socket, asio::buffer(m_snd_data, length), asio::async_write(m_socket, asio::buffer(m_snd_data, length),
[this, self](std::error_code ec, std::size_t /*length*/) [this, self](std::error_code ec, std::size_t /*length*/)
{
if (!ec)
{ {
do_read(); if (!ec) {
} do_read();
}); }
});
} }

View file

@ -1,9 +1,10 @@
#include "commands.hpp" #include "commands.hpp"
#include "trace.hpp"
#include <iostream> #include <iostream>
#include "trace.hpp"
#include "util.hpp"
namespace game { namespace game {
void ShootCommand::apply(Player *player, State *state) const void ShootCommand::apply(Player *player, State *state) const
{ {
@ -12,7 +13,7 @@ namespace game {
// TODO: idea // TODO: idea
// shoot multiple rockets at once or from different positions after // shoot multiple rockets at once or from different positions after
// level up / upgrade ... // level up / upgrade ...
Missile *missile = new Missile(player, player->ship->position, m_angle, player->speed); Missile *missile = new Missile(player, player->ship->position, util::deg2rad(m_angle), player->speed);
Trace *trace = new Trace(missile); Trace *trace = new Trace(missile);
missile->trace = trace; missile->trace = trace;

View file

@ -1,5 +1,6 @@
#include "util.hpp" #include "util.hpp"
#include <cmath>
#include <cstdlib> #include <cstdlib>
namespace util { namespace util {
@ -22,4 +23,14 @@ namespace util {
{ {
return glm::vec2(randf_0_1(), randf_0_1()); return glm::vec2(randf_0_1(), randf_0_1());
} }
float deg2rad(float deg)
{
return M_PI*deg/180.0;
}
float rad2deg(float rad)
{
return 180.0 * rad / M_PI;
}
} }

View file

@ -9,4 +9,7 @@ namespace util {
glm::vec2 randv2_m1_1(); glm::vec2 randv2_m1_1();
glm::vec2 randv2_0_1(); glm::vec2 randv2_0_1();
float deg2rad(float deg);
float rad2deg(float rad);
} }