diff options
| author | Aldrik Ramaekers <aldrik@amftech.nl> | 2022-12-12 18:06:53 +0100 |
|---|---|---|
| committer | Aldrik Ramaekers <aldrik@amftech.nl> | 2022-12-12 18:06:53 +0100 |
| commit | 9528c0c69dba57117f38f84f576af2c81a3b435b (patch) | |
| tree | 14f3b21a19f3733e05d64e1fc4113af52516a441 /src | |
| parent | 10ae402862df4337772fe8e35f68ee8ab5bfc224 (diff) | |
multiplayer
Diffstat (limited to 'src')
| -rw-r--r-- | src/bullets.c | 8 | ||||
| -rw-r--r-- | src/game.c | 140 | ||||
| -rw-r--r-- | src/players.c | 81 | ||||
| -rw-r--r-- | src/protocol.c | 38 | ||||
| -rw-r--r-- | src/zombies.c | 102 |
5 files changed, 266 insertions, 103 deletions
diff --git a/src/bullets.c b/src/bullets.c index c2f6d3b..191b342 100644 --- a/src/bullets.c +++ b/src/bullets.c @@ -169,10 +169,10 @@ void draw_bullets(platform_window* window) { for (int i = 0; i < max_bullets; i++) { bullet b = bullets[i]; if (!b.active) continue; - player p = get_player_by_id(b.player_id); - bullets[i].position.x = p.gunx; - bullets[i].position.y = p.guny; - bullets[i].position.z = p.gun_height; + player *p = get_player_by_id(b.player_id); + bullets[i].position.x = p->gunx; + bullets[i].position.y = p->guny; + bullets[i].position.z = p->gun_height; if (check_if_bullet_collided_with_ground(&b, window)) { bullets[i].endy = b.endy; @@ -14,7 +14,7 @@ void start_server(char* port) { void connect_to_server(char* ip, char* port) { messages_received_on_client = array_create(sizeof(protocol_generic_message*)); array_reserve(&messages_received_on_client, 100); - + global_state.network_state = CONNECTING; global_state.client = network_connect_to_server(ip, port); global_state.client->on_message = client_on_message_received; @@ -54,28 +54,119 @@ void destroy_game() { if (global_state.client) network_client_close(global_state.client); } -void update_server() { +static void broadcast_to_clients(network_message message) { + if (!global_state.server || !global_state.server->is_open) return; + for (int i = 0; i < global_state.server->clients.length; i++) { + network_client* client = array_at(&global_state.server->clients, i); + network_client_send(client, message); + } +} + +static void rotate_user(platform_window* window, protocol_user_look *message) { + player* p = get_player_by_id(message->id); + if (p == 0) { + log_info("Unknown user rotated"); + return; + } + + p->gunx = message->gunx; + p->guny = message->guny; +} + +static void move_user(platform_window* window, protocol_move *message) { + float speed = 0.1f; + float pad_between_player_and_obj = 0.01f; + + player* p = get_player_by_id(message->id); + if (p == 0) { + log_info("Unknown user moved"); + return; + } + + if (message->move == MOVE_UP) { + float newy = p->playery - speed; + if (is_in_bounds(p->playerx, newy)) { + p->playery = newy; + object o = check_if_player_collided_with_object(window, *p); + if (o.active) p->playery = o.position.y+o.size.y - get_player_size_in_tile() + pad_between_player_and_obj; + } + } + + if (message->move == MOVE_DOWN) { + float newy = p->playery + speed; + if (is_in_bounds(p->playerx, newy)) { + p->playery = newy; + object o = check_if_player_collided_with_object(window, *p); + if (o.active) p->playery = o.position.y - get_player_size_in_tile() - pad_between_player_and_obj; + } + } + + if (message->move == MOVE_LEFT) { + float newx = p->playerx - speed; + if (is_in_bounds(newx, p->playery)) { + p->playerx = newx; + object o = check_if_player_collided_with_object(window, *p); + if (o.active) p->playerx = o.position.x+o.size.x + pad_between_player_and_obj; + } + } + + if (message->move == MOVE_RIGHT) { + float newx = p->playerx + speed; + if (is_in_bounds(newx, p->playery)) { + p->playerx = newx; + object o = check_if_player_collided_with_object(window, *p); + if (o.active) p->playerx = o.position.x-get_player_size_in_tile() - pad_between_player_and_obj; + } + } +} + +float update_timer = 0.0f; +void update_server(platform_window* window) { + update_spawners(); + update_zombies_server(window); + for (int i = 0; i < messages_received_on_server.length; i++) { protocol_generic_message* msg = *(protocol_generic_message**)array_at(&messages_received_on_server, i); - switch (msg->type) + switch (msg->message->type) { - case MESSAGE_GET_ID_UPSTREAM: { - network_client_send(&msg->client, create_protocol_get_id_down(current_id)); - current_id++; - } break; - - default: - log_info("Unhandled message received"); - break; + case MESSAGE_GET_ID_UPSTREAM: { + network_client_send(&msg->client, create_protocol_get_id_down(current_id)); + spawn_player(current_id); + current_id++; + log_info("Player connected to server"); + } break; + + case MESSAGE_USER_MOVED: { + move_user(window, (protocol_move*)msg->message); + } break; + + case MESSAGE_USER_LOOK: { + rotate_user(window, (protocol_user_look*)msg->message); + } break; + + default: + log_info("Unhandled message received"); + break; } + mem_free(msg->message); + mem_free(msg); array_remove_at(&messages_received_on_server, i); i--; } + + broadcast_to_clients(create_protocol_user_list()); + + if (update_timer > 0.05f) { + broadcast_to_clients(create_protocol_zombie_list()); + update_timer = 0.0f; + } + + update_timer += update_delta; } -void update_client() { +void update_client(platform_window* window) { for (int i = 0; i < messages_received_on_client.length; i++) { protocol_generic_client_message* msg = *(protocol_generic_client_message**)array_at(&messages_received_on_client, i); @@ -85,27 +176,40 @@ void update_client() { protocol_get_id_downstream* msg_id = (protocol_get_id_downstream*)msg; my_id = msg_id->id; global_state.network_state = CONNECTED; - spawn_player(my_id); - log_info("Id received, spawning player"); + printf("Received id: %d\n", my_id); + log_info("Id received"); + } break; + + case MESSAGE_USER_LIST: { + protocol_user_list* msg_players = (protocol_user_list*)msg; + memcpy(players, msg_players->players, sizeof(players)); + } break; + case MESSAGE_ZOMBIE_LIST: { + if (global_state.server) break; // zombies are simulated on server so dont overwrite data. + protocol_zombie_list* msg_zombies = (protocol_zombie_list*)msg; + memcpy(zombies, msg_zombies->zombies, sizeof(zombies)); } break; - default: log_info("Unhandled message received"); break; } + mem_free(msg); array_remove_at(&messages_received_on_client, i); i--; } + + if (!global_state.server) { + update_zombies_client(window); + } } void update_game(platform_window* window) { + update_client(window); if (global_state.server) { - update_server(); + update_server(window); } - update_client(); - if (global_state.network_state == CONNECTED) { draw_grid(window); draw_spawners(window); diff --git a/src/players.c b/src/players.c index 132a467..82804d1 100644 --- a/src/players.c +++ b/src/players.c @@ -31,12 +31,12 @@ void spawn_player(int id) { } } -player get_player_by_id(int id) { +player* get_player_by_id(u32 id) { for (int i = 0; i < max_players; i++) { if (!players[i].active) continue; - if (players[i].id == id) return players[i]; + if (players[i].id == id) return &players[i]; } - return (player){-1}; + return 0; } object check_if_player_collided_with_object(platform_window* window, player p) { @@ -70,49 +70,34 @@ int get_my_player_index() { } void take_player_input(platform_window* window) { - float speed = 0.1f; - float pad_between_player_and_obj = 0.01f; - - int my_index = get_my_player_index(); - if (my_index == -1) return; - - float old_x = players[my_index].playerx; - float old_y = players[my_index].playery; + player* p = get_player_by_id(my_id); + if (!p) return; if (keyboard_is_key_down(KEY_W)) { - float newy = players[my_index].playery - speed; - if (is_in_bounds(players[my_index].playerx, newy)) { - players[my_index].playery = newy; - object o = check_if_player_collided_with_object(window, players[my_index]); - if (o.active) players[my_index].playery = o.position.y+o.size.y - get_player_size_in_tile() + pad_between_player_and_obj; - } + network_client_send(global_state.client, create_protocol_user_moved(MOVE_UP, my_id)); } - if (keyboard_is_key_down(KEY_S)) { - float newy = players[my_index].playery + speed; - if (is_in_bounds(players[my_index].playerx, newy)) { - players[my_index].playery = newy; - object o = check_if_player_collided_with_object(window, players[my_index]); - if (o.active) players[my_index].playery = o.position.y - get_player_size_in_tile() - pad_between_player_and_obj; - } + network_client_send(global_state.client, create_protocol_user_moved(MOVE_DOWN, my_id)); } - if (keyboard_is_key_down(KEY_A)) { - float newx = players[my_index].playerx - speed; - if (is_in_bounds(newx, players[my_index].playery)) { - players[my_index].playerx = newx; - object o = check_if_player_collided_with_object(window, players[my_index]); - if (o.active) players[my_index].playerx = o.position.x+o.size.x + pad_between_player_and_obj; - } + network_client_send(global_state.client, create_protocol_user_moved(MOVE_LEFT, my_id)); } - if (keyboard_is_key_down(KEY_D)) { - float newx = players[my_index].playerx + speed; - if (is_in_bounds(newx, players[my_index].playery)) { - players[my_index].playerx = newx; - object o = check_if_player_collided_with_object(window, players[my_index]); - if (o.active) players[my_index].playerx = o.position.x-get_player_size_in_tile() - pad_between_player_and_obj; - } + network_client_send(global_state.client, create_protocol_user_moved(MOVE_RIGHT, my_id)); + } + + // Send gun position + { + float dirx = (_global_mouse.x - (window->width/2)); + float diry = (_global_mouse.y - (window->height/2)); + double length = sqrt(dirx * dirx + diry * diry); + dirx /= length; + diry /= length; + + p->gunx = p->playerx + (get_player_size_in_tile()/2) + dirx/2; + p->guny = p->playery + (get_player_size_in_tile()/2) + diry/2; + + network_client_send(global_state.client, create_protocol_user_look(my_id, p->gunx, p->guny)); } } @@ -121,11 +106,7 @@ void draw_players_at_tile(platform_window* window, int x, int y) { if (!players[i].active) continue; if ((int)players[i].playerx != x || (int)(players[i].playery+get_player_size_in_tile()) != y) continue; - int size = get_tile_width(window) / 2; - map_info info = get_map_info(window); - float height = get_height_of_tile_under_coords(window, players[i].playerx, players[i].playery); - - take_player_input(window); + if (players[i].id == my_id) take_player_input(window); players[i].sec_since_last_shot += update_delta; float bullets_per_sec = 10; @@ -142,22 +123,18 @@ void draw_players_at_tile(platform_window* window, int x, int y) { } } + int size = get_tile_width(window) / 2; + map_info info = get_map_info(window); + float height = get_height_of_tile_under_coords(window, players[i].playerx, players[i].playery); + float player_render_x = players[i].playerx*info.tile_width + (players[i].playery*info.px_incline); float player_render_y = players[i].playery*info.tile_height - (height*info.px_raised_per_h); renderer->render_rectangle(player_render_x, player_render_y, size, size, rgb(200,150,120)); - float dirx = (_global_mouse.x - (window->width/2)); - float diry = (_global_mouse.y - (window->height/2)); - double length = sqrt(dirx * dirx + diry * diry); - dirx /= length; - diry /= length; - - players[i].gunx = players[i].playerx + (get_player_size_in_tile()/2) + dirx/2; - players[i].guny = players[i].playery + (get_player_size_in_tile()/2) + diry/2; players[i].gun_height = height+0.5; float gun_render_x = players[i].gunx*info.tile_width + (players[i].guny*info.px_incline); float gun_render_y = players[i].guny*info.tile_height - (players[i].gun_height*info.px_raised_per_h); - + renderer->render_rectangle(gun_render_x, gun_render_y, size/4, size/4, rgb(20,255,20)); if (players[i].id == my_id) { diff --git a/src/protocol.c b/src/protocol.c index 256e85d..f833d3a 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -13,10 +13,42 @@ network_message create_protocol_get_id_down(u32 id) { return network_create_message(network_buffer, sizeof(protocol_get_id_downstream), MAX_NETWORK_BUFFER_SIZE); } +network_message create_protocol_user_list() { + protocol_user_list* buf = (protocol_user_list*)network_buffer; + buf->type = MESSAGE_USER_LIST; + memcpy(buf->players, players, sizeof(players)); + return network_create_message(network_buffer, sizeof(protocol_user_list), MAX_NETWORK_BUFFER_SIZE); +} + +network_message create_protocol_zombie_list() { + protocol_zombie_list* buf = (protocol_zombie_list*)network_buffer; + buf->type = MESSAGE_ZOMBIE_LIST; + memcpy(buf->zombies, zombies, sizeof(zombies)); + return network_create_message(network_buffer, sizeof(protocol_zombie_list), MAX_NETWORK_BUFFER_SIZE); +} + +network_message create_protocol_user_moved(protocol_move_type move, u32 id) { + protocol_move* buf = (protocol_move*)network_buffer; + buf->type = MESSAGE_USER_MOVED; + buf->move = move; + buf->id = id; + return network_create_message(network_buffer, sizeof(protocol_move), MAX_NETWORK_BUFFER_SIZE); +} + +network_message create_protocol_user_look(u32 id, float gunx, float guny) { + protocol_user_look* buf = (protocol_user_look*)network_buffer; + buf->type = MESSAGE_USER_LOOK; + buf->id = id; + buf->gunx = gunx; + buf->guny = guny; + return network_create_message(network_buffer, sizeof(protocol_user_look), MAX_NETWORK_BUFFER_SIZE); +} + void server_on_message_received(u8* buffer, u32 length, network_client client) { - u8* allocated_buf = mem_alloc(length + sizeof(network_client)); - memcpy(allocated_buf, &client, sizeof(network_client)); - memcpy(allocated_buf + sizeof(network_client), buffer + 4, length-4); + protocol_generic_message* allocated_buf = mem_alloc(sizeof(protocol_generic_message)); + allocated_buf->client = client; + allocated_buf->message = mem_alloc(length); + memcpy(allocated_buf->message, buffer + 4, length-4); array_push(&messages_received_on_server, (u8*)&allocated_buf); } diff --git a/src/zombies.c b/src/zombies.c index 3685355..a924443 100644 --- a/src/zombies.c +++ b/src/zombies.c @@ -45,6 +45,17 @@ void spawn_zombie(int x, int y) { } } +void update_spawners() { + for (int x = 0; x < 1; x++) { + spawner spawner = spawner_tiles[x]; + spawner_tiles[x].sec_since_last_spawn += update_delta; + if (spawner_tiles[x].sec_since_last_spawn >= 2.0f) { + spawn_zombie(spawner.position.x, spawner.position.y); + spawner_tiles[x].sec_since_last_spawn = 0; + } + } +} + void draw_spawners(platform_window* window) { map_info info = get_map_info(window); @@ -61,12 +72,6 @@ void draw_spawners(platform_window* window) { tile.tr.x, tile.tr.y, rgb(100, 150, 50)); - spawner_tiles[x].sec_since_last_spawn += update_delta; - if (spawner_tiles[x].sec_since_last_spawn >= 2.0f) { - spawn_zombie(spawner.position.x, spawner.position.y); - spawner_tiles[x].sec_since_last_spawn = 0; - } - renderer->render_line(tile.tl.x, tile.tl.y, tile.tr.x, tile.tr.y, 1, rgb(0,255,255)); // top renderer->render_line(tile.tl.x, tile.tl.y, tile.bl.x, tile.bl.y, 1, rgb(0,255,255)); // left renderer->render_line(tile.tr.x, tile.tr.y, tile.br.x, tile.br.y, 1, rgb(0,255,255)); // right @@ -97,12 +102,7 @@ static void draw_path_of_zombie(platform_window* window, zombie o) { } } -static vec2f get_direction_to_next_tile(zombie o) { - vec2f dest = (vec2f){o.position.x, o.position.y}; - if (o.path.length > 0) { - dest = *(vec2f*)array_at(&o.path, o.path.length-1); - } - +static vec2f get_direction_to_tile(zombie o, vec2f dest) { float dirx = (dest.x - o.position.x); float diry = (dest.y - o.position.y); if (dirx == 0 && diry == 0) return (vec2f){0,0}; @@ -112,30 +112,61 @@ static vec2f get_direction_to_next_tile(zombie o) { return (vec2f){dirx, diry}; } +static vec2f get_direction_to_next_tile(zombie o) { + vec2f dest = (vec2f){o.position.x, o.position.y}; + if (o.path.length > 0) { + dest = *(vec2f*)array_at(&o.path, o.path.length-1); + } + + return get_direction_to_tile(o, dest); +} + +static bool is_within_tile(zombie o, vec2f dest) { + if (fabs(o.position.x - dest.x) < 0.05f && fabs(o.position.y - dest.y) < 0.05f) { + return true; + } + return false; +} + static bool is_within_next_tile(zombie o) { if (o.path.length > 0) { vec2f dest = *(vec2f*)array_at(&o.path, o.path.length-1); - if (fabs(o.position.x - dest.x) < 0.05f && fabs(o.position.y - dest.y) < 0.05f) { - return true; - } + is_within_tile(o, dest); } - return false; } -void draw_zombies_at_tile(platform_window* window, int x, int y) { - map_info info = get_map_info(window); +void update_zombies_client(platform_window* window) { float speed = 0.05f; - for (int i = 0; i < max_zombies; i++) { zombie o = zombies[i]; if (!o.alive) continue; + if (o.next2tiles[0].x == -1 || o.next2tiles[0].y == -1) continue; // ran out of stored path. - if ((int)o.position.x != x || (int)ceil(o.position.y) != y) continue; + float height = get_height_of_tile_under_coords(window, zombies[i].position.x, zombies[i].position.y); + + vec2f dir = get_direction_to_tile(o, o.next2tiles[0]); + zombies[i].position.x += dir.x*speed; + zombies[i].position.y += dir.y*speed; + zombies[i].position.z = height; + + if (is_within_tile(zombies[i], o.next2tiles[0])) { + o.next2tiles[0] = o.next2tiles[1]; + o.next2tiles[1] = (vec2f){-1,-1}; + } + } +} + +void update_zombies_server(platform_window* window) { + float speed = 0.05f; + + for (int i = 0; i < max_zombies; i++) { + zombie o = zombies[i]; + if (!o.alive) continue; zombies[i].time_since_last_path += update_delta; if (zombies[i].time_since_last_path > 0.05f) { - player closest_player = get_closest_player_to_tile(x, y); + player closest_player = get_closest_player_to_tile((int)o.position.x, (int)o.position.y); make_pathfinding_request((vec2f){o.position.x,o.position.y}, (vec2f){closest_player.playerx, closest_player.playery + get_player_size_in_tile()}, &zombies[i].next_path, &zombies[i].request); @@ -153,24 +184,43 @@ void draw_zombies_at_tile(platform_window* window, int x, int y) { mutex_unlock(&zombies[i].request.mutex); } - vec2f dir = get_direction_to_next_tile(o); + if (is_within_next_tile(zombies[i])) { + array_remove_at(&zombies[i].path, zombies[i].path.length-1); + } + vec2f dir = get_direction_to_next_tile(o); float height = get_height_of_tile_under_coords(window, zombies[i].position.x, zombies[i].position.y); zombies[i].position.x += dir.x*speed; zombies[i].position.y += dir.y*speed; zombies[i].position.z = height; - if (is_within_next_tile(zombies[i])) { - array_remove_at(&zombies[i].path, zombies[i].path.length-1); + zombies[i].next2tiles[0] = (vec2f){-1,-1}; + zombies[i].next2tiles[1] = (vec2f){-1,-1}; + if (o.path.length > 0) { + zombies[i].next2tiles[0] = *(vec2f*)array_at(&o.path, o.path.length-1); + if (o.path.length > 1) { + zombies[i].next2tiles[1] = *(vec2f*)array_at(&o.path, o.path.length-2); + } } + } +} + +void draw_zombies_at_tile(platform_window* window, int x, int y) { + map_info info = get_map_info(window); + + for (int i = 0; i < max_zombies; i++) { + zombie o = zombies[i]; + if (!o.alive) continue; + + if ((int)o.position.x != x || (int)ceil(o.position.y) != y) continue; - box box = get_render_box_of_square(window, (vec3f){o.position.x, o.position.y, height}, o.size); + box box = get_render_box_of_square(window, (vec3f){o.position.x, o.position.y, o.position.z}, o.size); render_quad_with_outline(box.tl_b, box.tr_b, box.bl_b, box.br_b); render_quad_with_outline(box.tl_u, box.tr_u, box.bl_u, box.br_u); render_quad_with_outline(box.tl_u, box.tl_b, box.bl_u, box.bl_b); render_quad_with_outline(box.bl_u, box.br_u, box.bl_b, box.br_b); - draw_path_of_zombie(window, o); + if (global_state.server) draw_path_of_zombie(window, o); } } |
