Compare commits
2 Commits
a6266a336b
...
249109f117
| Author | SHA1 | Date | |
|---|---|---|---|
|
249109f117
|
|||
|
d0d79d0551
|
24
code/.vscode/launch.json
vendored
Normal file
24
code/.vscode/launch.json
vendored
Normal 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
20
code/.vscode/tasks.json
vendored
Normal 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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -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
100
code/game/impl/nav.c
Normal 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
40
code/game/nav.h
Normal 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
10
code/game/npc.h
Normal 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
10
code/game/world.h
Normal 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_
|
||||||
Reference in New Issue
Block a user