Compare commits

..

2 Commits

Author SHA1 Message Date
249109f117 Merge remote-tracking branch 'origin' 2025-10-04 21:09:17 +01:00
d0d79d0551 feat: Added nav and start of npc stuff 2025-10-04 21:08:52 +01:00
7 changed files with 214 additions and 0 deletions

24
code/.vscode/launch.json vendored Normal file
View File

@@ -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"
}
]
}

20
code/.vscode/tasks.json vendored Normal file
View File

@@ -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"
]
}
]
}

View File

@@ -45,4 +45,14 @@
#define thread_var __thread #define thread_var __thread
#endif #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_ #endif // LD_CORE_MACROS_H_

100
code/game/impl/nav.c Normal file
View File

@@ -0,0 +1,100 @@
#include "../nav.h"
#include "../../core/types.h"
#include <stdio.h>
#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;
}

40
code/game/nav.h Normal file
View File

@@ -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

10
code/game/npc.h Normal file
View File

@@ -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_

10
code/game/world.h Normal file
View File

@@ -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_