diff --git a/data/shader/gameobjects.vert b/data/shader/gameobjects.vert index 7d9c827..91f5184 100644 --- a/data/shader/gameobjects.vert +++ b/data/shader/gameobjects.vert @@ -9,11 +9,12 @@ varying vec3 lightDirection; uniform mat4 model; uniform vec3 lightPosition; +uniform float aspectRatio; void main() { // TODO: this becomes invalid when projection matrices are used - vec3 p = (model*vec4(in_vertex, 1.0)).xyz; + vec3 p = (model*vec4(in_vertex/vec3(aspectRatio, 1.0, 1.0), 1.0)).xyz; lightDirection = normalize(lightPosition - p); vertex = p.xyz; diff --git a/data/shader/particle.frag b/data/shader/particle.frag index 1c3307e..87e9819 100644 --- a/data/shader/particle.frag +++ b/data/shader/particle.frag @@ -4,7 +4,6 @@ varying vec3 velocity; varying float decay; varying float explCenterDist; -uniform vec3 explCenter; vec3 hsv2rgb(vec3 c) { diff --git a/data/shader/particle.vert b/data/shader/particle.vert index 4cf4f03..68f698d 100644 --- a/data/shader/particle.vert +++ b/data/shader/particle.vert @@ -14,6 +14,8 @@ varying vec3 velocity; varying vec2 vertex; varying float explCenterDist; +uniform float aspectRatio; + // TODO: rotate to face the user! void main() { @@ -38,5 +40,5 @@ void main() vertex = base.xy; velocity = in_velocity; - explCenterDist = length(explCenter-offset); + explCenterDist = length(explCenter - offset); } \ No newline at end of file diff --git a/game/game.cpp b/game/game.cpp index 52cf3cf..c6c448a 100644 --- a/game/game.cpp +++ b/game/game.cpp @@ -80,3 +80,7 @@ bool Game::cycle(float dt) return true; } +void Game::resize(int width, int height) +{ + m_state->setPlayingFieldSize(width, height); +} diff --git a/game/game.hpp b/game/game.hpp index 707e713..9bbaff1 100644 --- a/game/game.hpp +++ b/game/game.hpp @@ -13,6 +13,9 @@ class Game { // for rendering game::State *state() const { return m_state; } + // resize the playing field + void resize(int width, int height); + private: game::State *m_state; diff --git a/game/game_window.hpp b/game/game_window.hpp index 1a201c3..3723bd4 100644 --- a/game/game_window.hpp +++ b/game/game_window.hpp @@ -45,7 +45,21 @@ class GameWindow : public endofthejedi::GLWindow { m_renderer.render(m_game->state()); } - void resize() override { glViewport(0, 0, getwidth(), getheight()); } + void resize() override + { + std::cout<<"resize()" << std::endl; + + glViewport(0, 0, getwidth(), getheight()); + + // resize the game + m_game->resize(getwidth(), getheight()); + + // TODO: mark it and let the reinit() happen in the next so it happnens just once. while doing the resize + m_game->state()->init(); + + // resize the renderer + m_renderer.setWindowSize(getwidth(), getheight()); + } public: GameWindow(unsigned int width, unsigned int height, Game *ptr) diff --git a/game/opengl.cpp b/game/opengl.cpp index 5d370d6..e1e99ef 100644 --- a/game/opengl.cpp +++ b/game/opengl.cpp @@ -99,6 +99,7 @@ namespace endofthejedi { m_width = attribs.width; m_height = attribs.height; resize(); + } else if (event.type == ClientMessage) { if (event.xclient.data.l[0] == m_atomWmDeleteWindow) { stop(); diff --git a/game/renderer.hpp b/game/renderer.hpp index a07c00c..ae96d0a 100644 --- a/game/renderer.hpp +++ b/game/renderer.hpp @@ -5,6 +5,8 @@ #include #include +#include + #include "game.hpp" namespace endofthejedi { @@ -21,6 +23,9 @@ namespace endofthejedi { public: virtual void setup() { } virtual void render(const game::State *state) = 0; + + virtual void setWindowSize(int px, int py) { (void) px; (void) py; } + virtual void setCameraMatrix(const glm::mat4 &cam) { (void) cam; } }; } diff --git a/game/renderer_polygon_3d/particle_batch.cpp b/game/renderer_polygon_3d/particle_batch.cpp index 7d63ab4..8fa8fec 100644 --- a/game/renderer_polygon_3d/particle_batch.cpp +++ b/game/renderer_polygon_3d/particle_batch.cpp @@ -33,14 +33,16 @@ namespace endofthejedi { m_data_velocity.resize(m_numParticles); m_data_kind.resize(m_numParticles); m_data_max_age.resize(m_numParticles); + } - std::string vss_particles = "../data/shader/particle.vert"; - std::string fss_particles = "../data/shader/particle.frag"; - - m_shader.init(); - m_shader.loadFile(vss_particles, GL_VERTEX_SHADER); - m_shader.loadFile(fss_particles, GL_FRAGMENT_SHADER); + ParticleBatch::~ParticleBatch() + { + // TODO: find out if stuff must be deallocated + glDeleteBuffers(5, m_data_vbos); + } + void ParticleBatch::setup(Shader *shader) + { const char *names[] = { "in_vertex", "in_position", @@ -51,18 +53,12 @@ namespace endofthejedi { for (int i=0; i<5; i++) { const char *name = names[i]; - GLint loc = glGetAttribLocation(m_shader.program(), name); + GLint loc = glGetAttribLocation(shader->program(), name); m_attr_locations[i] = loc; //std::cout<<"attr location " << i << " " << loc << " " << name << std::endl; } } - ParticleBatch::~ParticleBatch() - { - // TODO: find out if stuff must be deallocated - glDeleteBuffers(5, m_data_vbos); - } - void ParticleBatch::setCenter(const glm::vec3 ¢er) { m_center = center; @@ -130,16 +126,14 @@ namespace endofthejedi { } } - void ParticleBatch::render() + void ParticleBatch::render(Shader *shader) { //std::cout<<"[ParticleBatch] render " << std::endl; - m_shader.bind(); - - glUniform1f(m_shader.location("age"), m_age); - glUniform1f(m_shader.location("maxVelocity"), m_maxVelocity); - glUniform1f(m_shader.location("halfAge"), m_halfAge); - glUniform1f(m_shader.location("size"), m_particleRadius); - glUniform3f(m_shader.location("explCenter"), m_center.x, m_center.y, m_center.z); + glUniform1f(shader->location("age"), m_age); + glUniform1f(shader->location("maxVelocity"), m_maxVelocity); + glUniform1f(shader->location("halfAge"), m_halfAge); + glUniform1f(shader->location("size"), m_particleRadius); + glUniform3f(shader->location("explCenter"), m_center.x, m_center.y, m_center.z); bind(); diff --git a/game/renderer_polygon_3d/particle_batch.hpp b/game/renderer_polygon_3d/particle_batch.hpp index 5c7de78..72ddf28 100644 --- a/game/renderer_polygon_3d/particle_batch.hpp +++ b/game/renderer_polygon_3d/particle_batch.hpp @@ -22,15 +22,14 @@ namespace endofthejedi { void setCenter(const glm::vec3 ¢er); void setMaxVelocity(float maxVelocity); + void setup(Shader *shader); void bind(); void upload(); - void render(); + void render(Shader *shader); void tick(float dt); bool done() const; - Shader *shader() { return &m_shader; } - size_t id() const { return m_id; } private: @@ -55,7 +54,5 @@ namespace endofthejedi { std::vector m_data_max_age; GLuint m_attr_locations[5]; - - Shader m_shader; }; } diff --git a/game/renderer_polygon_3d/renderer_polygon_3d.cpp b/game/renderer_polygon_3d/renderer_polygon_3d.cpp index 8f02b37..1c2ad02 100644 --- a/game/renderer_polygon_3d/renderer_polygon_3d.cpp +++ b/game/renderer_polygon_3d/renderer_polygon_3d.cpp @@ -2,11 +2,6 @@ #include -#include -#include -#include -#include - namespace endofthejedi { void RendererPolygon3d::setup() { @@ -14,19 +9,21 @@ namespace endofthejedi { std::cout<<"setup polygon 3d" << std::endl; - m_shader.init(); - -#if 0 - std::string vss_simple = "../data/shader/simple.vert"; - std::string fss_simple = "../data/shader/simple.frag"; - m_shader.loadFile(vss_simple, GL_VERTEX_SHADER); - m_shader.loadFile(fss_simple, GL_FRAGMENT_SHADER); -#else std::string vss_game_objects = "../data/shader/gameobjects.vert"; std::string fss_game_objects = "../data/shader/gameobjects.frag"; - m_shader.loadFile(vss_game_objects, GL_VERTEX_SHADER); - m_shader.loadFile(fss_game_objects, GL_FRAGMENT_SHADER); -#endif + + m_shader_game_objects.init(); + m_shader_game_objects.loadFile(vss_game_objects, GL_VERTEX_SHADER); + m_shader_game_objects.loadFile(fss_game_objects, GL_FRAGMENT_SHADER); + + + std::string vss_particles = "../data/shader/particle.vert"; + std::string fss_particles = "../data/shader/particle.frag"; + + m_shader_particles.init(); + m_shader_particles.loadFile(vss_particles, GL_VERTEX_SHADER); + m_shader_particles.loadFile(fss_particles, GL_FRAGMENT_SHADER); + //addModel("../data/mesh/small_atomic_bomb.stl", &m_missileModel); addModel("../data/mesh/rocket.stl", &m_missileModel); @@ -56,17 +53,22 @@ namespace endofthejedi { //float s = 0.1; //glClearColor(s, s, s, 1.0); - m_shader.bind(); + m_shader_game_objects.bind(); // TODO: add ONE sun planet // TODO: add lights for explosions configureLightningInShader(); + //std::cout<<"setting aspect ratio: " << m_aspectRatio << std::endl; + glUniform1f(m_shader_game_objects.location("aspectRatio"), m_aspectRatio); + renderPlanets(); renderShips(); renderMissiles(); + renderParticles(); + renderTraces(); //glColor3f(1.0, 0.0, 0.0); @@ -82,9 +84,13 @@ namespace endofthejedi { void RendererPolygon3d::renderParticles() { + m_shader_particles.bind(); + + glUniform1f(m_shader_particles.location("aspectRatio"), m_aspectRatio); + for (ParticleBatch *batch : m_particles) { batch->bind(); - batch->render(); + batch->render(&m_shader_particles); } } @@ -100,6 +106,7 @@ namespace endofthejedi { float maxVelocity = 0.4f; ParticleBatch *batch = new ParticleBatch(id, n, particleRadius, duration); + batch->setup(&m_shader_particles); batch->setCenter(glm::vec3(pos, 0.0)); batch->setMaxVelocity(maxVelocity); @@ -168,12 +175,12 @@ namespace endofthejedi { // too (same for missiles) for (const game::Planet *planet : m_state->planets) { glm::mat4 model = computeModelMatrix(planet); - glUniformMatrix4fv(m_shader.location("model"), 1, GL_FALSE, glm::value_ptr(model)); + glUniformMatrix4fv(m_shader_game_objects.location("model"), 1, GL_FALSE, glm::value_ptr(model)); glm::vec3 c = planet->getColor(); - glUniform3f(m_shader.location("materialColor"), c.x, c.y, c.z); - glUniform1i(m_shader.location("materialSeed"), planet->seed); - glUniform1i(m_shader.location("materialKind"), (int) planet->material); + glUniform3f(m_shader_game_objects.location("materialColor"), c.x, c.y, c.z); + glUniform1i(m_shader_game_objects.location("materialSeed"), planet->seed); + glUniform1i(m_shader_game_objects.location("materialKind"), (int) planet->material); m_planetModel->render(); } @@ -186,10 +193,10 @@ namespace endofthejedi { for (const game::Player *player : m_state->players) { for (const game::Missile *missile : player->missiles) { glm::vec3 c = glm::vec3(1.0, 1.0, 0.3); - glUniform3f(m_shader.location("materialColor"), c.x, c.y, c.z); + glUniform3f(m_shader_game_objects.location("materialColor"), c.x, c.y, c.z); glm::mat4 model = computeModelMatrix(missile); - glUniformMatrix4fv(m_shader.location("model"), 1, GL_FALSE, glm::value_ptr(model)); + glUniformMatrix4fv(m_shader_game_objects.location("model"), 1, GL_FALSE, glm::value_ptr(model)); m_missileModel->render(); } @@ -202,10 +209,10 @@ namespace endofthejedi { for (const game::Ship *ship : m_state->ships) { glm::mat4 model = computeModelMatrix(ship); - glUniformMatrix4fv(m_shader.location("model"), 1, GL_FALSE, glm::value_ptr(model)); + glUniformMatrix4fv(m_shader_game_objects.location("model"), 1, GL_FALSE, glm::value_ptr(model)); glm::vec3 c = glm::vec3(0.1, 1.0, 0.2); - glUniform3f(m_shader.location("materialColor"), c.x, c.y, c.z); + glUniform3f(m_shader_game_objects.location("materialColor"), c.x, c.y, c.z); m_shipModel->render(); } @@ -221,7 +228,7 @@ namespace endofthejedi { exit(-1); } - (*dest)->setup(&m_shader); + (*dest)->setup(&m_shader_game_objects); (*dest)->uploadToOpenGl(); m_models.push_back(*dest); @@ -319,7 +326,17 @@ namespace endofthejedi { } } - glUniform3f(m_shader.location("lightPosition"), p.x, p.y, p.z); - glUniform3f(m_shader.location("lightColor"), c.x, c.y, c.z); + glUniform3f(m_shader_game_objects.location("lightPosition"), p.x, p.y, p.z); + glUniform3f(m_shader_game_objects.location("lightColor"), c.x, c.y, c.z); + } + + void RendererPolygon3d::setWindowSize(int px, int py) + { + m_aspectRatio = (float) px / (float) py; + } + + void RendererPolygon3d::setCameraMatrix(const glm::mat4 &cam) + { + (void) cam; } } diff --git a/game/renderer_polygon_3d/renderer_polygon_3d.hpp b/game/renderer_polygon_3d/renderer_polygon_3d.hpp index 69a0152..acdc851 100644 --- a/game/renderer_polygon_3d/renderer_polygon_3d.hpp +++ b/game/renderer_polygon_3d/renderer_polygon_3d.hpp @@ -2,6 +2,13 @@ #include +#include +#include +#include +#include +#include +#include + #include "glclasses.hpp" #include "game.hpp" @@ -17,9 +24,6 @@ #include "particle_batch.hpp" #include "polygon_model.hpp" -#include -#include - namespace endofthejedi { class RendererPolygon3d : public Renderer { @@ -27,6 +31,9 @@ namespace endofthejedi { void setup(); void render(const game::State *state) override; + void setWindowSize(int px, int py); + void setCameraMatrix(const glm::mat4 &cam); + private: void renderPlanets(); void renderMissiles(); @@ -61,7 +68,8 @@ namespace endofthejedi { PolygonModel *m_shipModel; // for rendering everything - Shader m_shader; + Shader m_shader_game_objects; + Shader m_shader_particles; // for accessing const game::State *m_state; @@ -70,5 +78,7 @@ namespace endofthejedi { // time value for last rendering cycle (-1 after setup/startup) float m_lastTime; + + float m_aspectRatio; }; } diff --git a/game/state/state.cpp b/game/state/state.cpp index a094071..7276cd1 100644 --- a/game/state/state.cpp +++ b/game/state/state.cpp @@ -10,7 +10,6 @@ #include "object.hpp" #include "missile.hpp" #include "player.hpp" -#include "planet.hpp" #include "ship.hpp" #include "commands.hpp" #include "trace.hpp" @@ -21,6 +20,14 @@ namespace game { void State::init(int numPlanets, bool devMode) { + for (Planet *planet : planets) { + delete(planet); + } + planets.clear(); + + //for (Player *player : players) { + //} + m_nextId = 0; m_time = 0.0; m_shipRadius = 0.02; @@ -30,33 +37,59 @@ namespace game { m_maxNumTraces = 10; m_developerMode = devMode; - Planet::Material mat = Planet::Material::Rock; + setPlayingFieldCenter(0, 0); - for (int i=0; iposition, *pos); + + float extraDist = (other->material == Planet::Material::Sun) + ? 4.0 + : 1.0; + + if (d < extraDist*other->radius + radius) { + collidesWithOtherPlanet = true; + break; + } + } + } + if (tries++ > 1000) { + return false; } - glm::vec2 pos; + } while(collidesWithOtherPlanet || tooNearToCenter); + + return true; + } + + void State::setupPlanets(int numPlanets) + { + for (int i=0; iposition, pos); + case 3: + case 4: + return Planet::Material::Sand; - float extraDist = (other->material == Planet::Material::Sun) - ? 4.0 - : 1.0; + case 5: + return Planet::Material::Metal; - if (d < extraDist*other->radius + radius) { - collidesWithOtherPlanet = true; - break; - } - } - } - - } while((collidesWithOtherPlanet || tooNearToCenter) && tries++ < 1000); - - planets.push_back(new Planet(pos, i, radius, mat)); + default: + return Planet::Material::Rock; } } @@ -430,4 +461,14 @@ namespace game { deleteTrace(trace); } } + + void State::setPlayingFieldCenter(int center_x, int center_y) + { + m_playingFieldCenter = glm::vec2((float) center_x, (float) center_y); + } + + void State::setPlayingFieldSize(int width, int height) + { + m_playingFieldSize = glm::vec2(width, height); + } } diff --git a/game/state/state.hpp b/game/state/state.hpp index aab4e81..2850ff9 100644 --- a/game/state/state.hpp +++ b/game/state/state.hpp @@ -10,6 +10,7 @@ #include #include "missile.hpp" +#include "planet.hpp" // TODO: // give points for equipment / better weapons / more energy when: @@ -27,7 +28,7 @@ namespace game { // forward declarations class Command; class Player; - class Planet; + class Ship; class Trace; class Explosion; @@ -91,6 +92,11 @@ namespace game { m_developerMode = on; } + // called when the rendering window changes + // TODO: give dpi as information too + void setPlayingFieldSize(int width, int height); + void setPlayingFieldCenter(int width, int height); + /*************************************************************************/ /* Rendering */ /*************************************************************************/ @@ -111,12 +117,15 @@ namespace game { void playerKillsPlayer(Player *killer, Player *victim); void addExplosionFromHit(const Missile::Event *evt); + bool findPlanetSpawnPosition(bool planetIsSun, float radius, glm::vec2 *pos); void advanceTraceAges(float dt); void advanceExplosions(float dt); void advancePlayerShipSpawns(float dt); void advancePlayerCommands(float dt); void advancePlayerMissiles(float dt); + void setupPlanets(int numPlanets); + Planet::Material materialForStandardPlanetDistribution(int index); // try to spawn a ship for this player. // return true on success, false on failure to find a spot. @@ -134,5 +143,8 @@ namespace game { int m_maxNumTraces; float m_time; bool m_developerMode; + + glm::vec2 m_playingFieldCenter; + glm::vec2 m_playingFieldSize; }; };