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/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; diff --git a/src/client/Client-gl.cc b/src/client/Client-gl.cc index 915489b..41fc340 100644 --- a/src/client/Client-gl.cc +++ b/src/client/Client-gl.cc @@ -1,4 +1,3 @@ - #include #include #include GL_INCLUDE_FILE @@ -42,6 +41,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) { @@ -87,91 +92,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); - if (obj_v_source == NULL || obj_f_source == NULL || - overlay_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_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_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_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; + 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_tank_obj.load("models/tank.obj", load_file)) { cerr << "Error loading tank model" << endl; @@ -197,10 +148,16 @@ 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; } - vector sky_attributes((NUM_SKY_STEPS + 1) * 2 * (3 * 3)); + 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)); 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); @@ -258,22 +215,22 @@ void Client::redraw() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - double dir_x = cos((*m_players)[current_player].direction); - double dir_y = sin((*m_players)[current_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_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, + 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 - for(std::map::iterator piter = m_players->begin(); piter != m_players->end(); piter++) - { - draw_player(piter->second); - } - - - draw_map(); + for(std::map >::iterator piter = m_players.begin(); piter != m_players.end(); piter++) + { + draw_player(piter->second); + } + + + draw_map(); draw_sky(); draw_lava(); @@ -282,12 +239,12 @@ void Client::redraw() m_window->display(); } -void Client::draw_player(Player player) +void Client::draw_player(refptr player) { m_obj_program.use(); m_modelview.push(); - m_modelview.translate(player.x, player.y, 4); - m_modelview.rotate(player.direction * 180.0 / M_PI, 0, 0, 1); + m_modelview.translate(player->x, player->y, 4); + m_modelview.rotate(player->direction * 180.0 / M_PI, 0, 0, 1); m_modelview.scale(2, 2, 2); m_tank_obj.bindBuffers(); glEnableVertexAttribArray(0); @@ -391,6 +348,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); @@ -403,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_players)[current_player].direction * 180 / M_PI, 0, 0, 1); - modelview.translate(-(*m_players)[current_player].x, -(*m_players)[current_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); @@ -446,9 +404,48 @@ 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_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); + + /* 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")); + glDrawArrays(GL_LINE_LOOP, 0, 4); + + /* reset GL to normal state */ + glDisableVertexAttribArray(0); glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); - glViewport(0, 0, m_width, m_height); } void Client::draw_sky() @@ -457,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_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.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 f6d3a81..0363961 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -1,15 +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 = new std::map; - m_players->clear(); - current_player = 0; + client_has_focus = true; + m_players.clear(); + current_player = 0; } Client::~Client() @@ -20,13 +20,14 @@ Client::~Client() void Client::run(bool fullscreen, int width, int height, std::string pname) { - - current_player_name = pname; + Timer client_timer; + client_timer.Init(); + current_player_name = pname; if (!create_window(fullscreen, width, height)) return; 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()) { @@ -65,12 +66,17 @@ void Client::run(bool fullscreen, int width, int height, std::string pname) } } + // 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); - if(m_players->size() > 0) - { - redraw(); - } - last_time = current_time; + if(m_players.size() > 0) + { + redraw(); + } + last_time = current_time; // temporary for now. otherwise this thread consumed way too processing sf::sleep(sf::seconds(0.005)); // 5 milli-seconds @@ -79,7 +85,7 @@ void Client::run(bool fullscreen, int width, int height, std::string pname) void Client::update(double elapsed_time) { - static bool registered_player = false; + static bool registered_player = false; sf::Packet client_packet; @@ -88,127 +94,141 @@ void Client::update(double elapsed_time) // Handle all received data (only really want the latest) while(m_net_client->getData(client_packet)) { - sf::Uint8 packet_type; - client_packet >> packet_type; - switch(packet_type) - { - case PLAYER_CONNECT: - { - Player p; - sf::Uint8 pindex; - std::string name = ""; - client_packet >> pindex; - client_packet >> name; - if(name == current_player_name) - { - current_player = pindex; - } - p.name = name; - (*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; - } - } + 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 - if(m_players->size() > 0) - { - 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; + if(m_players.size() > 0) + { + 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 (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); - } + // 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 (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); + } - // 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)) - { - 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; + // 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)) + { + 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_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; - } - } - else if(!registered_player) - { - 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); - registered_player = true; - } + 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; + } + } + else if(!registered_player) + { + 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 f6232e7..6518f71 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -1,4 +1,3 @@ - #ifndef CLIENT_H #define CLIENT_H @@ -25,7 +24,7 @@ class Client void resize_window(int width, int height); void update(double elapsed_time); void redraw(); - void draw_player(Player player); + void draw_player(refptr player); void draw_map(); void draw_overlay(); void draw_sky(); @@ -34,13 +33,14 @@ class Client refptr m_window; sf::Clock m_clock; Map m_map; - sf::Uint8 current_player; - std::string current_player_name; - refptr< std::map > m_players; + sf::Uint8 current_player; + std::string current_player_name; + std::map > m_players; int m_width; 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; @@ -51,6 +51,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; 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; }; diff --git a/src/client/main.cc b/src/client/main.cc index 84bdff3..276275d 100644 --- a/src/client/main.cc +++ b/src/client/main.cc @@ -1,4 +1,3 @@ - #include #include #include "Client.h" @@ -8,14 +7,14 @@ int main(int argc, char *argv[]) bool fullscreen = false; int width = 1200; int height = 900; - std::string player_name = "Player"; + 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} + {NULL, 0, NULL, 0} }; for (;;) { @@ -33,9 +32,9 @@ int main(int argc, char *argv[]) case 'w': width = atoi(optarg); break; - case 'n': - player_name = std::string(optarg); - break; + case 'n': + player_name = std::string(optarg); + break; } } 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 1bf8ee1..2b76977 100644 --- a/src/common/Player.cc +++ b/src/common/Player.cc @@ -1,4 +1,3 @@ - #include "Player.h" #include @@ -8,11 +7,11 @@ Player::Player() y = 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; + 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 e692d81..015e0c5 100644 --- a/src/common/Player.h +++ b/src/common/Player.h @@ -1,4 +1,3 @@ - #ifndef PLAYER_H #define PLAYER_H @@ -14,12 +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; + 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 91c0620..a2da1d9 100644 --- a/src/common/Types.h +++ b/src/common/Types.h @@ -4,9 +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 +#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 d5ab153..1344f94 100644 --- a/src/server/Server.cc +++ b/src/server/Server.cc @@ -1,13 +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_players = new std::map; - m_players->clear(); + m_players.clear(); } Server::~Server() @@ -20,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; @@ -43,132 +51,138 @@ void Server::update( double elapsed_time ) // Handle all received data (only really want the latest) while(m_net_server->getData(server_packet)) { - sf::Uint8 ptype; - // Get packet type - server_packet >> ptype; - switch(ptype) - { - case PLAYER_CONNECT: - { - Player p; - 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; - - // Send a response to the newly added player - server_packet.clear(); - server_packet << ptype; - server_packet << pindex; - server_packet << p.name; - 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; - } - } - } - - for(std::map::iterator piter = m_players->begin(); piter != m_players->end(); piter++) - { - sf::Uint8 pindex = piter->first; - double direction = (*m_players)[pindex].direction; - direction -= M_PI * 0.5 * (*m_players)[pindex].rel_mouse_movement / 1000; - if(direction != (*m_players)[pindex].direction) - { - (*m_players)[pindex].direction = direction; - (*m_players)[pindex].updated = true; - } - if (KEY_PRESSED == (*m_players)[pindex].a_pressed) - { - 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) - { - 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) - { - 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) - { - 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; - } - - server_packet.clear(); + sf::Uint8 ptype; + // Get packet type + server_packet >> ptype; + switch(ptype) + { + case PLAYER_CONNECT: + { + refptr p = new Player(); + std::string pname; + sf::Uint8 pindex; - // 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; - } - } + 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; + } + } + } + + for(std::map >::iterator piter = m_players.begin(); piter != m_players.end(); piter++) + { + 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(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 ff8b064..248b045 100644 --- a/src/server/Server.h +++ b/src/server/Server.h @@ -12,6 +12,6 @@ class Server{ protected: void update(double elapsed_time); refptr m_net_server; - refptr< std::map > m_players; + std::map > m_players; sf::Clock m_clock; };