diff --git a/code/.vscode/launch.json b/code/.vscode/launch.json new file mode 100644 index 0000000..407f136 --- /dev/null +++ b/code/.vscode/launch.json @@ -0,0 +1,24 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug 'main.c' Project", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/../build/ldebug", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "Build" + } + ] +} diff --git a/code/.vscode/tasks.json b/code/.vscode/tasks.json new file mode 100644 index 0000000..b17da5a --- /dev/null +++ b/code/.vscode/tasks.json @@ -0,0 +1,20 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Build", + "type": "shell", + "command": "/home/matt/Repos/ld58/linux", + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "reveal": "never" + }, + "problemMatcher": [ + "$gcc" + ] + } + ] +} diff --git a/code/core/macros.h b/code/core/macros.h index f2d89ff..fed60b8 100644 --- a/code/core/macros.h +++ b/code/core/macros.h @@ -45,4 +45,14 @@ #define thread_var __thread #endif +#define S(x) Str8_Wrap(sizeof(x) - sizeof(*(x)), (U8 *) (x)) +Str8 Str8_Wrap(S64 count, U8 *data) { + Str8 result; + result.data = data; + result.count = count; + + return result; +} +#define Sv(x) (int) (x).count, (x).data + #endif // LD_CORE_MACROS_H_ diff --git a/code/game/impl/nav.c b/code/game/impl/nav.c new file mode 100644 index 0000000..090eb09 --- /dev/null +++ b/code/game/impl/nav.c @@ -0,0 +1,100 @@ +#include "../nav.h" +#include "../../core/types.h" +#include + +#define MAX_UNFINISHED 128 + +typedef struct navSearchNodeState navSearchNodeState; +struct navSearchNodeState{ + bool visited; + U64 distance; + U32 shortest; + bool addedToUnvisited; +}; + +typedef struct navSearchState navSearchState; +struct navSearchState{ + navSearchNodeState nodeStates[NAV_MAX_NODES]; +}; + +navSearchState initState(U32 start, U32 meshSize) { + navSearchState state = {}; + for(int i = 0; i < meshSize; i++) { + state.nodeStates[i].visited = false; + state.nodeStates[i].addedToUnvisited = false; + // underflow to the max :) + state.nodeStates[i].distance = -1; + state.nodeStates[i].shortest = 0; + } + state.nodeStates[start].distance = 0; + return state; +} + +U32 getLowestState(U32 unfinishedIndexes[128], U32 unfinishedCount, navSearchState state, U32 *offset) { + U32 lowest = -1; + U32 lowestI = -1; + bool startFound = false; + for(int i = *offset; i < unfinishedCount; i++) { + navSearchNodeState checkNode = state.nodeStates[unfinishedIndexes[i]]; + if(checkNode.visited) { + if(!startFound) { + *offset = i; + } + continue; + } + startFound = true; + if (lowest > checkNode.distance) { + lowest = checkNode.distance; + lowestI = unfinishedIndexes[i]; + } + } + return lowestI; +} + +// Generate a path to follow between the start and end node. +NavPath Nav_Path(NavMesh mesh, U32 start, U32 end) { + navSearchState state = initState(start, mesh.nodeCount); + U32 unfinishedCount = 1; + U32 unfinishedIndexes[NAV_MAX_NODES] = {start}; + // I don't want to spend time removing items from + // the unfinished nodes, so when checking for a lowest + // if I find the first N items have been checked, I'll mark + // an offset to skip the first N items. + U32 unfinishedOffset = 0; + U32 lowestNodeIndex = start; + bool found = false; + while(!found) { + for(int connectionI = 0 ; connectionI < mesh.nodes[lowestNodeIndex].connectionCount; connectionI++) { + NavConnection connection = mesh.nodes[lowestNodeIndex].connections[connectionI]; + navSearchNodeState *testNode = &state.nodeStates[connection.NodeIndex]; + if(testNode->visited) {continue;} + U32 distance = state.nodeStates[lowestNodeIndex].distance + connection.Cost; + distance += mesh.nodes[end].pos.x - mesh.nodes[connection.NodeIndex].pos.x; + distance += mesh.nodes[end].pos.y - mesh.nodes[connection.NodeIndex].pos.y; + if(testNode->distance > distance) { + testNode->distance = distance; + testNode->shortest = lowestNodeIndex; + } + if(!testNode->addedToUnvisited) { + unfinishedIndexes[unfinishedCount] = connection.NodeIndex; + unfinishedCount++; + testNode->addedToUnvisited = true; + } + } + state.nodeStates[lowestNodeIndex].visited = true; + lowestNodeIndex = getLowestState(unfinishedIndexes, unfinishedCount, state, &unfinishedOffset); + if(lowestNodeIndex == end) { + found = true; + } + } + NavPath res_path = {0}; + U32 index = end; + while(index!=start) { + res_path.indexes[res_path.nodeCount] = index; + res_path.nodeCount++; + index = state.nodeStates[index].shortest; + } + res_path.indexes[res_path.nodeCount] = start; + res_path.nodeCount++; + return res_path; +} diff --git a/code/game/nav.h b/code/game/nav.h new file mode 100644 index 0000000..5820cb6 --- /dev/null +++ b/code/game/nav.h @@ -0,0 +1,40 @@ +#if !defined(LD_GAME_NAV_H_) +#define LD_GAME_NAV_H_ + +#include "../core/types.h" +#include "../core/macros.h" + +#define NAV_MAX_PATH 1024 +#define NAV_MAX_CONNECTIONS 8 +#define NAV_MAX_NODES 4096 + +typedef struct NavNode NavNode; + +typedef struct NavConnection NavConnection; +struct NavConnection{ + F32 Cost; + U32 NodeIndex; +}; + +struct NavNode { + V2f pos; + U8 connectionCount; + NavConnection connections[NAV_MAX_CONNECTIONS]; +}; + +typedef struct NavPath NavPath; +struct NavPath { + U32 nodeCount; + U32 indexes[NAV_MAX_PATH]; +}; + +typedef struct NavMesh NavMesh; +struct NavMesh{ + U32 nodeCount; + NavNode nodes[NAV_MAX_NODES]; +}; + + +function NavPath Nav_Path(NavMesh mesh, U32 start, U32 end); + +#endif diff --git a/code/game/npc.h b/code/game/npc.h new file mode 100644 index 0000000..a50868a --- /dev/null +++ b/code/game/npc.h @@ -0,0 +1,10 @@ +#if !defined(LD_GAME_NPC_H_) +#define LD_GAME_NPC_H_ +#include "aabb.h" + +typedef struct NPC NPC; +struct NPC { + AABB collision; +}; + +#endif // LD_GAME_NPC_H_ diff --git a/code/game/world.h b/code/game/world.h new file mode 100644 index 0000000..cb74ded --- /dev/null +++ b/code/game/world.h @@ -0,0 +1,10 @@ +#if !defined(LD_GAME_WORLD_H_) +#define LD_GAME_WORLD_H_ + +typedef struct World World; +struct World { + NPC[128] npcs; + u32 npcCount; +}; + +#endif // LD_GAME_WORLD_H_