summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/zombies.exebin1662213 -> 1679328 bytes
-rw-r--r--bullets.c19
-rw-r--r--include/bullets.h2
-rw-r--r--include/list.h27
-rw-r--r--include/map.h2
-rw-r--r--include/objects.h4
-rw-r--r--include/pathfinding.h23
-rw-r--r--include/players.h25
-rw-r--r--include/zombies.h10
-rw-r--r--list.c127
-rw-r--r--main.c10
-rw-r--r--map.c14
-rw-r--r--math_helper.c3
-rw-r--r--objects.c37
-rw-r--r--pathfinding.c308
-rw-r--r--players.c158
-rw-r--r--project-base.code-workspace6
-rw-r--r--zombies.c114
18 files changed, 778 insertions, 111 deletions
diff --git a/build/zombies.exe b/build/zombies.exe
index 072f96c..6c42ba3 100644
--- a/build/zombies.exe
+++ b/build/zombies.exe
Binary files differ
diff --git a/bullets.c b/bullets.c
index 9475729..1c8f8b0 100644
--- a/bullets.c
+++ b/bullets.c
@@ -1,10 +1,10 @@
#include "include/bullets.h"
-void shoot(platform_window* window) {
+void shoot(platform_window* window, player p) {
map_info info = get_map_info(window);
float bullet_range = 100.0f;
- float hh = get_height_of_tile_under_coords(window, playerx, playery);
+ float hh = get_height_of_tile_under_coords(window, p.playerx, p.playery);
float dirx = (_global_mouse.x - (window->width/2));
float diry = (_global_mouse.y - (window->height/2));
@@ -16,8 +16,8 @@ void shoot(platform_window* window) {
dirx += ((float)rand()/(float)(RAND_MAX/SPRAY_BOUNDS)-(SPRAY_BOUNDS/2));
diry += ((float)rand()/(float)(RAND_MAX/SPRAY_BOUNDS)-(SPRAY_BOUNDS/2));
- float bulletx = gunx;
- float bullety = guny;
+ float bulletx = p.gunx;
+ float bullety = p.guny;
float bullet_end_point_x = bulletx+dirx*bullet_range;
float bullet_end_point_y = bullety+diry*bullet_range;
@@ -25,7 +25,7 @@ void shoot(platform_window* window) {
bullet b = bullets[i];
if (b.active) continue;
- bullets[i] = (bullet){true, bulletx, bullety, hh + 0.5, bullet_end_point_x, bullet_end_point_y};
+ bullets[i] = (bullet){p.id, true, bulletx, bullety, hh + 0.5, bullet_end_point_x, bullet_end_point_y};
break;
}
}
@@ -167,13 +167,12 @@ void draw_bullets(platform_window* window) {
map_info info = get_map_info(window);
for (int i = 0; i < max_bullets; i++) {
- bullets[i].position.x = gunx;
- bullets[i].position.y = guny;
- bullets[i].position.z = gun_height;
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;
if (check_if_bullet_collided_with_ground(&b, window)) {
bullets[i].endy = b.endy;
diff --git a/include/bullets.h b/include/bullets.h
index e8ddb86..ed64333 100644
--- a/include/bullets.h
+++ b/include/bullets.h
@@ -8,6 +8,7 @@
#include "map.h"
typedef struct t_bullet {
+ int player_id;
bool active;
vec3f position;
float endx;
@@ -18,6 +19,7 @@ typedef struct t_bullet {
bullet bullets[500] = {0};
int max_bullets = 500;
+void shoot(platform_window* window, player p);
void draw_bullets(platform_window* window);
#endif \ No newline at end of file
diff --git a/include/list.h b/include/list.h
new file mode 100644
index 0000000..d4809de
--- /dev/null
+++ b/include/list.h
@@ -0,0 +1,27 @@
+
+#ifndef INCLUDE_LIST
+#define INCLUDE_LIST
+
+#include <projectbase/project_base.h>
+
+typedef struct t_list_item
+{
+ void *next;
+ void *data;
+} list_item;
+
+typedef struct t_list
+{
+ list_item *start;
+ u32 count;
+ u16 size;
+} list;
+
+void list_destroy(list* list);
+list list_create(u16 size);
+list_item *list_push(list *list, void *data);
+void* list_at(list *list, u32 index);
+void list_remove_at(list *list, u32 index);
+void list_debug_print(list *list);
+
+#endif \ No newline at end of file
diff --git a/include/map.h b/include/map.h
index 82584e9..3bc8273 100644
--- a/include/map.h
+++ b/include/map.h
@@ -49,7 +49,7 @@ int map[MAP_SIZE_Y][MAP_SIZE_X] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
- {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ {0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
diff --git a/include/objects.h b/include/objects.h
index c4bb689..b7c14b3 100644
--- a/include/objects.h
+++ b/include/objects.h
@@ -28,8 +28,8 @@ typedef struct t_box {
vec2f br_u;
} box;
-object objects[50];
-int max_objects = 50;
+int max_objects = 150;
+object objects[150];
void create_objects();
void draw_objects_at_row(platform_window* window, int row);
diff --git a/include/pathfinding.h b/include/pathfinding.h
new file mode 100644
index 0000000..2b38766
--- /dev/null
+++ b/include/pathfinding.h
@@ -0,0 +1,23 @@
+#ifndef INCLUDE_PATHFINDING
+#define INCLUDE_PATHFINDING
+
+#include <projectbase/project_base.h>
+
+#include "players.h"
+#include "objects.h"
+#include "list.h"
+
+typedef struct t_pathfinding_request
+{
+ vec2f start;
+ vec2f end;
+ array *to_fill;
+ bool cancelled;
+ bool done;
+} pathfinding_request;
+
+array global_pathfinding_queue;
+
+void make_pathfinding_request(vec2f start, vec2f end, array *to_fill, pathfinding_request *request);
+
+#endif \ No newline at end of file
diff --git a/include/players.h b/include/players.h
index 7107797..cd7560f 100644
--- a/include/players.h
+++ b/include/players.h
@@ -8,15 +8,24 @@
#include "zombies.h"
#include "math_helper.h"
-float sec_since_last_shot = 10.0f;
-float playerx = 3;
-float playery = 3;
-float gunx = 0.0f;
-float guny = 0.0f;
-float gun_height = 0.0f;
+typedef struct t_player {
+ int id;
+ bool active;
+ float sec_since_last_shot;
+ float playerx;
+ float playery;
+ float gunx;
+ float guny;
+ float gun_height;
+} player;
-void shoot(platform_window* window);
-void draw_player(platform_window* window);
+int my_id = 1;
+
+int max_players = 10;
+player players[10] = {0};
+
+player get_player_by_id(int id);
+void draw_players_at_tile(platform_window* window, int x, int y);
void draw_bullets(platform_window* window);
float get_player_size(platform_window* window);
diff --git a/include/zombies.h b/include/zombies.h
index 44b2956..a8a58fe 100644
--- a/include/zombies.h
+++ b/include/zombies.h
@@ -5,12 +5,17 @@
#include "players.h"
#include "objects.h"
+#include "pathfinding.h"
typedef struct t_zombie {
bool alive;
float health;
vec3f position;
vec3f size;
+ array path;
+ array next_path;
+ float time_since_last_path;
+ pathfinding_request request;
} zombie;
typedef struct t_spawner {
@@ -20,11 +25,10 @@ typedef struct t_spawner {
// data data that is stored on disk
spawner spawner_tiles[2] = {
- {9, 0, 0},
- {1, 8, 0},
+ {15, 5, 999},
+ {3, 8, 999},
};
-
zombie zombies[50] = {0};
int max_zombies = 50;
diff --git a/list.c b/list.c
new file mode 100644
index 0000000..35c41eb
--- /dev/null
+++ b/list.c
@@ -0,0 +1,127 @@
+/*
+* Copyright 2019 Aldrik Ramaekers
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "include/list.h"
+
+list list_create(u16 size)
+{
+ list l;
+ l.size = size;
+ l.count = 0;
+ l.start = 0;
+
+ return l;
+}
+
+void list_destroy(list* list) {
+ list_item *prev = 0;
+ list_item *current_item = list->start;
+ while(current_item)
+ {
+ prev = current_item;
+ current_item = current_item->next;
+ mem_free(prev);
+ }
+
+ list->count = 0;
+}
+
+list_item *list_push(list *list, void *data)
+{
+ list_item *item = mem_alloc(sizeof(list_item));
+ item->next = 0;
+ item->data = data;
+
+ if (list->count == 0)
+ {
+ list->start = item;
+ }
+ else
+ {
+ list_item *current_item = list->start;
+ while(current_item)
+ {
+ if (!current_item->next)
+ {
+ current_item->next = item;
+ goto done;
+ }
+ else
+ {
+ current_item = current_item->next;
+ }
+ }
+ }
+
+ done:
+ list->count++;
+ return item;
+}
+
+void* list_at(list *list, u32 index)
+{
+ list_item *current_item = list->start;
+ s32 count = 0;
+ while(current_item)
+ {
+ if (count == index)
+ return current_item->data;
+ count++;
+ current_item = current_item->next;
+ }
+ return 0;
+}
+
+void list_remove_at(list *list, u32 index)
+{
+ list_item *prev = 0;
+ list_item *current_item = list->start;
+ s32 count = 0;
+ while(current_item)
+ {
+ if (count == index)
+ {
+ if (prev)
+ prev->next = current_item->next;
+ else
+ list->start = current_item->next;
+
+ mem_free(current_item);
+ goto done;
+ }
+
+ count++;
+ prev = current_item;
+ current_item = current_item->next;
+ }
+
+ done:
+ list->count--;
+}
+
+void list_debug_print(list *list)
+{
+ list_item *current_item = list->start;
+ s32 count = 0;
+ while(current_item)
+ {
+ printf("%d %p\n", count, current_item->data);
+
+ count++;
+ current_item = current_item->next;
+ }
+} \ No newline at end of file
diff --git a/main.c b/main.c
index ea17371..ccdfc91 100644
--- a/main.c
+++ b/main.c
@@ -6,6 +6,8 @@
#include "include/zombies.h"
#include "include/math_helper.h"
#include "include/bullets.h"
+#include "include/pathfinding.h"
+#include "include/list.h"
#include "map.c"
#include "players.c"
@@ -13,6 +15,8 @@
#include "zombies.c"
#include "bullets.c"
#include "math_helper.c"
+#include "pathfinding.c"
+#include "list.c"
#define CONFIG_DIRECTORY "zombieshooter"
@@ -43,12 +47,18 @@ int main(int argc, char **argv)
load_map_from_data();
create_objects();
+ pathfinding_init();
+
+ thread t = thread_start(pathfinding_thread, 0);
+ thread_detach(&t);
+
while(platform_keep_running(window)) {
platform_handle_events();
}
settings_write_to_file();
platform_destroy();
+ pathfinding_destroy();
memory_print_leaks();
diff --git a/map.c b/map.c
index e6f7fd5..15a7c70 100644
--- a/map.c
+++ b/map.c
@@ -26,19 +26,19 @@ static int get_height_of_tile_tl(int current_height, int x, int y) {
static int get_height_of_tile_br(int current_height, int x, int y) {
int highest_point = current_height;
- if (x < 9) {
+ if (x < MAP_SIZE_X-1) {
int tile_right = map[y][x+1];
if (tile_right > highest_point) {
highest_point = tile_right;
}
}
- if (y < 9 && x < 9) {
+ if (y < MAP_SIZE_Y-1 && x < MAP_SIZE_X-1) {
int tile_bottom_right = map[y+1][x+1];
if (tile_bottom_right > highest_point) {
highest_point = tile_bottom_right;
}
}
- if (y < 9) {
+ if (y < MAP_SIZE_Y-1) {
int tile_bottom = map[y+1][x];
if (tile_bottom > highest_point) {
highest_point = tile_bottom;
@@ -55,13 +55,13 @@ static int get_height_of_tile_bl(int current_height, int x, int y) {
highest_point = tile_left;
}
}
- if (y < 9 && x > 0) {
+ if (y < MAP_SIZE_Y-1 && x > 0) {
int tile_bottom_left = map[y+1][x-1];
if (tile_bottom_left > highest_point) {
highest_point = tile_bottom_left;
}
}
- if (y < 9) {
+ if (y < MAP_SIZE_Y-1) {
int tile_bottom = map[y+1][x];
if (tile_bottom > highest_point) {
highest_point = tile_bottom;
@@ -78,13 +78,13 @@ static int get_height_of_tile_tr(int current_height, int x, int y) {
highest_point = tile_above;
}
}
- if (y > 0 && x < 9) {
+ if (y > 0 && x < MAP_SIZE_X-1) {
int tile_above_right = map[y-1][x+1];
if (tile_above_right > highest_point) {
highest_point = tile_above_right;
}
}
- if (x < 9) {
+ if (x < MAP_SIZE_X-1) {
int tile_right = map[y][x+1];
if (tile_right > highest_point) {
highest_point = tile_right;
diff --git a/math_helper.c b/math_helper.c
index 782599d..648fbd2 100644
--- a/math_helper.c
+++ b/math_helper.c
@@ -49,7 +49,8 @@ bool lines_intersect(vec2f p1, vec2f q1, vec2f p2, vec2f q2)
if (o1 != o2 && o3 != o4) {
vec2f bdir = get_dir_of_line(p1, q1);
vec2f pdir = get_dir_of_line(p1, p2);
- if ((neg2(bdir.x, pdir.x) || pos2(bdir.x, pdir.x)) && (neg2(bdir.y, pdir.y) || pos2(bdir.y, pdir.y))) return true; // going down
+ if (((p1.x <= p2.x && q1.x >= p2.x) || (p1.x >= p2.x && q1.x <= p2.x)) || ((p1.y <= p2.y && q1.y >= p2.y) || (p1.y >= p2.y && q1.y <= p2.y)))
+ if ((neg2(bdir.x, pdir.x) || pos2(bdir.x, pdir.x)) && (neg2(bdir.y, pdir.y) || pos2(bdir.y, pdir.y))) return true;
}
// Special Cases
diff --git a/objects.c b/objects.c
index 39e0f30..72af5a5 100644
--- a/objects.c
+++ b/objects.c
@@ -30,17 +30,11 @@ object get_object_at_tile(int x, int y) {
void draw_objects_at_row(platform_window* window, int row) {
map_info info = get_map_info(window);
- bool did_player_draw = false;
- int x_of_player = playerx;
- int y_of_player = playery+get_player_size_in_tile();
-
for (int i = MAP_SIZE_X-1; i >= 0; i--) {
object o = get_object_at_tile(i, row);
- if (row == y_of_player && x_of_player == i) {
- OBJECT_RENDER_DEPTH(o.h);
- draw_player(window);
- }
+ OBJECT_RENDER_DEPTH(o.h);
+ draw_players_at_tile(window, i, row);
draw_zombies_at_tile(window, i, row);
@@ -71,12 +65,27 @@ void create_box(float x, float y, float h) {
void create_objects() {
// rechts naar links op map.
- create_box(4, 0, 0);
- create_box(1, 0, 0);
- create_box(0, 0, 0);
- create_box(0, 1, 0);
- create_box(3, 5, 0);
+ for (int i = MAP_SIZE_X-1; i >= 0; i--) {
+ create_box(i, 0, 0);
+ create_box(i, MAP_SIZE_Y-1, 0);
+ }
+
+ for (int i = MAP_SIZE_Y-1; i >= 0; i--) {
+ create_box(0, i, 0);
+ create_box(MAP_SIZE_Y-1, i, 0);
+ }
+
+ create_box(16, 8, 0);
+ create_box(14, 8, 0);
+ create_box(11, 8, 0);
+ create_box(10, 8, 0);
- spawn_zombie(2, 7);
+ create_box(15, 10, 0);
+ create_box(14, 10, 0);
+ create_box(13, 10, 0);
+ create_box(11, 10, 0);
+
+ spawn_player(my_id);
+ spawn_player(my_id+1);
} \ No newline at end of file
diff --git a/pathfinding.c b/pathfinding.c
new file mode 100644
index 0000000..b69d420
--- /dev/null
+++ b/pathfinding.c
@@ -0,0 +1,308 @@
+#include "include/pathfinding.h"
+
+static float distance_between(vec2f v1, vec2f v2)
+{
+ return ((v1.x-v2.x)*(v1.x-v2.x)+(v1.y-v2.y)*(v1.y-v2.y));
+}
+
+bool can_walk_at(float x, float y)
+{
+ for (int i = 0; i < max_objects; i++) {
+ object o = objects[i];
+ if (!o.active) continue;
+ if (x >= o.position.x && x < o.position.x + o.size.x && y >= o.position.y && y < o.position.y + o.size.y) return false;
+ }
+ return true;
+}
+
+bool find_path_to(vec2f start_pos, vec2f end_pos, array *to_fill, pathfinding_request* request)
+{
+ struct path_node {
+ struct path_node *parent;
+ vec2f position;
+ s32 g;
+ s32 h;
+ s32 f;
+ };
+
+ list open_array = list_create(sizeof(struct path_node));
+ list closed_array = list_create(sizeof(struct path_node));
+
+ struct path_node *start_node = mem_alloc(sizeof(struct path_node));
+ start_node->g = 0;
+ start_node->h = 0;
+ start_node->f = 0;
+ start_node->parent = 0;
+ start_node->position = start_pos;
+
+ list_push(&open_array, (uint8_t*)start_node);
+
+ struct path_node *current_node = 0;
+ while(open_array.count > 0 && !request->cancelled)
+ {
+ // Get the current node
+ current_node = list_at(&open_array, 0);
+ s32 current_index = 0;
+
+ for (s32 i = 0; i < open_array.count; i++)
+ {
+ struct path_node *item = list_at(&open_array, i);
+ if (item->f < current_node->f)
+ {
+ current_node = item;
+ current_index = i;
+ }
+ }
+
+ //Pop current off open array, add to closed array
+ list_push(&closed_array, (uint8_t*)current_node);
+
+ if (closed_array.count > 1000) return false;
+ if (open_array.count > 1000) return false;
+
+ // Found the goal
+ if (distance_between(current_node->position, end_pos) <= 0)
+ {
+ if (to_fill)
+ to_fill->length = 0;
+ struct path_node *current = current_node;
+
+ while(current != 0)
+ {
+ if (to_fill)
+ {
+ vec2f v;
+ v.x = current->position.x + 0.5;
+ v.y = current->position.y + 0.5;
+ array_push(to_fill, (uint8_t*)&v);
+ }
+
+ struct path_node *prev = current;
+ current = current->parent;
+ mem_free(prev);
+ }
+
+ if (to_fill) {
+ array_remove_at(to_fill, to_fill->length-1);
+ request->done = true;
+ }
+
+ list_destroy(&open_array);
+ list_destroy(&closed_array);
+
+ return true;
+ }
+
+ vec2 adjecent[8] = { {0, -1}, {0, 1}, {-1, 0}, {1, 0}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1} };
+
+ list children = list_create(sizeof(struct path_node));
+
+ // Generate children
+ for (s32 i = 0; i < 8; i++)
+ {
+ //Get node position
+ vec2f node_position;
+ node_position.x = current_node->position.x + adjecent[i].x;
+ node_position.y = current_node->position.y + adjecent[i].y;
+
+ //Make sure within range
+ if (!is_in_bounds(node_position.x, node_position.y) || !can_walk_at(node_position.x, node_position.y)) continue;
+
+ // if diagonal move, check if not cutting off building
+ if (i >= 4) {
+ if (i == 4) // top left
+ {
+ if (!can_walk_at(node_position.x+1, node_position.y)) continue;
+ if (!can_walk_at(node_position.x, node_position.y+1)) continue;
+ }
+ if (i == 5) // down left
+ {
+ if (!can_walk_at(node_position.x+1, node_position.y)) continue;
+ if (!can_walk_at(node_position.x, node_position.y-1)) continue;
+ }
+ if (i == 6) // top right
+ {
+ if (!can_walk_at(node_position.x-1, node_position.y)) continue;
+ if (!can_walk_at(node_position.x, node_position.y+1)) continue;
+ }
+ if (i == 7) // down right
+ {
+ if (!can_walk_at(node_position.x-1, node_position.y)) continue;
+ if (!can_walk_at(node_position.x, node_position.y-1)) continue;
+ }
+ }
+
+ // Create new node
+ struct path_node *new_node = mem_alloc(sizeof(struct path_node));
+ new_node->g = 0;
+ new_node->h = 0;
+ new_node->f = 0;
+ new_node->parent = current_node;
+ new_node->position = node_position;
+
+ if (node_position.x == current_node->position.x &&
+ node_position.y == current_node->position.y)
+ continue;
+
+ // Child is on the closed array
+ for (s32 c = 0; c < closed_array.count; c++)
+ {
+ struct path_node *closed_child = list_at(&closed_array, c);
+
+ if (closed_child->position.x == new_node->position.x &&
+ closed_child->position.y == new_node->position.y)
+ {
+ goto skip_adjecent;
+ }
+ }
+
+ list_push(&children,(uint8_t*)new_node);
+
+ skip_adjecent:;
+ }
+
+ // Loop through children
+ for (s32 i = 0; i < children.count; i++)
+ {
+ struct path_node *child = list_at(&children, i);
+
+ // Child is on the closed array
+ for (s32 c = 0; c < closed_array.count; c++)
+ {
+ struct path_node *closed_child = list_at(&closed_array, c);
+
+ if (closed_child->position.x == child->position.x &&
+ closed_child->position.y == child->position.y)
+ {
+ goto skip_child;
+ }
+ }
+
+ // Create the f, g, and h values
+ child->g = current_node->g + 1;
+ child->h = distance_between(child->position, end_pos);
+ child->f = child->g + child->h;
+
+ // Child is already in the open array
+ for (s32 c = 0; c < open_array.count; c++)
+ {
+ struct path_node *open_child = list_at(&open_array, c);
+
+ if ((open_child->position.x == child->position.x &&
+ open_child->position.y == child->position.y) &&
+ child->g >= open_child->g)
+ {
+ goto skip_child;
+ }
+ }
+
+ // Add the child to the open array
+ list_push(&open_array, (uint8_t*)child);
+
+ skip_child:;
+ }
+
+ list_remove_at(&open_array, current_index);
+ }
+
+ return false;
+}
+
+vec2f get_open_tile_next_to_target(float x, float y)
+{
+ vec2f adjecent[8] = { {0, -1}, {0, 1}, {-1, 0}, {1, 0}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1} };
+
+ vec2f v_s;
+ v_s.x = x;
+ v_s.y = y;
+
+ s32 closest_index = -1;
+ s32 closest_dist = 999999;
+ vec2f v;
+ for (s32 i = 0; i < 8; i++)
+ {
+ if (can_walk_at(x + adjecent[i].x, y + adjecent[i].y))
+ {
+ vec2f vv;
+ vv.x = x + adjecent[i].x;
+ vv.y = y + adjecent[i].y;
+
+ s32 dist = distance_between(v_s, vv);
+ if (dist < closest_dist)
+ {
+ v = vv;
+ closest_dist = dist;
+ closest_index = i;
+ }
+ }
+ }
+
+ if (closest_index != -1)
+ {
+ return v;
+ }
+
+ v.x = -1;
+ v.y = -1;
+ return v;
+}
+
+void pathfinding_init()
+{
+ global_pathfinding_queue = array_create(sizeof(pathfinding_request));
+ array_reserve(&global_pathfinding_queue, 1000);
+}
+
+void pathfinding_destroy()
+{
+ array_destroy(&global_pathfinding_queue);
+}
+
+void* pathfinding_thread(void *args)
+{
+ while(1)
+ {
+ pathfinding_request request;
+
+ mutex_lock(&global_pathfinding_queue.mutex);
+ if (global_pathfinding_queue.length)
+ {
+ pathfinding_request* request = *(pathfinding_request**)array_at(&global_pathfinding_queue, 0);
+ array_remove_at(&global_pathfinding_queue, 0);
+ mutex_unlock(&global_pathfinding_queue.mutex);
+
+ request->cancelled = false;
+ find_path_to(request->start, request->end, request->to_fill, request);
+
+ continue;
+ }
+ else
+ {
+ mutex_unlock(&global_pathfinding_queue.mutex);
+ continue;
+ }
+
+ thread_sleep(100);
+ }
+
+ return 0;
+}
+
+void make_pathfinding_request(vec2f start, vec2f end, array *to_fill, pathfinding_request *request)
+{
+ mutex_lock(&global_pathfinding_queue.mutex);
+
+ request->cancelled = true;
+
+ start.x = (int)start.x;
+ start.y = (int)start.y;
+ end.x = (int)end.x;
+ end.y = (int)end.y;
+
+ request->start = start;
+ request->end = end;
+ request->to_fill = to_fill;
+ request->done = false;
+ array_push(&global_pathfinding_queue, (uint8_t*)&request);
+ mutex_unlock(&global_pathfinding_queue.mutex);
+} \ No newline at end of file
diff --git a/players.c b/players.c
index 40b2de3..f6719b5 100644
--- a/players.c
+++ b/players.c
@@ -16,7 +16,30 @@ float get_player_size(platform_window* window) {
int player_size = get_tile_width(window) * get_player_size_in_tile();
}
-object check_if_player_collided_with_object(platform_window* window) {
+void spawn_player(int id) {
+ for (int i = 0; i < max_players; i++) {
+ if (players[i].active) continue;
+ players[i].active = true;
+ players[i].sec_since_last_shot = 10.0f;
+ players[i].playerx = 3;
+ players[i].playery = 3;
+ players[i].gunx = 0.0f;
+ players[i].guny = 0.0f;
+ players[i].gun_height = 0.0f;
+ players[i].id = id;
+ return;
+ }
+}
+
+player get_player_by_id(int id) {
+ for (int i = 0; i < max_players; i++) {
+ if (!players[i].active) continue;
+ if (players[i].id == id) return players[i];
+ }
+ return (player){-1};
+}
+
+object check_if_player_collided_with_object(platform_window* window, player p) {
map_info info = get_map_info(window);
float player_size = get_player_size(window);
@@ -25,9 +48,9 @@ object check_if_player_collided_with_object(platform_window* window) {
if (!o.active) continue;
box box = get_box_of_object(window, o);
- float x_to_check = playerx;
+ float x_to_check = p.playerx;
float player_size_in_tile_px = player_size / (float)info.tile_width;
- float y_to_check = playery + player_size_in_tile_px;
+ float y_to_check = p.playery + player_size_in_tile_px;
if (x_to_check+player_size_in_tile_px >= o.position.x && x_to_check <= o.position.x+o.size.x
&& y_to_check >= o.position.y && y_to_check <= o.position.y+o.size.y) {
@@ -38,85 +61,108 @@ object check_if_player_collided_with_object(platform_window* window) {
return (object){0};
}
+int get_my_player_index() {
+ for (int i = 0; i < max_players; i++) {
+ if (!players[i].active) continue;
+ if (players[i].id == my_id) return i;
+ }
+ return -1;
+}
+
void take_player_input(platform_window* window) {
float speed = 0.1f;
float pad_between_player_and_obj = 0.01f;
- float old_x = playerx;
- float old_y = playery;
+ 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;
if (keyboard_is_key_down(KEY_W)) {
- float newy = playery - speed;
- if (is_in_bounds(playerx, newy)) {
- playery = newy;
- object o = check_if_player_collided_with_object(window);
- if (o.active) playery = o.position.y+o.size.y - get_player_size_in_tile() + pad_between_player_and_obj;
+ 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;
}
}
if (keyboard_is_key_down(KEY_S)) {
- float newy = playery + speed;
- if (is_in_bounds(playerx, newy)) {
- playery = newy;
- object o = check_if_player_collided_with_object(window);
- if (o.active) playery = o.position.y - get_player_size_in_tile() - pad_between_player_and_obj;
+ 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;
}
}
if (keyboard_is_key_down(KEY_A)) {
- float newx = playerx - speed;
- if (is_in_bounds(newx, playery)) {
- playerx = newx;
- object o = check_if_player_collided_with_object(window);
- if (o.active) playerx = o.position.x+o.size.x + pad_between_player_and_obj;
+ 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;
}
}
if (keyboard_is_key_down(KEY_D)) {
- float newx = playerx + speed;
- if (is_in_bounds(newx, playery)) {
- playerx = newx;
- object o = check_if_player_collided_with_object(window);
- if (o.active) playerx = o.position.x-get_player_size_in_tile() - pad_between_player_and_obj;
+ 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;
}
}
}
-void draw_player(platform_window* window) {
- int size = get_tile_width(window) / 2;
- map_info info = get_map_info(window);
- float height = get_height_of_tile_under_coords(window, playerx, playery);
-
- take_player_input(window);
-
- sec_since_last_shot += update_delta;
- float bullets_per_sec = 10;
- float time_between_bullets = 1.0f/bullets_per_sec;
- if (is_left_down()) {
- if (sec_since_last_shot > time_between_bullets) {
- for (int i = 0; i < 3; i++) shoot(window);
- sec_since_last_shot = 0.0f;
+void draw_players_at_tile(platform_window* window, int x, int y) {
+ for (int i = 0; i < max_players; i++) {
+ 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);
+
+ players[i].sec_since_last_shot += update_delta;
+ float bullets_per_sec = 10;
+ float time_between_bullets = 1.0f/bullets_per_sec;
+ if (is_left_down()) {
+ if (players[i].sec_since_last_shot > time_between_bullets) {
+ int ix = get_my_player_index();
+ if (ix != -1) {
+ for (int i = 0; i < 3; i++) {
+ shoot(window, players[ix]);
+ players[i].sec_since_last_shot = 0.0f;
+ }
+ }
+ }
}
- }
- float player_render_x = playerx*info.tile_width + (playery*info.px_incline);
- float player_render_y = 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 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;
+ 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;
- gunx = playerx + (get_player_size_in_tile()/2) + dirx/2;
- guny = playery + (get_player_size_in_tile()/2) + diry/2;
- gun_height = height+0.5;
- float gun_render_x = gunx*info.tile_width + (guny*info.px_incline);
- float gun_render_y = guny*info.tile_height - (gun_height*info.px_raised_per_h);
+ 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));
+ renderer->render_rectangle(gun_render_x, gun_render_y, size/4, size/4, rgb(20,255,20));
- _global_camera.x = -(window->width / 2) + player_render_x;
- _global_camera.y = -(window->height / 2) + player_render_y;
+ if (players[i].id == my_id) {
+ _global_camera.x = -(window->width / 2) + player_render_x;
+ _global_camera.y = -(window->height / 2) + player_render_y;
+ }
+ }
}
diff --git a/project-base.code-workspace b/project-base.code-workspace
index 45b030e..be07839 100644
--- a/project-base.code-workspace
+++ b/project-base.code-workspace
@@ -53,7 +53,11 @@
"map.h": "c",
"zombies.h": "c",
"math.h": "c",
- "math_helper.h": "c"
+ "math_helper.h": "c",
+ "xiosbase": "c",
+ "pathfinding.h": "c",
+ "unordered_map": "c",
+ "players.h": "c"
}
}
} \ No newline at end of file
diff --git a/zombies.c b/zombies.c
index 80a34ad..85dea2d 100644
--- a/zombies.c
+++ b/zombies.c
@@ -1,14 +1,44 @@
#include "include/zombies.h"
+static player get_closest_player_to_tile(int x, int y) {
+ float best_length = 99999;
+ int best_index = -1;
+
+ for (int i = 0; i < max_players; i++) {
+ if (!players[i].active) continue;
+ float dirx = (players[i].playerx - x);
+ float diry = (players[i].playery - y);
+ double length = sqrt(dirx * dirx + diry * diry);
+
+ if (length < best_length) {
+ best_length = length;
+ best_index = i;
+ }
+ }
+ if (best_index == -1) {
+ return (player){-1};
+ }
+ else {
+ return players[best_index];
+ }
+}
+
void spawn_zombie(int x, int y) {
for (int i = 0; i < max_zombies; i++) {
zombie o = zombies[i];
if (o.alive) continue;
+ zombies[i].path = array_create(sizeof(vec2f));
+ zombies[i].next_path = array_create(sizeof(vec2f));
zombies[i].alive = true;
zombies[i].health = 100.0f;
zombies[i].position = (vec3f){x,y, 0};
zombies[i].size = (vec3f){0.4, 0.4, 1};
+ zombies[i].time_since_last_path = 0.0f;
+
+ player closest_player = get_closest_player_to_tile(x, y);
+
+ make_pathfinding_request((vec2f){x,y}, (vec2f){closest_player.playerx, closest_player.playery}, &zombies[i].path, &zombies[i].request);
break;
}
}
@@ -30,7 +60,7 @@ void draw_spawners(platform_window* window) {
rgb(100, 150, 50));
spawner_tiles[x].sec_since_last_spawn += update_delta;
- if (spawner_tiles[x].sec_since_last_spawn >= 1.0f) {
+ if (spawner_tiles[x].sec_since_last_spawn >= 3.0f) {
spawn_zombie(spawner.position.x, spawner.position.y);
spawner_tiles[x].sec_since_last_spawn = 0;
}
@@ -42,6 +72,55 @@ void draw_spawners(platform_window* window) {
}
}
+static void draw_path_of_zombie(platform_window* window, zombie o) {
+ map_info info = get_map_info(window);
+ vec2f prev_pos = (vec2f){o.position.x, o.position.y};
+
+ for (int i = 0; i < o.path.length; i++) {
+ vec2f* pos = array_at(&o.path, o.path.length-1-i);
+
+ int render_x = (info.tile_width * prev_pos.x) + (info.px_incline * prev_pos.y);
+ int render_y = info.tile_height * prev_pos.y;
+
+ int render_x2 = (info.tile_width * pos->x) + (info.px_incline * pos->y);
+ int render_y2 = info.tile_height * pos->y;
+
+ prev_pos = *pos;
+ if (i == 0) {
+ renderer->render_line(render_x, render_y, render_x2, render_y2, 2, rgb(0,255,255));
+ continue;
+ }
+
+ renderer->render_line(render_x, render_y, render_x2, render_y2, 2, rgb(0,0,255));
+ }
+}
+
+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);
+ }
+
+ float dirx = (dest.x - o.position.x);
+ float diry = (dest.y - o.position.y);
+ if (dirx == 0 && diry == 0) return (vec2f){0,0};
+ double length = sqrt(dirx * dirx + diry * diry);
+ dirx /= length;
+ diry /= length;
+ return (vec2f){dirx, diry};
+}
+
+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;
+ }
+ }
+
+ return false;
+}
+
void draw_zombies_at_tile(platform_window* window, int x, int y) {
map_info info = get_map_info(window);
float speed = 0.05f;
@@ -49,24 +128,43 @@ void draw_zombies_at_tile(platform_window* window, int x, int y) {
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;
- float dirx = (playerx - o.position.x);
- float diry = (playery - o.position.y);
- double length = sqrt(dirx * dirx + diry * diry);
- dirx /= length;
- diry /= length;
+ zombies[i].time_since_last_path += update_delta;
+ if (zombies[i].time_since_last_path > 0.1f) {
+ player closest_player = get_closest_player_to_tile(x, 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);
+ zombies[i].time_since_last_path = 0;
+ }
+ else {
+ if (zombies[i].request.done) {
+ zombies[i].path = zombies[i].next_path;
+ array_clear(&zombies[i].next_path);
+ zombies[i].request.done = false;
+ }
+ }
+
+ 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 += dirx*speed;
- zombies[i].position.y += diry*speed;
+ 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);
+ }
+
box box = get_render_box_of_square(window, (vec3f){o.position.x, o.position.y, height}, 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);
}
}