From 70e354291067bfac400b73887dab0044250e6677 Mon Sep 17 00:00:00 2001 From: gmueller Date: Thu, 6 Jan 2011 13:51:52 +0100 Subject: [PATCH] add bombs, closes #24 --- src/game.cpp | 65 ++++++++++++- src/game.h | 29 ++++-- src/main.cpp | 256 +++++++++++++++++++++++++++++++++------------------ 3 files changed, 245 insertions(+), 105 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index aa2a34b..974e8be 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1,6 +1,7 @@ #include "game.h" #include +#include void game_setup_team(team_t *team, uint8_t id) { team->id = id; @@ -55,7 +56,7 @@ player_t *game_spawn_player(game_t *game, team_t *team) { return player; } -player_t *game_spawn_player_id(game_t *game, team_t *team, uint8_t id) { +player_t *game_spawn_player_id(game_t *game, team_t *team, uint16_t id) { player_t *player = _game_free_player(game); player->team = team; player->id = id; @@ -75,7 +76,7 @@ void game_update_players(game_t *game, double dt) { size_t i; for (i = 0; i < GAME_PLAYER_COUNT; i++) { player_t *player = &game->player[i]; - if(player->status == 0) + if (player->status == 0) return; player->x += player->vx * dt; player->y += player->vy * dt; @@ -83,11 +84,54 @@ void game_update_players(game_t *game, double dt) { } } +void _explode_bomb(game_t *game, bomb_t *bomb, void(*explosion_callback)( + double x, double y, double z)) { + size_t i; + for (i = 0; i < GAME_PLAYER_COUNT; i++) { + player_t *player = &game->player[i]; + if (player->status == 0) + return; + double distance2 = pow(player->x - bomb->x, 2) + pow(player->y + - bomb->y, 2) + pow(player->z - bomb->z, 2); + if (distance2 < 10000.0) { + explosion_callback(player->x, player->y, player->z); + player->x = player->team->x + 100; + player->y = player->team->y; + player->z = player->team->z; + player->vx = 0.; + player->vy = 0.; + player->vz = 0.; + } + } +} + +void game_update_bombs(game_t *game, double dt, void(*explosion_callback)( + double x, double y, double z)) { + size_t i; + for (i = 0; i < GAME_BOMB_COUNT; i++) { + bomb_t *bomb = &game->bomb[i]; + if (bomb->status == 0) + return; + bomb->x += bomb->vx * dt; + bomb->y += bomb->vy * dt; + bomb->z += bomb->vz * dt; + bomb->ttl -= dt; + if (bomb->ttl < 0) { + if (bomb->status == 1) { + explosion_callback(bomb->x, bomb->y, bomb->z); + bomb->status = 2; + } else if (bomb->ttl < 0.8) { + _explode_bomb(game, bomb, explosion_callback); + bomb->status = 0; + } + } + } +} size_t game_active_team_players(game_t *game, team_t *team) { size_t i, count = 0; for (i = 0; i < GAME_PLAYER_COUNT; i++) { - if(game->player[i].status == 0) + if (game->player[i].status == 0) continue; if (game->player[i].team == team) count++; @@ -108,7 +152,7 @@ team_t *game_team_with_least_players(game_t *game) { return team; } -team_t *game_team(game_t *game, uint8_t id){ +team_t *game_team(game_t *game, uint16_t id) { size_t i; for (i = 0; i < GAME_TEAM_COUNT; i++) { if (game->team[i].id == id) { @@ -118,7 +162,7 @@ team_t *game_team(game_t *game, uint8_t id){ return NULL; } -player_t *game_player(game_t *game, uint8_t id){ +player_t *game_player(game_t *game, uint16_t id) { size_t i; for (i = 0; i < GAME_PLAYER_COUNT; i++) { if (game->player[i].id == id) { @@ -127,3 +171,14 @@ player_t *game_player(game_t *game, uint8_t id){ } return NULL; } + +bomb_t *game_spawn_bomb(game_t *game) { + size_t i; + for (i = 0; i < GAME_BOMB_COUNT; i++) { + if (game->bomb[i].status == 0) { + game->bomb[i].status = 1; + return &game->bomb[i]; + } + } + return NULL; +} diff --git a/src/game.h b/src/game.h index 58a28f5..c971afd 100644 --- a/src/game.h +++ b/src/game.h @@ -9,18 +9,26 @@ typedef struct game_t game_t; #define GAME_TEAM_COUNT 8 #define GAME_PLAYER_COUNT 64 +#define GAME_BOMB_COUNT (GAME_PLAYER_COUNT * 4) struct player_t { - uint8_t id; - uint8_t status; + uint16_t id; + uint16_t status; double x, y, z; double rx, ry, rz, rw; double vx, vy, vz; team_t *team; }; +struct bomb_t { + uint8_t status; + double x, y, z; + double vx, vy, vz; + double ttl; +}; + struct team_t { - uint8_t id; + uint16_t id; double x, y, z; float color[4]; }; @@ -28,15 +36,20 @@ struct team_t { struct game_t { team_t team[GAME_TEAM_COUNT]; player_t player[GAME_PLAYER_COUNT]; - int32_t max_player_id; + bomb_t bomb[GAME_BOMB_COUNT]; + int16_t max_player_id; }; extern void game_setup(game_t *game); extern team_t *game_team_with_least_players(game_t *game); extern player_t *game_spawn_player(game_t *game, team_t *team); -extern player_t *game_spawn_player_id(game_t *game, team_t *team, uint8_t id); -extern team_t *game_team(game_t *game, uint8_t id); -extern player_t *game_player(game_t *game, uint8_t id); +extern player_t *game_spawn_player_id(game_t *game, team_t *team, uint16_t id); +extern team_t *game_team(game_t *game, uint16_t id); +extern player_t *game_player(game_t *game, uint16_t id); +extern bomb_t *game_bomb(game_t *game, uint16_t index); extern void game_update_players(game_t *game, double dt); +extern bomb_t *game_spawn_bomb(game_t *game); +extern void game_update_bombs(game_t *game, double dt, + void(*explosion_callback)(double x, double y, double z)); -#endif \ No newline at end of file +#endif diff --git a/src/main.cpp b/src/main.cpp index 081af33..3df7da8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -85,6 +85,18 @@ void draw_player(player_t *player) { glPopMatrix(); } +void draw_bomb(bomb_t *bomb) { + if (bomb->status != 1) + return; + GLfloat red[] = { 1.0f, 0.0f, 0.0f, 1.0f }; + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); + glMatrixMode( GL_MODELVIEW); + glPushMatrix(); + glTranslated(bomb->x, bomb->y, bomb->z); + gluSphere(quadratic, 3.f, 32, 32); + glPopMatrix(); +} + void setup_network(const char *remote) { if (enet_initialize() != 0) { fprintf(stderr, "An error occurred while initializing ENet.\n"); @@ -147,6 +159,8 @@ void setup_network(const char *remote) { #define MESSAGE_ACCEPT 2 #define MESSAGE_PLAYER_UPDATE 3 #define MESSAGE_PLAYER_ACCELERATE 4 +#define MESSAGE_BOMB_DROP 5 +#define MESSAGE_BOMB_UPDATE 6 typedef struct message_t { uint16_t msg_id; @@ -155,22 +169,22 @@ typedef struct message_t { typedef struct player_spawn_message_t { uint16_t msg_id; uint8_t team_id; - uint8_t player_id; + uint16_t player_id; } player_spawn_message_t; typedef struct player_kill_message_t { uint16_t msg_id; - uint8_t player_id; + uint16_t player_id; } player_kill_message_t; typedef struct accept_message_t { uint16_t msg_id; - uint8_t player_id; + uint16_t player_id; } accept_message_t; typedef struct player_update_message_t { uint16_t msg_id; - uint8_t player_id; + uint16_t player_id; unsigned int session; double x, y, z; double vx, vy, vz; @@ -178,10 +192,25 @@ typedef struct player_update_message_t { typedef struct player_accelerate_message_t { uint16_t msg_id; - uint8_t player_id; + uint16_t player_id; double x, y, z; } player_accelerate_message_t; +typedef struct bomb_drop_meesage_t { + uint16_t msg_id; + double x, y, z; + double vx, vy, vz; + double ttl; +} bomb_drop_meesage_t; + +typedef struct bomb_update_meesage_t { + uint16_t msg_id; + uint16_t bomb_index; + double x, y, z; + double vx, vy, vz; + double ttl; +} bomb_update_meesage_t; + void send_player_updates(game_t *game) { size_t i; for (i = 0; i < GAME_PLAYER_COUNT; i++) { @@ -201,6 +230,68 @@ void send_player_updates(game_t *game) { } } +void dispatch_message(enet_uint8 *data, size_t length, game_t *game) { + message_t *msg = (message_t *) data; + switch (msg->msg_id) { + case MESSAGE_PLAYER_SPAWN: { + player_spawn_message_t *sm = (player_spawn_message_t *) data; + team_t *team = game_team(game, sm->team_id); + player_t *player = game_spawn_player_id(game, team, sm->player_id); + break; + } + case MESSAGE_PLAYER_KILL: { + player_kill_message_t *sm = (player_kill_message_t *) data; + player_t *player = game_player(game, sm->player_id); + player->status = 0; + player->team = 0; + break; + } + case MESSAGE_ACCEPT: { + accept_message_t *am = (accept_message_t *) data; + local_player = game_player(game, am->player_id); + printf("Spwan as %d.%d\n", local_player->team->id, local_player->id); + break; + } + case MESSAGE_PLAYER_UPDATE: { + player_update_message_t *um = (player_update_message_t *) data; + player_t *player = game_player(game, um->player_id); + player->x = um->x; + player->y = um->y; + player->z = um->z; + player->vx = um->vx; + player->vy = um->vy; + player->vz = um->vz; + break; + } + case MESSAGE_PLAYER_ACCELERATE: { + player_accelerate_message_t *um = (player_accelerate_message_t *) data; + player_t *player = game_player(game, um->player_id); + player->vx += um->x; + player->vy += um->y; + player->vz += um->z; + break; + } + case MESSAGE_BOMB_DROP: { + bomb_drop_meesage_t *m = (bomb_drop_meesage_t *) data; + bomb_t *bomb = game_spawn_bomb(game); + if (bomb == NULL) + return; + bomb->x = m->x; + bomb->y = m->y; + bomb->z = m->z; + bomb->vx = m->vx; + bomb->vy = m->vy; + bomb->vz = m->vz; + bomb->ttl = m->ttl; + if (client_peer == NULL) { + ENetPacket * packet = enet_packet_create(data, length, + ENET_PACKET_FLAG_RELIABLE); + enet_host_broadcast(host, 0, packet); + } + break; + } + }; +} void service_network(game_t *game) { ENetEvent event; @@ -253,63 +344,8 @@ void service_network(game_t *game) { break; case ENET_EVENT_TYPE_RECEIVE: { -#if 0 - printf( - "A packet of length %u was received from %s on channel %u.\n", - event.packet->dataLength, event.packet->data, - event.peer->data, event.channelID); -#endif - /* Clean up the packet now that we're done using it. */ - message_t *msg = (message_t *) event.packet->data; - switch (msg->msg_id) { - case MESSAGE_PLAYER_SPAWN: { - player_spawn_message_t *sm = - (player_spawn_message_t *) event.packet->data; - team_t *team = game_team(game, sm->team_id); - player_t *player = game_spawn_player_id(game, team, - sm->player_id); - } - break; - case MESSAGE_PLAYER_KILL: { - player_kill_message_t *sm = - (player_kill_message_t *) event.packet->data; - player_t *player = game_player(game, sm->player_id); - player->status = 0; - player->team = 0; - } - break; - case MESSAGE_ACCEPT: { - accept_message_t *am = (accept_message_t *) event.packet->data; - local_player = game_player(game, am->player_id); - printf("Spwan as %d.%d\n", local_player->team->id, - local_player->id); - } - break; - case MESSAGE_PLAYER_UPDATE: { - player_update_message_t *um = - (player_update_message_t *) event.packet->data; - player_t *player = game_player(game, um->player_id); - player->x = um->x; - player->y = um->y; - player->z = um->z; - player->vx = um->vx; - player->vy = um->vy; - player->vz = um->vz; - } - break; - case MESSAGE_PLAYER_ACCELERATE: { - player_accelerate_message_t *um = - (player_accelerate_message_t *) event.packet->data; - player_t *player = game_player(game, um->player_id); - player->vx += um->x; - player->vy += um->y; - player->vz += um->z; - } - break; - }; - + dispatch_message(event.packet->data, event.packet->dataLength, game); enet_packet_destroy(event.packet); - break; } case ENET_EVENT_TYPE_DISCONNECT: @@ -335,20 +371,38 @@ void service_network(game_t *game) { } -void accelerate(double x, double y, double z) { - local_player->vx += x; - local_player->vy += y; - local_player->vz += z; +void accelerate(game_t *game, double x, double y, double z) { + player_accelerate_message_t msg; + msg.msg_id = MESSAGE_PLAYER_ACCELERATE; + msg.player_id = local_player->id; + msg.x = x; + msg.y = y; + msg.z = z; if (client_peer) { - player_accelerate_message_t msg; - msg.msg_id = MESSAGE_PLAYER_ACCELERATE; - msg.player_id = local_player->id; - msg.x = x; - msg.y = y; - msg.z = z; ENetPacket * packet = enet_packet_create(&msg, sizeof(msg), ENET_PACKET_FLAG_RELIABLE); enet_peer_send(client_peer, 0, packet); + } else { + dispatch_message((uint8_t*) &msg, sizeof(msg), game); + } +} + +void drop_bomb(game_t *game, double x, double y, double z, double ttl) { + bomb_drop_meesage_t msg; + msg.msg_id = MESSAGE_BOMB_DROP; + msg.x = x; + msg.y = y; + msg.z = z; + msg.vx = local_player->vx; + msg.vy = local_player->vy; + msg.vz = local_player->vz; + msg.ttl = ttl; + if (client_peer) { + ENetPacket * packet = enet_packet_create(&msg, sizeof(msg), + ENET_PACKET_FLAG_RELIABLE); + enet_peer_send(client_peer, 0, packet); + } else { + dispatch_message((uint8_t*) &msg, sizeof(msg), game); } } @@ -398,9 +452,14 @@ void setup_explosion() { textures[4]); } +void explosion_callback(double x, double y, double z) { + explosion.add(x, y, z); +} + int main(int argc, char ** argv) { int width, height, x, y, last_x, last_y; - double time, last_time, phi = 0.0, theta = 0.0, last_player_update; + double time, last_time, phi = 0.0, theta = 0.0, last_player_update, + last_bomb; GLboolean running; int server = 0; @@ -430,6 +489,8 @@ int main(int argc, char ** argv) { running = GL_TRUE; last_time = glfwGetTime(); last_player_update = last_time; + last_bomb = last_time; + double camX, camY, camZ; glfwGetMousePos(&last_x, &last_y); while (running) { // Get time and mouse position @@ -447,27 +508,45 @@ int main(int argc, char ** argv) { last_x = x; last_y = y; + if (local_player) { + camX = local_player->x; + camY = local_player->y; + camZ = local_player->z; + } else { + camX = 1000.0; + camY = 1000.0; + camZ = 1000.0; + } + double rx = cos(phi) * cos(theta); double ry = sin(theta); double rz = sin(phi) * cos(theta); double v = 50.0f * dt; if (glfwGetKey('W')) { - accelerate(rx * v, ry * v, rz * v); + accelerate(&game, rx * v, ry * v, rz * v); } else if (glfwGetKey('S')) { - accelerate(rx * -v, ry * -v, rz * -v); + accelerate(&game, rx * -v, ry * -v, rz * -v); } if (glfwGetKey('A')) { - accelerate(rz * v, 0, -rx * v); + accelerate(&game, rz * v, 0, -rx * v); } else if (glfwGetKey('D')) { - accelerate(-rz * v, 0, rx * v); + accelerate(&game, -rz * v, 0, rx * v); } if (glfwGetKey(GLFW_KEY_SPACE)) { - accelerate(local_player->vx * -dt, local_player->vy * -dt, + accelerate(&game, local_player->vx * -dt, local_player->vy * -dt, local_player->vz * -dt); } + if (glfwGetKey(GLFW_KEY_LCTRL)) { + if (time - last_bomb > 5.0) { + last_bomb = time; + drop_bomb(&game, local_player->x + rx - 20.0, local_player->y + + ry * -20.0, local_player->z + rz * -20.0, 5.0); + } + } + if (glfwGetKey(GLFW_KEY_ENTER)) { explosion.add(200.0, 200.0, 200.0); } @@ -492,19 +571,9 @@ int main(int argc, char ** argv) { // Select and setup the modelview matrix glMatrixMode( GL_MODELVIEW); glLoadIdentity(); - if (local_player) { - gluLookAt(local_player->x, local_player->y, - local_player->z, // Eye-position - local_player->x + cos(phi) * cos(theta) * 10.0f, - local_player->y + sin(theta) * 10.0f, local_player->z - + sin(phi) * cos(theta) * 10.0f, // View-point - 0.0f, 1.0f, 0.0f); // Up-vector - } else { - gluLookAt(100.0f, 100.0f, 100.0f, // Eye-position - 100.0f + cos(phi) * cos(theta) * 10.0f, 100.0f + sin(theta) - * 10.0f, 100.0f + sin(phi) * cos(theta) * 10.0f, // View-point - 0.0f, 1.0f, 0.0f); // Up-vector - } + gluLookAt(camX, camY, camZ, camX + cos(phi) * cos(theta) * 10.0f, camY + + sin(theta) * 10.0f, camZ + sin(phi) * cos(theta) * 10.0f, // View-point + 0.0f, 1.0f, 0.0f); // Up-vector service_network(&game); if (server) { @@ -515,6 +584,7 @@ int main(int argc, char ** argv) { } game_update_players(&game, dt); + game_update_bombs(&game, dt, explosion_callback); glEnable( GL_LIGHT0); glEnable( GL_LIGHTING); @@ -534,11 +604,13 @@ int main(int argc, char ** argv) { for (i = 0; i < GAME_PLAYER_COUNT; i++) draw_player(&game.player[i]); + for (i = 0; i < GAME_BOMB_COUNT; i++) + draw_bomb(&game.bomb[i]); + glDisable(GL_LIGHT0); glDisable(GL_LIGHTING); glDisable(GL_CULL_FACE); - explosion.update(dt * 1000.0, local_player->x, local_player->y, - local_player->z); + explosion.update(dt * 1000.0, camX, camY, camZ); explosion.render(); // Swap buffers