From 24ee6b011e37eb1f6bfbbeae6a42cf696f3eaadd Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Sun, 23 Sep 2012 15:17:45 -0400 Subject: [PATCH 1/7] draw overlay hover bar --- assets/fs/shaders/overlay_hover.f.glsl | 18 +++++++++ src/client/Client-gl.cc | 56 ++++++++++++++++++++++++-- src/client/Client.h | 2 + 3 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 assets/fs/shaders/overlay_hover.f.glsl diff --git a/assets/fs/shaders/overlay_hover.f.glsl b/assets/fs/shaders/overlay_hover.f.glsl new file mode 100644 index 0000000..d314e70 --- /dev/null +++ b/assets/fs/shaders/overlay_hover.f.glsl @@ -0,0 +1,18 @@ + +varying vec3 pos_i; + +const vec4 red = vec4(1, 0, 0, 1); +const vec4 yellow = vec4(1, 1, 0, 1); +const vec4 green = vec4(0, 1, 0, 1); + +void main(void) +{ + if (pos_i.x < 0) + { + gl_FragColor = mix(red, yellow, pos_i.x + 1); + } + else + { + gl_FragColor = mix(yellow, green, pos_i.x); + } +} diff --git a/src/client/Client-gl.cc b/src/client/Client-gl.cc index 1f49b3a..ec0e8c7 100644 --- a/src/client/Client-gl.cc +++ b/src/client/Client-gl.cc @@ -42,6 +42,12 @@ static const struct {{-0.5, -0.5, 0.0}, {0.0, 0.0}}, {{0.5, -0.5, 0.0}, {1.0, 0.0}} }; +static const float quad_attributes[][3] = { + {0.5, 0.5, 0.0}, + {-0.5, 0.5, 0.0}, + {-0.5, -0.5, 0.0}, + {0.5, -0.5, 0.0} +}; static bool load_file(const char *fname, WFObj::Buffer & buff) { @@ -136,8 +142,10 @@ bool Client::initgl() (const char *) CFS.get_file("shaders/lava.v.glsl", NULL); const char *lava_f_source = (const char *) CFS.get_file("shaders/lava.f.glsl", NULL); + const char *overlay_hover_f_source = + (const char *) CFS.get_file("shaders/overlay_hover.f.glsl", NULL); if (obj_v_source == NULL || obj_f_source == NULL || - overlay_f_source == NULL || + overlay_f_source == NULL || overlay_hover_f_source == NULL || sky_v_source == NULL || sky_f_source == NULL || lava_v_source == NULL || lava_f_source == NULL) { @@ -158,6 +166,13 @@ bool Client::initgl() cerr << "Error creating overlay program" << endl; return false; } + if (!m_overlay_hover_program.create(obj_v_source, overlay_hover_f_source, + obj_attrib_bindings, LEN(obj_attrib_bindings), + sky_uniforms, LEN(sky_uniforms))) + { + cerr << "Error creating overlay hover program" << endl; + return false; + } if (!m_sky_program.create(sky_v_source, sky_f_source, sky_attrib_bindings, LEN(sky_attrib_bindings), sky_uniforms, LEN(sky_uniforms))) @@ -197,7 +212,13 @@ bool Client::initgl() if (!m_tex_quad_attributes.create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, tex_quad_attributes, sizeof(tex_quad_attributes))) { - cerr << "Error creating tex quad attribute buffer" << endl; + cerr << "Error creating tex quad attributes buffer" << endl; + return false; + } + if (!m_quad_attributes.create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, + quad_attributes, sizeof(quad_attributes))) + { + cerr << "Error creating quad attributes buffer" << endl; return false; } vector sky_attributes((NUM_SKY_STEPS + 1) * 2 * (3 * 3)); @@ -386,6 +407,7 @@ void Client::draw_map() void Client::draw_overlay() { + /* draw overlay map */ int overlay_size = (int)(m_width * 0.15); glViewport(m_width - overlay_size - 50, m_height - overlay_size - 50, overlay_size, overlay_size); @@ -441,9 +463,37 @@ void Client::draw_overlay() glPointSize(3); glDrawArrays(GL_POINTS, 0, 1); + /* draw hover bar */ + glViewport(m_width - 200, 100, 150, 25); + m_overlay_hover_program.use(); + m_quad_attributes.bind(); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL); + GLMatrix::Identity.to_uniform( + m_overlay_hover_program.uniform("projection")); + modelview.load_identity(); + modelview.translate(m_player->hover - 1, 0, 0); + modelview.scale(m_player->hover * 2, 2.0, 1.0); + modelview.to_uniform(m_overlay_hover_program.uniform("modelview")); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + /* draw hover bar border */ + glViewport(0, 0, m_width, m_height); + m_overlay_program.use(); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL); + GLMatrix::Identity.to_uniform(m_overlay_program.uniform("projection")); + modelview.load_identity(); + modelview.ortho(0, m_width, 0, m_height, -1, 1); + modelview.translate(m_width - 200 + 150 / 2, 100 + 25 / 2, 0); + modelview.scale(150.1, 25.1, 1); + modelview.to_uniform(m_overlay_program.uniform("modelview")); + glUniform4f(m_overlay_program.uniform("color"), 1, 1, 1, 1); + glDrawArrays(GL_LINE_LOOP, 0, 4); + glDisableVertexAttribArray(0); + + /* reset GL to normal state */ glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); - glViewport(0, 0, m_width, m_height); } void Client::draw_sky() diff --git a/src/client/Client.h b/src/client/Client.h index 766b330..1e0160f 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -39,6 +39,7 @@ class Client int m_height; GLProgram m_obj_program; GLProgram m_overlay_program; + GLProgram m_overlay_hover_program; GLProgram m_sky_program; GLProgram m_lava_program; WFObj m_tank_obj; @@ -49,6 +50,7 @@ class Client GLBuffer m_overlay_hex_indices; GLBuffer m_sky_attributes; GLBuffer m_tex_quad_attributes; + GLBuffer m_quad_attributes; refptr m_net_client; bool client_has_focus; sf::Texture m_lava_texture; From a5b1f5c131cd4b1e283d55b264d53b0fbd283811 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Sun, 23 Sep 2012 15:35:01 -0400 Subject: [PATCH 2/7] draw border around overlay map --- src/client/Client-gl.cc | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/client/Client-gl.cc b/src/client/Client-gl.cc index ec0e8c7..96d6dcd 100644 --- a/src/client/Client-gl.cc +++ b/src/client/Client-gl.cc @@ -477,21 +477,32 @@ void Client::draw_overlay() modelview.to_uniform(m_overlay_hover_program.uniform("modelview")); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - /* draw hover bar border */ + /* draw map border */ glViewport(0, 0, m_width, m_height); m_overlay_program.use(); + m_quad_attributes.bind(); + glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL); GLMatrix::Identity.to_uniform(m_overlay_program.uniform("projection")); modelview.load_identity(); modelview.ortho(0, m_width, 0, m_height, -1, 1); + modelview.translate(m_width - overlay_size / 2 - 50, + m_height - overlay_size / 2 - 50, 0); + modelview.scale(overlay_size + 0.1, overlay_size + 0.1, 1); + modelview.to_uniform(m_overlay_program.uniform("modelview")); + glUniform4f(m_overlay_program.uniform("color"), 1, 1, 1, 1); + glDrawArrays(GL_LINE_LOOP, 0, 4); + + /* draw hover bar border */ + modelview.load_identity(); + modelview.ortho(0, m_width, 0, m_height, -1, 1); modelview.translate(m_width - 200 + 150 / 2, 100 + 25 / 2, 0); modelview.scale(150.1, 25.1, 1); modelview.to_uniform(m_overlay_program.uniform("modelview")); - glUniform4f(m_overlay_program.uniform("color"), 1, 1, 1, 1); glDrawArrays(GL_LINE_LOOP, 0, 4); - glDisableVertexAttribArray(0); /* reset GL to normal state */ + glDisableVertexAttribArray(0); glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); } From 249e7a626caba727c7887585d19ee9bbcb38d856 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Sun, 23 Sep 2012 22:31:34 -0400 Subject: [PATCH 3/7] minor bugfix - using more memory on sky than needed --- src/client/Client-gl.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/Client-gl.cc b/src/client/Client-gl.cc index 96d6dcd..d2726c6 100644 --- a/src/client/Client-gl.cc +++ b/src/client/Client-gl.cc @@ -221,7 +221,7 @@ bool Client::initgl() cerr << "Error creating quad attributes buffer" << endl; return false; } - vector sky_attributes((NUM_SKY_STEPS + 1) * 2 * (3 * 3)); + vector sky_attributes((NUM_SKY_STEPS + 1) * 2 * (3 + 3)); for (int i = 0, idx = 0; i <= NUM_SKY_STEPS; i++) { GLfloat x = SKY_DIST * sin(M_PI_4 + i * M_PI_2 / NUM_SKY_STEPS); From 889ba4735a0956e36fa73873b45d58b52d24a2e8 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Mon, 24 Sep 2012 22:05:52 -0400 Subject: [PATCH 4/7] CCFS: print error when unable to find file by default --- ccfs_gen.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ccfs_gen.py b/ccfs_gen.py index 22b521d..26168f9 100755 --- a/ccfs_gen.py +++ b/ccfs_gen.py @@ -47,6 +47,8 @@ def main(argv): c_file = open(out_fname, 'w') h_file = open(header_fname, 'w') c_file.write('#include \n') + c_file.write('#include \n') + c_file.write('using namespace std;\n') c_file.write('#include "%s"\n' % os.path.basename(header_fname)) for p in paths: c_name = cname(p) @@ -77,7 +79,8 @@ def main(argv): c_file.write('};\n') c_file.write(''' -const unsigned char *CCFSClass::get_file(const char *fname, unsigned int *length) +const unsigned char *CCFSClass::get_file(const char *fname, + unsigned int *length, bool err_on_not_found) { int i; for (i = 0; store[i].fname != NULL; i++) @@ -89,6 +92,8 @@ const unsigned char *CCFSClass::get_file(const char *fname, unsigned int *length return store[i].data; } } + if (err_on_not_found) + cerr << "Error loading file \\"" << fname << '"' << endl; return NULL; } @@ -100,7 +105,8 @@ CCFSClass %s; class CCFSClass { public: - const unsigned char *get_file(const char *fname, unsigned int *length); + const unsigned char *get_file(const char *fname, + unsigned int *length = NULL, bool err_on_not_found = true); }; extern CCFSClass %s; From 7df681082af25187217370f79e2c546b5c9c01e3 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Mon, 24 Sep 2012 22:11:29 -0400 Subject: [PATCH 5/7] simplify GLProgram creation with stdarg --- src/client/Client-gl.cc | 115 +++++++++---------------------------- src/client/GL/GLProgram.cc | 55 ++++++++++++------ src/client/GL/GLProgram.h | 15 ++--- 3 files changed, 70 insertions(+), 115 deletions(-) diff --git a/src/client/Client-gl.cc b/src/client/Client-gl.cc index d2726c6..2acc88a 100644 --- a/src/client/Client-gl.cc +++ b/src/client/Client-gl.cc @@ -93,100 +93,37 @@ bool Client::initgl() return false; } glEnable(GL_DEPTH_TEST); - GLProgram::AttributeBinding obj_attrib_bindings[] = { - {0, "pos"}, - {1, "normal"} - }; - GLProgram::AttributeBinding sky_attrib_bindings[] = { - {0, "pos"}, - {1, "color"} - }; - GLProgram::AttributeBinding lava_attrib_bindings[] = { - {0, "pos"}, - {1, "tex_coord"} - }; - const char *obj_uniforms[] = { - "ambient", - "diffuse", - "specular", - "shininess", - "projection", - "modelview" - }; - const char *overlay_uniforms[] = { - "projection", - "modelview", - "color" - }; - const char *sky_uniforms[] = { - "projection", - "modelview" - }; - const char *lava_uniforms[] = { - "projection", - "modelview", - "tex", - "shift" - }; - const char *obj_v_source = - (const char *) CFS.get_file("shaders/obj.v.glsl", NULL); - const char *obj_f_source = - (const char *) CFS.get_file("shaders/obj.f.glsl", NULL); - const char *overlay_f_source = - (const char *) CFS.get_file("shaders/overlay.f.glsl", NULL); - const char *sky_v_source = - (const char *) CFS.get_file("shaders/sky.v.glsl", NULL); - const char *sky_f_source = - (const char *) CFS.get_file("shaders/sky.f.glsl", NULL); - const char *lava_v_source = - (const char *) CFS.get_file("shaders/lava.v.glsl", NULL); - const char *lava_f_source = - (const char *) CFS.get_file("shaders/lava.f.glsl", NULL); - const char *overlay_hover_f_source = - (const char *) CFS.get_file("shaders/overlay_hover.f.glsl", NULL); - if (obj_v_source == NULL || obj_f_source == NULL || - overlay_f_source == NULL || overlay_hover_f_source == NULL || - sky_v_source == NULL || sky_f_source == NULL || - lava_v_source == NULL || lava_f_source == NULL) - { - cerr << "Error loading shader sources" << endl; + if (!m_obj_program.create( + CFS.get_file("shaders/obj.v.glsl"), + CFS.get_file("shaders/obj.f.glsl"), + "pos", 0, "normal", 1, NULL, + "ambient", "diffuse", "specular", "shininess", + "projection", "modelview", NULL)) return false; - } - if (!m_obj_program.create(obj_v_source, obj_f_source, - obj_attrib_bindings, LEN(obj_attrib_bindings), - obj_uniforms, LEN(obj_uniforms))) - { - cerr << "Error creating obj program" << endl; + if (!m_overlay_program.create( + CFS.get_file("shaders/obj.v.glsl"), + CFS.get_file("shaders/overlay.f.glsl"), + "pos", 0, "normal", 1, NULL, + "projection", "modelview", "color", NULL)) return false; - } - if (!m_overlay_program.create(obj_v_source, overlay_f_source, - obj_attrib_bindings, LEN(obj_attrib_bindings), - overlay_uniforms, LEN(overlay_uniforms))) - { - cerr << "Error creating overlay program" << endl; + if (!m_overlay_hover_program.create( + CFS.get_file("shaders/obj.v.glsl"), + CFS.get_file("shaders/overlay_hover.f.glsl"), + "pos", 0, "normal", 1, NULL, + "projection", "modelview", NULL)) return false; - } - if (!m_overlay_hover_program.create(obj_v_source, overlay_hover_f_source, - obj_attrib_bindings, LEN(obj_attrib_bindings), - sky_uniforms, LEN(sky_uniforms))) - { - cerr << "Error creating overlay hover program" << endl; + if (!m_sky_program.create( + CFS.get_file("shaders/sky.v.glsl"), + CFS.get_file("shaders/sky.f.glsl"), + "pos", 0, "color", 1, NULL, + "projection", "modelview", NULL)) return false; - } - if (!m_sky_program.create(sky_v_source, sky_f_source, - sky_attrib_bindings, LEN(sky_attrib_bindings), - sky_uniforms, LEN(sky_uniforms))) - { - cerr << "Error creating sky program" << endl; + if (!m_lava_program.create( + CFS.get_file("shaders/lava.v.glsl"), + CFS.get_file("shaders/lava.f.glsl"), + "pos", 0, "tex_coord", 1, NULL, + "projection", "modelview", "tex", "shift", NULL)) return false; - } - if (!m_lava_program.create(lava_v_source, lava_f_source, - lava_attrib_bindings, LEN(lava_attrib_bindings), - lava_uniforms, LEN(lava_uniforms))) - { - cerr << "Error creating lava program" << endl; - return false; - } if (!m_tank_obj.load("models/tank.obj", load_file)) { cerr << "Error loading tank model" << endl; diff --git a/src/client/GL/GLProgram.cc b/src/client/GL/GLProgram.cc index 238546a..f2bdcde 100644 --- a/src/client/GL/GLProgram.cc +++ b/src/client/GL/GLProgram.cc @@ -1,5 +1,6 @@ #include "GLProgram.h" +#include #include using namespace std; @@ -7,7 +8,6 @@ using namespace std; GLProgram::GLProgram() { m_id = 0; - m_uniform_locations = NULL; } GLProgram::~GLProgram() @@ -16,29 +16,50 @@ GLProgram::~GLProgram() { glDeleteProgram(m_id); } - if (m_uniform_locations != NULL) - { - delete[] m_uniform_locations; - } } -bool GLProgram::create(const char *v_source, const char *f_source, - GLProgram::AttributeBinding *bindings, int n_bindings, - const char **uniforms, int n_uniforms) +bool GLProgram::create(const char *v_source, const char *f_source, ...) { + va_list va; + va_start(va, f_source); + bool rv = createv(v_source, f_source, va); + va_end(va); + return rv; +} + +bool GLProgram::create(const uint8_t *v_source, const uint8_t *f_source, ...) +{ + va_list va; + va_start(va, f_source); + bool rv = createv((const char *) v_source, (const char *) f_source, va); + va_end(va); + return rv; +} + +bool GLProgram::createv(const char *v_source, const char *f_source, va_list va) +{ + if (v_source == NULL || f_source == NULL) + return false; if (!m_v_shader.create(GL_VERTEX_SHADER, v_source)) return false; if (!m_f_shader.create(GL_FRAGMENT_SHADER, f_source)) return false; m_id = glCreateProgram(); if (m_id <= 0) + { + cerr << "Error allocating GL program object" << endl; return false; + } glAttachShader(m_id, m_v_shader.get_id()); glAttachShader(m_id, m_f_shader.get_id()); - for (int i = 0; i < n_bindings; i++) + for (;;) { - glBindAttribLocation(m_id, bindings[i].index, bindings[i].name); + const char *attribute_name = va_arg(va, const char *); + if (attribute_name == NULL) + break; + GLuint attribute_index = va_arg(va, uint32_t); + glBindAttribLocation(m_id, attribute_index, attribute_name); } glLinkProgram(m_id); @@ -59,14 +80,14 @@ bool GLProgram::create(const char *v_source, const char *f_source, return false; } - if (n_uniforms > 0) + for (;;) { - m_uniform_locations = new GLint[n_uniforms]; - for (int i = 0; i < n_uniforms; i++) - { - m_uniform_locations[i] = glGetUniformLocation(m_id, uniforms[i]); - m_uniform_location_names[uniforms[i]] = m_uniform_locations[i]; - } + const char *uniform_name = va_arg(va, const char *); + if (uniform_name == NULL) + break; + GLint loc = glGetUniformLocation(m_id, uniform_name); + m_uniform_locations.push_back(loc); + m_uniform_location_names[uniform_name] = loc; } return true; diff --git a/src/client/GL/GLProgram.h b/src/client/GL/GLProgram.h index 3ab5b12..362355d 100644 --- a/src/client/GL/GLProgram.h +++ b/src/client/GL/GLProgram.h @@ -2,23 +2,20 @@ #ifndef GLPROGRAM_H #define GLPROGRAM_H +#include #include "GLShader.h" #include #include +#include class GLProgram { public: - typedef struct - { - GLuint index; - const char *name; - } AttributeBinding; GLProgram(); ~GLProgram(); - bool create(const char *v_source, const char *f_source, - AttributeBinding *bindings = NULL, int n_bindings = 0, - const char **uniforms = NULL, int n_uniforms = 0); + bool create(const char *v_source, const char *f_source, ...); + bool create(const uint8_t *v_source, const uint8_t *f_source, ...); + bool createv(const char *v_source, const char *f_source, va_list va); GLuint get_id() { return m_id; } GLint get_uniform_location(const char *name); void get_uniform_locations(const char **names, int num, GLint *locs); @@ -29,7 +26,7 @@ class GLProgram GLuint m_id; GLShader m_v_shader; GLShader m_f_shader; - GLint * m_uniform_locations; + std::vector m_uniform_locations; std::map m_uniform_location_names; }; From ba0bc9b77d8844488f286a2f34ee167b9f4873d0 Mon Sep 17 00:00:00 2001 From: Chris Peterson Date: Tue, 25 Sep 2012 20:36:11 -0400 Subject: [PATCH 6/7] Multiplayer framework in place (can now connect multiple clients and view them in game) Fixed some bugs with multiplayer Changed from refptr > to map > --- src/client/Client-gl.cc | 28 +++--- src/client/Client.cc | 204 ++++++++++++++++++++++++++++------------ src/client/Client.h | 7 +- src/client/main.cc | 8 +- src/common/HexTile.cc | 1 - src/common/HexTile.h | 1 - src/common/Map.cc | 1 - src/common/Map.h | 1 - src/common/Player.cc | 11 ++- src/common/Player.h | 9 +- src/common/Timer.cc | 1 - src/common/Types.h | 5 +- src/common/refptr.h | 1 - src/server/Server.cc | 192 ++++++++++++++++++++++++++----------- src/server/Server.h | 3 +- 15 files changed, 329 insertions(+), 144 deletions(-) diff --git a/src/client/Client-gl.cc b/src/client/Client-gl.cc index 2acc88a..41fc340 100644 --- a/src/client/Client-gl.cc +++ b/src/client/Client-gl.cc @@ -1,4 +1,3 @@ - #include #include #include GL_INCLUDE_FILE @@ -216,16 +215,21 @@ void Client::redraw() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - double dir_x = cos(m_player->direction); - double dir_y = sin(m_player->direction); + double dir_x = cos(m_players[current_player]->direction); + double dir_y = sin(m_players[current_player]->direction); m_modelview.load_identity(); m_modelview.look_at( - m_player->x - dir_x * 25, m_player->y - dir_y * 25, 30, - m_player->x, m_player->y, 20, + m_players[current_player]->x - dir_x * 25, m_players[current_player]->y - dir_y * 25, 30, + m_players[current_player]->x, m_players[current_player]->y, 20, 0, 0, 1); // TODO: call draw_player() for each networked player - draw_player(m_player); + for(std::map >::iterator piter = m_players.begin(); piter != m_players.end(); piter++) + { + draw_player(piter->second); + } + + draw_map(); draw_sky(); draw_lava(); @@ -357,8 +361,8 @@ void Client::draw_overlay() proj.ortho(-span, span, -span, span, -1, 1); proj.to_uniform(m_overlay_program.uniform("projection")); GLMatrix modelview; - modelview.rotate(90 - m_player->direction * 180 / M_PI, 0, 0, 1); - modelview.translate(-m_player->x, -m_player->y, 0); + modelview.rotate(90 - m_players[current_player]->direction * 180 / M_PI, 0, 0, 1); + modelview.translate(-m_players[current_player]->x, -m_players[current_player]->y, 0); m_overlay_hex_attributes.bind(); m_overlay_hex_indices.bind(); glEnableVertexAttribArray(0); @@ -409,8 +413,8 @@ void Client::draw_overlay() GLMatrix::Identity.to_uniform( m_overlay_hover_program.uniform("projection")); modelview.load_identity(); - modelview.translate(m_player->hover - 1, 0, 0); - modelview.scale(m_player->hover * 2, 2.0, 1.0); + modelview.translate(m_players[current_player]->hover - 1, 0, 0); + modelview.scale(m_players[current_player]->hover * 2, 2.0, 1.0); modelview.to_uniform(m_overlay_hover_program.uniform("modelview")); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -450,8 +454,8 @@ void Client::draw_sky() m_sky_attributes.bind(); m_projection.to_uniform(m_sky_program.uniform("projection")); m_modelview.push(); - m_modelview.translate(m_player->x, m_player->y, 0); - m_modelview.rotate(m_player->direction * 180.0 / M_PI, 0, 0, 1); + m_modelview.translate(m_players[current_player]->x, m_players[current_player]->y, 0); + m_modelview.rotate(m_players[current_player]->direction * 180.0 / M_PI, 0, 0, 1); m_modelview.to_uniform(m_sky_program.uniform("modelview")); m_modelview.pop(); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, diff --git a/src/client/Client.cc b/src/client/Client.cc index 349d6b1..0363961 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -1,12 +1,15 @@ #include #include "Client.h" #include "Types.h" +#include "Timer.h" Client::Client() { m_net_client = new Network(); m_net_client->Create(59243, "127.0.0.1"); // Just connect to local host for now - testing client_has_focus = true; + m_players.clear(); + current_player = 0; } Client::~Client() @@ -15,16 +18,16 @@ Client::~Client() } -void Client::run(bool fullscreen, int width, int height) +void Client::run(bool fullscreen, int width, int height, std::string pname) { + Timer client_timer; + client_timer.Init(); + current_player_name = pname; if (!create_window(fullscreen, width, height)) return; - m_player = new Player(); - m_player->x = 0; - m_player->y = 0; - m_player->direction = M_PI_2; m_clock.restart(); sf::Mouse::setPosition(sf::Vector2i(m_width / 2, m_height / 2), *m_window); + double last_time = 0.0; while (m_window->isOpen()) { @@ -63,8 +66,16 @@ void Client::run(bool fullscreen, int width, int height) } } + // Time must be updated before any messages are sent + // Especially guaranteed messages, since the time needs to be + // non zero. + client_timer.Update(); + update(elapsed_time); - redraw(); + if(m_players.size() > 0) + { + redraw(); + } last_time = current_time; // temporary for now. otherwise this thread consumed way too processing @@ -74,81 +85,150 @@ void Client::run(bool fullscreen, int width, int height) void Client::update(double elapsed_time) { - static sf::Uint8 w_pressed_prev = KEY_NOT_PRESSED; - static sf::Uint8 a_pressed_prev = KEY_NOT_PRESSED; - static sf::Uint8 s_pressed_prev = KEY_NOT_PRESSED; - static sf::Uint8 d_pressed_prev = KEY_NOT_PRESSED; - static sf::Int32 rel_mouse_movement_prev = 0; - + static bool registered_player = false; sf::Packet client_packet; + m_net_client->Receive(); client_packet.clear(); // Handle all received data (only really want the latest) while(m_net_client->getData(client_packet)) { - // Update player position as calculated from the server. - client_packet >> m_player->direction; - client_packet >> m_player->x; - client_packet >> m_player->y; + sf::Uint8 packet_type; + client_packet >> packet_type; + switch(packet_type) + { + case PLAYER_CONNECT: + { + sf::Uint8 pindex; + std::string name = ""; + client_packet >> pindex; + client_packet >> name; + // Should be a much better way of doing this. + // Perhaps generate a random number + if(name == current_player_name) + { + current_player = pindex; + } + + // Create a new player if one does not exist. + if(m_players.end() == m_players.find(pindex)) + { + refptr p = new Player(); + p->name = name; + client_packet >> p->direction; + client_packet >> p->x; + client_packet >> p->y; + m_players[pindex] = p; + } + break; + } + case PLAYER_UPDATE: + { + sf::Uint8 player_index; + // Update player position as calculated from the server. + client_packet >> player_index; + if(m_players.end() != m_players.find(player_index)) + { + client_packet >> m_players[player_index]->direction; + client_packet >> m_players[player_index]->x; + client_packet >> m_players[player_index]->y; + } + break; + } + case PLAYER_DISCONNECT: + { + // This will remove the player once the disconnect algorithm is implemented + break; + } + case PLAYER_DEATH: + { + // This will set a death flag in the player struct. + break; + } + default : + { + // Eat the packet + break; + } + } } // For now, we are going to do a very crude shove data into // packet from keyboard and mouse events. // TODO: Clean this up and make it more robust - client_packet.clear(); - - sf::Uint8 w_pressed = KEY_NOT_PRESSED; - sf::Uint8 a_pressed = KEY_NOT_PRESSED; - sf::Uint8 s_pressed = KEY_NOT_PRESSED; - sf::Uint8 d_pressed = KEY_NOT_PRESSED; - sf::Int32 rel_mouse_movement = 0; - - // This is a fix so that the mouse will not move outside the window and - // cause the user to click on another program. - // Note: Does not work well with fast movement. - if(client_has_focus) + if(m_players.size() > 0) { - if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) + sf::Uint8 w_pressed = KEY_NOT_PRESSED; + sf::Uint8 a_pressed = KEY_NOT_PRESSED; + sf::Uint8 s_pressed = KEY_NOT_PRESSED; + sf::Uint8 d_pressed = KEY_NOT_PRESSED; + sf::Int32 rel_mouse_movement = 0; + + // This is a fix so that the mouse will not move outside the window and + // cause the user to click on another program. + // Note: Does not work well with fast movement. + if(client_has_focus) { - a_pressed = KEY_PRESSED; + if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) + { + a_pressed = KEY_PRESSED; + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) + { + d_pressed = KEY_PRESSED; + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) + { + w_pressed = KEY_PRESSED; + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) + { + s_pressed = KEY_PRESSED; + } + rel_mouse_movement = sf::Mouse::getPosition(*m_window).x - m_width / 2; + sf::Mouse::setPosition(sf::Vector2i(m_width / 2, m_height / 2), *m_window); } - if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) + + // Send an update to the server if something has changed + if((m_players[current_player]->w_pressed != w_pressed) || + (m_players[current_player]->a_pressed != a_pressed) || + (m_players[current_player]->s_pressed != s_pressed) || + (m_players[current_player]->d_pressed != d_pressed) || + (m_players[current_player]->rel_mouse_movement != rel_mouse_movement)) { - d_pressed = KEY_PRESSED; + sf::Uint8 packet_type = PLAYER_UPDATE; + client_packet.clear(); + client_packet << packet_type; + client_packet << current_player; + client_packet << w_pressed; + client_packet << a_pressed; + client_packet << s_pressed; + client_packet << d_pressed; + client_packet << rel_mouse_movement; + + m_net_client->sendData(client_packet); + + m_players[current_player]->w_pressed = w_pressed; + m_players[current_player]->a_pressed = a_pressed; + m_players[current_player]->s_pressed = s_pressed; + m_players[current_player]->d_pressed = d_pressed; + m_players[current_player]->rel_mouse_movement = rel_mouse_movement; } - if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) - { - w_pressed = KEY_PRESSED; - } - if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) - { - s_pressed = KEY_PRESSED; - } - rel_mouse_movement = sf::Mouse::getPosition(*m_window).x - m_width / 2; - sf::Mouse::setPosition(sf::Vector2i(m_width / 2, m_height / 2), *m_window); } - - // Send an update to the server if something has changed - if((w_pressed_prev != w_pressed) || - (a_pressed_prev != a_pressed) || - (s_pressed_prev != s_pressed) || - (d_pressed_prev != d_pressed) || - (rel_mouse_movement_prev != rel_mouse_movement)) + else if(!registered_player) { - client_packet << w_pressed; - client_packet << a_pressed; - client_packet << s_pressed; - client_packet << d_pressed; - client_packet << rel_mouse_movement; - - m_net_client->sendData(client_packet); - - w_pressed_prev = w_pressed; - a_pressed_prev = a_pressed; - s_pressed_prev = s_pressed; - d_pressed_prev = d_pressed; - rel_mouse_movement_prev = rel_mouse_movement; + sf::Uint8 packet_type = PLAYER_CONNECT; + client_packet.clear(); + client_packet << packet_type; + client_packet << current_player; + client_packet << current_player_name; + m_net_client->sendData(client_packet, true); + registered_player = true; + } + else + { + // Do nothing. } m_net_client->Transmit(); } diff --git a/src/client/Client.h b/src/client/Client.h index 1e0160f..6518f71 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -1,4 +1,3 @@ - #ifndef CLIENT_H #define CLIENT_H @@ -18,7 +17,7 @@ class Client public: Client(); ~Client(); - void run(bool fullscreen, int width, int height); + void run(bool fullscreen, int width, int height, std::string pname); protected: bool create_window(bool fullscreen, int width, int height); bool initgl(); @@ -34,7 +33,9 @@ class Client refptr m_window; sf::Clock m_clock; Map m_map; - refptr m_player; + sf::Uint8 current_player; + std::string current_player_name; + std::map > m_players; int m_width; int m_height; GLProgram m_obj_program; diff --git a/src/client/main.cc b/src/client/main.cc index ec111df..276275d 100644 --- a/src/client/main.cc +++ b/src/client/main.cc @@ -1,4 +1,3 @@ - #include #include #include "Client.h" @@ -8,11 +7,13 @@ int main(int argc, char *argv[]) bool fullscreen = false; int width = 1200; int height = 900; + std::string player_name = "Player"; struct option longopts[] = { {"fullscreen", no_argument, NULL, 'f'}, {"height", required_argument, NULL, 'h'}, {"width", required_argument, NULL, 'w'}, + {"name", required_argument, NULL, 'n'}, {NULL, 0, NULL, 0} }; for (;;) @@ -31,12 +32,15 @@ int main(int argc, char *argv[]) case 'w': width = atoi(optarg); break; + case 'n': + player_name = std::string(optarg); + break; } } Client client; - client.run(fullscreen, width, height); + client.run(fullscreen, width, height, player_name); return 0; } diff --git a/src/common/HexTile.cc b/src/common/HexTile.cc index e9774bb..526c1e5 100644 --- a/src/common/HexTile.cc +++ b/src/common/HexTile.cc @@ -1,4 +1,3 @@ - #include #include "HexTile.h" diff --git a/src/common/HexTile.h b/src/common/HexTile.h index b4c1beb..4944ad6 100644 --- a/src/common/HexTile.h +++ b/src/common/HexTile.h @@ -1,4 +1,3 @@ - #ifndef HEXTILE_H #define HEXTILE_H diff --git a/src/common/Map.cc b/src/common/Map.cc index ea901b3..4953752 100644 --- a/src/common/Map.cc +++ b/src/common/Map.cc @@ -1,4 +1,3 @@ - #include "Map.h" #include "HexTile.h" diff --git a/src/common/Map.h b/src/common/Map.h index 64e898d..b3050ba 100644 --- a/src/common/Map.h +++ b/src/common/Map.h @@ -1,4 +1,3 @@ - #ifndef MAP_H #define MAP_H diff --git a/src/common/Player.cc b/src/common/Player.cc index c9467fc..2b76977 100644 --- a/src/common/Player.cc +++ b/src/common/Player.cc @@ -1,10 +1,17 @@ - #include "Player.h" +#include Player::Player() { x = 0.0; y = 0.0; - direction = 0.0; + direction = M_PI_2; hover = 1.0; + name = ""; + w_pressed = KEY_NOT_PRESSED; + a_pressed = KEY_NOT_PRESSED; + s_pressed = KEY_NOT_PRESSED; + d_pressed = KEY_NOT_PRESSED; + rel_mouse_movement = 0; + updated = false; } diff --git a/src/common/Player.h b/src/common/Player.h index 6f662a7..015e0c5 100644 --- a/src/common/Player.h +++ b/src/common/Player.h @@ -1,8 +1,9 @@ - #ifndef PLAYER_H #define PLAYER_H #include +#include "Types.h" +#include "SFML/Config.hpp" class Player { @@ -12,6 +13,12 @@ class Player double y; double direction; /* 0 = East, M_PI_2 = North, M_PI = West, ... */ double hover; + sf::Uint8 w_pressed; + sf::Uint8 a_pressed; + sf::Uint8 s_pressed; + sf::Uint8 d_pressed; + sf::Int32 rel_mouse_movement; + bool updated; Player(); }; diff --git a/src/common/Timer.cc b/src/common/Timer.cc index b5e5137..8c854e9 100644 --- a/src/common/Timer.cc +++ b/src/common/Timer.cc @@ -23,7 +23,6 @@ void Timer::Update(void) { // Record the time step stepTime = ((myClock.getElapsedTime().asSeconds() / 1000.0f) * gameSpeed); - //stepTime = ((((sf::Window*)screen)->GetFrameTime() / 1000.0f) * gameSpeed); myClock.restart(); // Add the time to the total time diff --git a/src/common/Types.h b/src/common/Types.h index 215e744..a2da1d9 100644 --- a/src/common/Types.h +++ b/src/common/Types.h @@ -4,6 +4,9 @@ #define KEY_PRESSED 0xA5u #define KEY_NOT_PRESSED 0x5Au - +#define PLAYER_CONNECT 0x1Au +#define PLAYER_DISCONNECT 0x2Bu +#define PLAYER_DEATH 0x3Cu +#define PLAYER_UPDATE 0x4Du #endif diff --git a/src/common/refptr.h b/src/common/refptr.h index 7335af5..6209953 100644 --- a/src/common/refptr.h +++ b/src/common/refptr.h @@ -1,4 +1,3 @@ - #ifndef REFPTR_H #define REFPTR_H REFPTR_H diff --git a/src/server/Server.cc b/src/server/Server.cc index 9b28625..1344f94 100644 --- a/src/server/Server.cc +++ b/src/server/Server.cc @@ -1,15 +1,13 @@ #include "Server.h" #include "Types.h" #include +#include "Timer.h" Server::Server(sf::Uint16 port) { m_net_server = new Network(); m_net_server->Create(port, sf::IpAddress::None); - m_player = new Player(); - m_player->x = 0; - m_player->y = 0; - m_player->direction = M_PI_2; + m_players.clear(); } Server::~Server() @@ -22,10 +20,18 @@ void Server::run( void ) double current_time; double elapsed_time; double last_time = 0.0; + Timer server_timer; + server_timer.Init(); while(1) { current_time = m_clock.getElapsedTime().asSeconds(); elapsed_time = current_time - last_time; + + // Time must be updated before any messages are sent + // Especially guaranteed messages, since the time needs to be + // non zero. + server_timer.Update(); + update( elapsed_time ); last_time = current_time; @@ -40,65 +46,143 @@ void Server::update( double elapsed_time ) static Player player_prev; const double move_speed = 75.0; sf::Packet server_packet; - static sf::Uint8 w_pressed = KEY_NOT_PRESSED; - static sf::Uint8 a_pressed = KEY_NOT_PRESSED; - static sf::Uint8 s_pressed = KEY_NOT_PRESSED; - static sf::Uint8 d_pressed = KEY_NOT_PRESSED; - static sf::Int32 rel_mouse_movement = 0; m_net_server->Receive(); // Handle all received data (only really want the latest) while(m_net_server->getData(server_packet)) { - server_packet >> w_pressed; - server_packet >> a_pressed; - server_packet >> s_pressed; - server_packet >> d_pressed; - server_packet >> rel_mouse_movement; + sf::Uint8 ptype; + // Get packet type + server_packet >> ptype; + switch(ptype) + { + case PLAYER_CONNECT: + { + refptr p = new Player(); + std::string pname; + sf::Uint8 pindex; + + server_packet >> pindex; + server_packet >> pname; + // When a player connects, we need to associate + // that player with a new ID. find first unused id + // player zero means a player does not exist. + if(pindex == 0) + { + for(pindex = 1u; pindex < 255u; pindex++ ) + { + if(m_players.end() == m_players.find(pindex)) + { + break; + } + } + p->name = pname; + m_players[pindex] = p; + + // Alert all connected clients of all the connected players. + for(std::map >::iterator piter = m_players.begin(); piter != m_players.end(); piter++) + { + server_packet.clear(); + server_packet << ptype; + server_packet << piter->first; + server_packet << piter->second->name; + // Send correct starting locations so that they match + // the other players screens. + server_packet << piter->second->direction; + server_packet << piter->second->x; + server_packet << piter->second->y; + m_net_server->sendData(server_packet, true); + } + } + break; + } + case PLAYER_UPDATE: + { + // Need to determine the correct player id + // then update the stored contents. + sf::Uint8 pindex; + server_packet >> pindex; + if(m_players.end() != m_players.find(pindex)) + { + server_packet >> m_players[pindex]->w_pressed; + server_packet >> m_players[pindex]->a_pressed; + server_packet >> m_players[pindex]->s_pressed; + server_packet >> m_players[pindex]->d_pressed; + server_packet >> m_players[pindex]->rel_mouse_movement; + } + break; + } + case PLAYER_DISCONNECT: + { + // This completely removes the player from the game + // Deletes member from the player list + break; + } + case PLAYER_DEATH: + { + // This just forces the player to dissapper from the + // playing field. + break; + } + default: + { + // Just eat the packet + break; + } + } } - if (KEY_PRESSED == a_pressed) + for(std::map >::iterator piter = m_players.begin(); piter != m_players.end(); piter++) { - double direction = m_player->direction + M_PI_2; - m_player->x += cos(direction) * move_speed * elapsed_time; - m_player->y += sin(direction) * move_speed * elapsed_time; - } - if (KEY_PRESSED == d_pressed) - { - double direction = m_player->direction - M_PI_2; - m_player->x += cos(direction) * move_speed * elapsed_time; - m_player->y += sin(direction) * move_speed * elapsed_time; - } - if (KEY_PRESSED == w_pressed) - { - double direction = m_player->direction; - m_player->x += cos(direction) * move_speed * elapsed_time; - m_player->y += sin(direction) * move_speed * elapsed_time; - } - if (KEY_PRESSED == s_pressed) - { - double direction = m_player->direction + M_PI; - m_player->x += cos(direction) * move_speed * elapsed_time; - m_player->y += sin(direction) * move_speed * elapsed_time; - } - m_player->direction -= M_PI * 0.5 * rel_mouse_movement / 1000; + sf::Uint8 pindex = piter->first; + if (KEY_PRESSED == m_players[pindex]->a_pressed) + { + double direction = m_players[pindex]->direction + M_PI_2; + m_players[pindex]->x += cos(direction) * move_speed * elapsed_time; + m_players[pindex]->y += sin(direction) * move_speed * elapsed_time; + m_players[pindex]->updated = true; + } + if (KEY_PRESSED == m_players[pindex]->d_pressed) + { + double direction = m_players[pindex]->direction - M_PI_2; + m_players[pindex]->x += cos(direction) * move_speed * elapsed_time; + m_players[pindex]->y += sin(direction) * move_speed * elapsed_time; + m_players[pindex]->updated = true; + } + if (KEY_PRESSED == m_players[pindex]->w_pressed) + { + double direction = m_players[pindex]->direction; + m_players[pindex]->x += cos(direction) * move_speed * elapsed_time; + m_players[pindex]->y += sin(direction) * move_speed * elapsed_time; + m_players[pindex]->updated = true; + } + if (KEY_PRESSED == m_players[pindex]->s_pressed) + { + double direction = m_players[pindex]->direction + M_PI; + m_players[pindex]->x += cos(direction) * move_speed * elapsed_time; + m_players[pindex]->y += sin(direction) * move_speed * elapsed_time; + m_players[pindex]->updated = true; + } + if(0 != m_players[pindex]->rel_mouse_movement) + { + m_players[pindex]->direction -= M_PI * 0.5 * m_players[pindex]->rel_mouse_movement / 1000; + m_players[pindex]->updated = true; + } - server_packet.clear(); - - // Send the player update if there were changes - if((player_prev.direction != m_player->direction) || - (player_prev.x != m_player->x) || - (player_prev.y != m_player->y)) - { - server_packet << m_player->direction; - server_packet << m_player->x; - server_packet << m_player->y; - m_net_server->sendData(server_packet); - - player_prev.direction = m_player->direction; - player_prev.x = m_player->x; - player_prev.y = m_player->y; - } + server_packet.clear(); + // Send the player update if there were changes + if(m_players[pindex]->updated) + { + sf::Uint8 ptype = PLAYER_UPDATE; + server_packet << ptype; + server_packet << pindex; + server_packet << m_players[pindex]->direction; + server_packet << m_players[pindex]->x; + server_packet << m_players[pindex]->y; + m_net_server->sendData(server_packet); + m_players[pindex]->updated = false; + } + } m_net_server->Transmit(); } diff --git a/src/server/Server.h b/src/server/Server.h index 5812a06..248b045 100644 --- a/src/server/Server.h +++ b/src/server/Server.h @@ -1,6 +1,7 @@ #include "Network.h" #include "Player.h" #include "refptr.h" +#include "SFML/Config.hpp" class Server{ public: @@ -11,6 +12,6 @@ class Server{ protected: void update(double elapsed_time); refptr m_net_server; - refptr m_player; + std::map > m_players; sf::Clock m_clock; }; From 741a325a5f4195679b6c8b4a04cab34ae9c026b4 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Thu, 27 Sep 2012 23:01:52 -0400 Subject: [PATCH 7/7] add shot-ring shader and create shot-ring attributes buffer --- assets/fs/shaders/shot-ring.f.glsl | 5 +++++ assets/fs/shaders/shot-ring.v.glsl | 13 +++++++++++++ src/client/Client-gl.cc | 25 +++++++++++++++++++++++++ src/client/Client.h | 1 + 4 files changed, 44 insertions(+) create mode 100644 assets/fs/shaders/shot-ring.f.glsl create mode 100644 assets/fs/shaders/shot-ring.v.glsl diff --git a/assets/fs/shaders/shot-ring.f.glsl b/assets/fs/shaders/shot-ring.f.glsl new file mode 100644 index 0000000..660872d --- /dev/null +++ b/assets/fs/shaders/shot-ring.f.glsl @@ -0,0 +1,5 @@ + +void main(void) +{ + gl_FragColor = vec4(1.0, 0.1, 0.1, 1.0); +} diff --git a/assets/fs/shaders/shot-ring.v.glsl b/assets/fs/shaders/shot-ring.v.glsl new file mode 100644 index 0000000..2d2fb41 --- /dev/null +++ b/assets/fs/shaders/shot-ring.v.glsl @@ -0,0 +1,13 @@ + +uniform mat4 projection; +uniform mat4 modelview; +uniform float scale; + +/* pos.xyz is position, pos.w is offset */ +attribute vec4 pos; + +void main(void) +{ + vec3 pos3 = pos.xyz * (scale + pos.w); + gl_Position = projection * modelview * vec4(pos3, 1); +} diff --git a/src/client/Client-gl.cc b/src/client/Client-gl.cc index 41fc340..c1ade35 100644 --- a/src/client/Client-gl.cc +++ b/src/client/Client-gl.cc @@ -17,6 +17,8 @@ using namespace std; #define SKY_DIST 2000 #define NUM_SKY_STEPS 9 #define LAVA_SIZE 100 +#define SHOT_RING_WIDTH 20.0f +#define NUM_SHOT_RING_STEPS 24 /* points of a horizontal hexagon 1.0 units high */ static const float overlay_hex_attributes[][3] = { @@ -183,6 +185,29 @@ bool Client::initgl() cerr << "Error creating sky attribute buffer" << endl; return false; } + vector shot_ring_attributes((NUM_SHOT_RING_STEPS + 1) * 2 * 4); + for (int i = 0, idx = 0; i <= NUM_SHOT_RING_STEPS; i++) + { + double angle = i * M_PI * 2.0 / NUM_SHOT_RING_STEPS; + GLfloat x = sin(angle); + GLfloat y = cos(angle); + shot_ring_attributes[idx++] = x; + shot_ring_attributes[idx++] = y; + shot_ring_attributes[idx++] = 0.0f; + shot_ring_attributes[idx++] = 0.0f; + + shot_ring_attributes[idx++] = x; + shot_ring_attributes[idx++] = y; + shot_ring_attributes[idx++] = 0.0f; + shot_ring_attributes[idx++] = SHOT_RING_WIDTH; + } + if (!m_shot_ring_attributes.create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, + &shot_ring_attributes[0], + sizeof(shot_ring_attributes[0]) * shot_ring_attributes.size())) + { + cerr << "Error creating shot ring attributes buffer" << endl; + return false; + } unsigned int lava_texture_length; const uint8_t *lava_texture = CFS.get_file("textures/lava.jpg", &lava_texture_length); diff --git a/src/client/Client.h b/src/client/Client.h index 6518f71..0c967c4 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -52,6 +52,7 @@ class Client GLBuffer m_sky_attributes; GLBuffer m_tex_quad_attributes; GLBuffer m_quad_attributes; + GLBuffer m_shot_ring_attributes; refptr m_net_client; bool client_has_focus; sf::Texture m_lava_texture;