summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAldrik Ramaekers <aldrik@amftech.nl>2022-12-12 18:06:53 +0100
committerAldrik Ramaekers <aldrik@amftech.nl>2022-12-12 18:06:53 +0100
commit9528c0c69dba57117f38f84f576af2c81a3b435b (patch)
tree14f3b21a19f3733e05d64e1fc4113af52516a441 /src
parent10ae402862df4337772fe8e35f68ee8ab5bfc224 (diff)
multiplayer
Diffstat (limited to 'src')
-rw-r--r--src/bullets.c8
-rw-r--r--src/game.c140
-rw-r--r--src/players.c81
-rw-r--r--src/protocol.c38
-rw-r--r--src/zombies.c102
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;
diff --git a/src/game.c b/src/game.c
index 55d64a4..d3ec30b 100644
--- a/src/game.c
+++ b/src/game.c
@@ -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);
}
}