Initial work on physics

This commit is contained in:
Edgaru089 2024-02-29 16:17:55 +08:00
parent 8e6b6cec9b
commit e8f0b0c63a
9 changed files with 179 additions and 11 deletions

86
Component_Physics.c Normal file
View File

@ -0,0 +1,86 @@
#include "Component_Physics.h"
#include "Entity.h"
#include "Types.h"
#include "util/tree.h"
#include "util/vector.h"
#include "util/assert.h"
#include <stdlib.h>
#include <string.h>
double physics_Gravity = 5.0;
System_Physics *physics_NewSystem() {
System_Physics *sys = malloc(sizeof(System_Physics));
sys->pos = tree_Create(sizeof(uintptr_t));
sys->hit = tree_Create(sizeof(uintptr_t));
sys->flaggedDelete = vector_Create(sizeof(uintptr_t));
return sys;
}
void physics_DeleteSystem(System_Physics *sys) {
tree_Destroy(sys->pos);
tree_Destroy(sys->hit);
vector_Destroy(sys->flaggedDelete);
}
void physics_AddEntity(System_Physics *sys, Entity *e) {
if (e->position)
memcpy(tree_Insert(sys->pos, e->id, NULL), &e->position, sizeof(uintptr_t));
if (e->hitbox) {
ASSERT(!e->hitbox->fixed && !e->position && "Entity has non-Fixed Hitbox but no position");
memcpy(tree_Insert(sys->hit, e->id, NULL), &e->hitbox, sizeof(uintptr_t));
}
}
void physics_DeleteEntity(System_Physics *sys, uintptr_t id) {
vector_Push(sys->flaggedDelete, &id);
}
inline void _physics_AdvanceEntity(Entity *e, Duration deltaTime) {
if (!e->position)
return;
// Short path
if (!e->hitbox || e->hitbox->fixed) {
e->position->position =
vec2_Add(
e->position->position,
vec2_Scale(
e->position->velocity,
duration_Seconds(deltaTime)));
return;
}
// Long path
}
void physics_Advance(System_Physics *sys, Duration deltaTime) {
// Delete flagged entities
while (vector_Size(sys->flaggedDelete)) {
uintptr_t id;
vector_Pop(sys->flaggedDelete, &id);
tree_Node *n;
n = tree_FindNode(sys->pos, id);
if (n)
tree_Delete(sys->pos, n);
n = tree_FindNode(sys->hit, id);
if (n)
tree_Delete(sys->hit, n);
}
for (tree_Node *i = tree_FirstNode(sys->pos);
i != NULL;
i = tree_Node_Next(i)) {
Component_Position *pos = *((Component_Position **)i->data);
_physics_AdvanceEntity(pos->super, deltaTime);
}
}

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "util/tree.h"
#include "util/vector.h"
#include "Types.h" #include "Types.h"
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
@ -9,14 +11,15 @@ extern "C" {
#endif #endif
typedef struct Entity; typedef struct _Entity Entity;
extern double Physics_Gravity;
extern double physics_Gravity;
typedef struct { typedef struct {
Entity *super; Entity *super;
double x, y; Vec2 position;
double vecX, vecY; Vec2 velocity;
} Component_Position; } Component_Position;
@ -26,11 +29,32 @@ typedef struct {
// Moving hitboxes only hits fixed hitboxes // Moving hitboxes only hits fixed hitboxes
typedef struct { typedef struct {
Entity *super; Entity *super;
Box2 box; Box2 box;
bool fixed; bool fixed;
} Component_Hitbox; } Component_Hitbox;
// Physics manager
typedef struct {
// Every Position & Hitbox components
tree_Tree *pos, *hit;
vector_Vector *flaggedDelete;
} System_Physics;
// Returns an empty physics system.
System_Physics *physics_NewSystem();
// Frees a physics system.
void physics_DeleteSystem(System_Physics *sys);
// Adds an entity.
void physics_AddEntity(System_Physics *sys, Entity *e);
// Deletes an entity.
void physics_DeleteEntity(System_Physics *sys, uintptr_t id);
// Advance is called on every frame.
void physics_Advance(System_Physics *sys, Duration deltaTime);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -2,6 +2,7 @@
#include <stdint.h> #include <stdint.h>
#include "util/vector.h" #include "util/vector.h"
#include "Component_Physics.h"
#ifdef __cplusplus #ifdef __cplusplus
@ -10,12 +11,15 @@ extern "C" {
// Entity. // Entity.
typedef struct { typedef struct _Entity {
uintptr_t type; uintptr_t id;
uintptr_t type;
const char *name; const char *name;
} Entity; Component_Position *position;
Component_Hitbox *hitbox;
} Entity;
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -138,6 +138,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Types.c" /> <ClCompile Include="Types.c" />
<ClCompile Include="Component_Physics.c" />
<ClCompile Include="util\queue.c" /> <ClCompile Include="util\queue.c" />
<ClCompile Include="util\tree.c" /> <ClCompile Include="util\tree.c" />
<ClCompile Include="util\vector.c" /> <ClCompile Include="util\vector.c" />
@ -145,4 +146,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>
</Project> </Project>

View File

@ -55,6 +55,9 @@
</ClCompile> </ClCompile>
<ClCompile Include="Types.c"> <ClCompile Include="Types.c">
<Filter>源文件</Filter> <Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="Component_Physics.c">
<Filter>源文件</Filter>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -29,6 +29,14 @@ typedef struct {
bool box2_Intersects(const Box2 x, const Box2 y, Box2 *out_intersection); bool box2_Intersects(const Box2 x, const Box2 y, Box2 *out_intersection);
typedef struct {
uint64_t microseconds;
} Duration;
static inline double duration_Seconds(const Duration t) { return ((double)t.microseconds) / 1000.0 / 1000.0; }
static inline double duration_Milliseconds(const Duration t) { return ((double)t.microseconds) / 1000.0; }
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

21
util/assert.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
inline static void __panicf(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
int ret = vfprintf(stderr, fmt, args);
va_end(args);
abort();
}
#define ASSERT(expr) \
do { \
if (!(expr)) \
__panicf("Assertion failed: " __FILE__ ":%d[%s]\n Expression: %s", __LINE__, __func__, #expr); \
} while (0)

View File

@ -36,6 +36,18 @@ void *vector_Push(vector_Vector *vec, const void *data) {
return vec->data + vec->size - vec->objectSize; return vec->data + vec->size - vec->objectSize;
} }
bool vector_Pop(vector_Vector *vec, void *out_data) {
if (!vector_Size(vec))
return false;
if (out_data)
memcpy(out_data, vec->data + (vec->size - vec->objectSize), vec->objectSize);
vector_Resize(vec, vector_Size(vec) - 1);
return true;
}
void vector_Append(vector_Vector *vec, const void *data, uintptr_t n) { void vector_Append(vector_Vector *vec, const void *data, uintptr_t n) {
uintptr_t oldsize = vec->size, addsize = vec->objectSize * n; uintptr_t oldsize = vec->size, addsize = vec->objectSize * n;
vector_Resize(vec, oldsize + addsize); vector_Resize(vec, oldsize + addsize);

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -27,6 +28,14 @@ void vector_Destroy(vector_Vector *vec);
// Returns a pointer to data. // Returns a pointer to data.
void *vector_Push(vector_Vector *vec, const void *data); void *vector_Push(vector_Vector *vec, const void *data);
// Pop pops one object at the back of the vector.
//
// If out_data is not NULL, the popped data is copied.
//
// If the vector is already empty, return false.
// Returns true otherwise.
bool vector_Pop(vector_Vector *vec, void *out_data);
// Append pushes multiple objects at the back of the buffer. // Append pushes multiple objects at the back of the buffer.
// //
// If data is NULL, the data is zeroed. // If data is NULL, the data is zeroed.