Physics I guess
This commit is contained in:
@@ -35,6 +35,7 @@ add_subdirectory(engine)
|
||||
add_subdirectory(error)
|
||||
add_subdirectory(input)
|
||||
# add_subdirectory(locale)
|
||||
add_subdirectory(physics)
|
||||
add_subdirectory(rpg)
|
||||
add_subdirectory(thread)
|
||||
add_subdirectory(time)
|
||||
|
@@ -70,6 +70,23 @@ void cameraPushMatrix(camera_t *camera) {
|
||||
view
|
||||
);
|
||||
break;
|
||||
|
||||
case CAMERA_VIEW_TYPE_2D:
|
||||
glm_mat4_identity(view);
|
||||
glm_translate(view, (vec3){
|
||||
-camera->_2d.position[0],
|
||||
-camera->_2d.position[1],
|
||||
0.0f
|
||||
});
|
||||
glm_scale(view, (vec3){
|
||||
camera->_2d.zoom,
|
||||
camera->_2d.zoom,
|
||||
1.0f
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
assertUnreachable("Invalid camera view type");
|
||||
}
|
||||
|
||||
#if DISPLAY_SDL2
|
||||
|
@@ -18,7 +18,8 @@ typedef enum {
|
||||
|
||||
typedef enum {
|
||||
CAMERA_VIEW_TYPE_MATRIX,
|
||||
CAMERA_VIEW_TYPE_LOOKAT
|
||||
CAMERA_VIEW_TYPE_LOOKAT,
|
||||
CAMERA_VIEW_TYPE_2D
|
||||
} cameraviewtype_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -27,11 +28,17 @@ typedef struct {
|
||||
|
||||
union {
|
||||
mat4 view;
|
||||
|
||||
struct {
|
||||
float_t position[3];
|
||||
float_t target[3];
|
||||
float_t up[3];
|
||||
} lookat;
|
||||
|
||||
struct {
|
||||
float_t position[2];
|
||||
float_t zoom;
|
||||
} _2d;
|
||||
};
|
||||
|
||||
union {
|
||||
|
@@ -11,3 +11,4 @@ target_sources(${DUSK_TARGET_NAME}
|
||||
|
||||
# Subdirs
|
||||
add_subdirectory(overworld)
|
||||
add_subdirectory(test)
|
@@ -93,9 +93,9 @@ void sceneOverworldRenderEntity(const entity_t *entity) {
|
||||
// For now, just draw a placeholder quad.
|
||||
spriteBatchPush(
|
||||
&testAsset->paletteImage.texture,
|
||||
entity->x, entity->y,
|
||||
entity->x + TILESET_ENTITIES.tileWidth,
|
||||
entity->y + TILESET_ENTITIES.tileHeight,
|
||||
entity->position[0], entity->position[1],
|
||||
entity->position[0] + TILESET_ENTITIES.tileWidth,
|
||||
entity->position[1] + TILESET_ENTITIES.tileHeight,
|
||||
COLOR_WHITE,
|
||||
uv[0], uv[1], uv[2], uv[3]
|
||||
);
|
||||
|
@@ -25,6 +25,7 @@ typedef struct {
|
||||
|
||||
typedef enum {
|
||||
SCENE_TYPE_LOGO,
|
||||
SCENE_TYPE_TEST,
|
||||
SCENE_TYPE_OVERWORLD,
|
||||
|
||||
SCENE_TYPE_COUNT
|
||||
|
@@ -8,12 +8,20 @@
|
||||
#include "scenemanager.h"
|
||||
|
||||
#include "display/scene/overworld/sceneoverworld.h"
|
||||
#include "display/scene/test/scenetest.h"
|
||||
|
||||
scenemanager_t SCENE_MANAGER;
|
||||
|
||||
scene_t SCENE_MANAGER_SCENES[SCENE_TYPE_COUNT] = {
|
||||
[SCENE_TYPE_LOGO] = { 0 },
|
||||
|
||||
[SCENE_TYPE_TEST] = {
|
||||
.init = sceneTestInit,
|
||||
.update = sceneTestUpdate,
|
||||
.render = sceneTestRender,
|
||||
.dispose = sceneTestDispose
|
||||
},
|
||||
|
||||
[SCENE_TYPE_OVERWORLD] = {
|
||||
.init = sceneOverworldInit,
|
||||
.update = sceneOverworldUpdate,
|
||||
|
@@ -15,7 +15,22 @@ typedef struct {
|
||||
extern scenemanager_t SCENE_MANAGER;
|
||||
extern scene_t SCENE_MANAGER_SCENES[SCENE_TYPE_COUNT];
|
||||
|
||||
/**
|
||||
* Initializes the scene manager and the initial scene.
|
||||
*/
|
||||
errorret_t sceneManagerInit(void);
|
||||
|
||||
/**
|
||||
* Updates all active scenes.
|
||||
*/
|
||||
void sceneManagerUpdate(void);
|
||||
|
||||
/**
|
||||
* Renders all visible scenes.
|
||||
*/
|
||||
void sceneManagerRender(void);
|
||||
|
||||
/**
|
||||
* Disposes of all scenes.
|
||||
*/
|
||||
void sceneManagerDispose(void);
|
10
src/display/scene/test/CMakeLists.txt
Normal file
10
src/display/scene/test/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
scenetest.c
|
||||
)
|
48
src/display/scene/test/scenetest.c
Normal file
48
src/display/scene/test/scenetest.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "scenetest.h"
|
||||
#include "display/scene/scenemanager.h"
|
||||
#include "display/spritebatch/spritebatch.h"
|
||||
|
||||
scenetest_t SCENE_TEST;
|
||||
|
||||
errorret_t sceneTestInit(void) {
|
||||
cameraInit(&SCENE_TEST.camera);
|
||||
SCENE_TEST.camera.projType = CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC;
|
||||
SCENE_TEST.camera.nearClip = -1.0f;
|
||||
SCENE_TEST.camera.farClip = 2.0f;
|
||||
|
||||
SCENE_TEST.camera.viewType = CAMERA_VIEW_TYPE_2D;
|
||||
SCENE_TEST.camera._2d.zoom = 2.0f;
|
||||
SCENE_TEST.camera._2d.position[0] = -150.0f;
|
||||
SCENE_TEST.camera._2d.position[1] = -50.0f;
|
||||
|
||||
scene_t *scene = &SCENE_MANAGER_SCENES[SCENE_TYPE_TEST];
|
||||
scene->flags |= SCENE_FLAG_ACTIVE | SCENE_FLAG_VISIBLE;
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
void sceneTestUpdate(void) {
|
||||
}
|
||||
|
||||
void sceneTestRender(void) {
|
||||
SCENE_TEST.camera.orthographic.left = 0.0f;
|
||||
SCENE_TEST.camera.orthographic.right = frameBufferGetWidth(FRAMEBUFFER_BOUND);
|
||||
SCENE_TEST.camera.orthographic.top = frameBufferGetHeight(FRAMEBUFFER_BOUND);
|
||||
SCENE_TEST.camera.orthographic.bottom = 0.0f;
|
||||
|
||||
cameraPushMatrix(&SCENE_TEST.camera);
|
||||
spriteBatchClear();
|
||||
|
||||
spriteBatchFlush();
|
||||
cameraPopMatrix();
|
||||
}
|
||||
|
||||
void sceneTestDispose(void) {
|
||||
}
|
36
src/display/scene/test/scenetest.h
Normal file
36
src/display/scene/test/scenetest.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "display/camera.h"
|
||||
#include "error/error.h"
|
||||
|
||||
typedef struct {
|
||||
camera_t camera;
|
||||
} scenetest_t;
|
||||
|
||||
extern scenetest_t SCENE_TEST;
|
||||
|
||||
/**
|
||||
* Initialize the test scene.
|
||||
*/
|
||||
errorret_t sceneTestInit(void);
|
||||
|
||||
/**
|
||||
* Update the test scene.
|
||||
*/
|
||||
void sceneTestUpdate(void);
|
||||
|
||||
/**
|
||||
* Render the test scene.
|
||||
*/
|
||||
void sceneTestRender(void);
|
||||
|
||||
/**
|
||||
* Dispose of the test scene.
|
||||
*/
|
||||
void sceneTestDispose(void);
|
@@ -16,8 +16,10 @@
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <float.h>
|
||||
|
||||
#include <cglm/cglm.h>
|
||||
#include <cglm/types.h>
|
||||
#include <cglm/vec2.h>
|
||||
|
||||
#if PSP
|
||||
#include <pspkernel.h>
|
||||
|
@@ -71,7 +71,7 @@ errorret_t errorChainImpl(
|
||||
) {
|
||||
if (retval.code == ERROR_OK) return retval;
|
||||
|
||||
assertNotNull(retval.state, "Error state cannot be NULL");
|
||||
assertNotNull(retval.state, "Error state NULL (Likely missing errorOk)");
|
||||
assertNotNull(retval.state->message, "Message cannot be NULL");
|
||||
|
||||
// Create a new line string.
|
||||
|
10
src/physics/CMakeLists.txt
Normal file
10
src/physics/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2025 Dominic Masters
|
||||
#
|
||||
# This software is released under the MIT License.
|
||||
# https://opensource.org/licenses/MIT
|
||||
|
||||
# Sources
|
||||
target_sources(${DUSK_TARGET_NAME}
|
||||
PRIVATE
|
||||
physicscircle.c
|
||||
)
|
9
src/physics/physics.h
Normal file
9
src/physics/physics.h
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "physicscircle.h"
|
33
src/physics/physicscircle.c
Normal file
33
src/physics/physicscircle.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "physicscircle.h"
|
||||
|
||||
void physicsCircleCheckCircle(
|
||||
const physicscircle_t a,
|
||||
const physicscircle_t b,
|
||||
physicscirclecircleresult_t *out
|
||||
) {
|
||||
vec2 delta;
|
||||
glm_vec2_sub(b.position, a.position, delta);
|
||||
float_t distSq = glm_vec2_dot(delta, delta);
|
||||
float_t radiusSum = a.radius + b.radius;
|
||||
float_t radiusSumSq = radiusSum * radiusSum;
|
||||
|
||||
if(distSq < radiusSumSq) {
|
||||
out->hit = true;
|
||||
if (distSq != 0.0f) {
|
||||
glm_vec2_normalize_to(delta, out->normal);
|
||||
} else {
|
||||
out->normal[0] = 1.0f;
|
||||
out->normal[1] = 0.0f;
|
||||
}
|
||||
out->depth = radiusSum - sqrtf(distSq);
|
||||
} else {
|
||||
out->hit = false;
|
||||
}
|
||||
}
|
33
src/physics/physicscircle.h
Normal file
33
src/physics/physicscircle.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "dusk.h"
|
||||
|
||||
typedef struct physicscircle_s {
|
||||
vec2 position;
|
||||
float_t radius;
|
||||
} physicscircle_t;
|
||||
|
||||
typedef struct physicscirclecircleresult_s {
|
||||
bool_t hit;
|
||||
vec2 normal;
|
||||
float_t depth;
|
||||
} physicscirclecircleresult_t;
|
||||
|
||||
/**
|
||||
* Check for collision between two circles.
|
||||
*
|
||||
* @param a The first circle.
|
||||
* @param b The second circle.
|
||||
* @param out Pointer to the result structure to populate.
|
||||
*/
|
||||
void physicsCircleCheckCircle(
|
||||
const physicscircle_t a,
|
||||
const physicscircle_t b,
|
||||
physicscirclecircleresult_t *out
|
||||
);
|
@@ -8,6 +8,7 @@
|
||||
#include "entity.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
#include "display/tileset/tileset_entities.h"
|
||||
|
||||
entitycallback_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT] = {
|
||||
{ NULL, NULL }, // ENTITY_TYPE_NULL
|
||||
|
@@ -9,6 +9,7 @@
|
||||
// #include "direction.h"
|
||||
#include "rpg/entity/player.h"
|
||||
#include "npc.h"
|
||||
#include "physics/physics.h"
|
||||
|
||||
typedef struct {
|
||||
void (*init)(entity_t *entity);
|
||||
@@ -25,10 +26,12 @@ typedef enum {
|
||||
|
||||
typedef struct entity_s {
|
||||
// uint32_t id;// Completely unique ID for this entity.
|
||||
float_t x, y;
|
||||
entitytype_t type;
|
||||
// direction_t dir;
|
||||
|
||||
vec2 position;
|
||||
vec2 velocity;
|
||||
|
||||
union {
|
||||
player_t player;
|
||||
npc_t npc;
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include "input/input.h"
|
||||
|
||||
#include "display/scene/overworld/sceneoverworld.h"
|
||||
#include "display/tileset/tileset_entities.h"
|
||||
|
||||
void playerInit(entity_t *entity) {
|
||||
assertNotNull(entity, "Entity pointer cannot be NULL");
|
||||
@@ -26,9 +27,26 @@ void playerUpdate(entity_t *entity) {
|
||||
inputAxis(INPUT_ACTION_UP, INPUT_ACTION_DOWN)
|
||||
};
|
||||
glm_vec2_normalize(dir);
|
||||
entity->x += move * dir[0];
|
||||
entity->y -= move * dir[1];
|
||||
entity->position[0] += move * dir[0];
|
||||
entity->position[1] -= move * dir[1];
|
||||
|
||||
SCENE_OVERWORLD.camera.lookat.target[0] = entity->x;
|
||||
SCENE_OVERWORLD.camera.lookat.target[1] = entity->y;
|
||||
SCENE_OVERWORLD.camera.lookat.target[0] = entity->position[0];
|
||||
SCENE_OVERWORLD.camera.lookat.target[1] = entity->position[1];
|
||||
|
||||
// Can we move?
|
||||
physicscircle_t npc = {
|
||||
.position = { 32.0f, 32.0f },
|
||||
.radius = TILESET_ENTITIES.tileWidth / 2.0f
|
||||
};
|
||||
|
||||
physicscircle_t self;
|
||||
glm_vec2_copy(entity->position, self.position);
|
||||
self.radius = npc.radius;
|
||||
|
||||
physicscirclecircleresult_t result;
|
||||
physicsCircleCheckCircle(self, npc, &result);
|
||||
if(result.hit) {
|
||||
entity->position[0] -= result.normal[0] * result.depth;
|
||||
entity->position[1] -= result.normal[1] * result.depth;
|
||||
}
|
||||
}
|
@@ -19,8 +19,8 @@ void rpgInit() {
|
||||
|
||||
entity_t *npc = mapEntityAdd(&testMap);
|
||||
entityInit(npc, ENTITY_TYPE_NPC);
|
||||
npc->x = 32.0f;
|
||||
npc->y = 32.0f;
|
||||
npc->position[0] = 32.0f;
|
||||
npc->position[1] = 32.0f;
|
||||
}
|
||||
|
||||
void rpgUpdate() {
|
||||
|
@@ -10,9 +10,25 @@
|
||||
|
||||
#define MAP_ENTITY_COUNT_MAX 32
|
||||
|
||||
#define MAP_WIDTH_MAX 64
|
||||
#define MAP_HEIGHT_MAX 64
|
||||
#define MAP_TILE_COUNT_MAX (MAP_WIDTH_MAX * MAP_HEIGHT_MAX)
|
||||
|
||||
typedef struct {
|
||||
uint8_t id;
|
||||
} tile_t;
|
||||
|
||||
typedef struct {
|
||||
tile_t tiles[MAP_TILE_COUNT_MAX];
|
||||
} maplayer_t;
|
||||
|
||||
typedef struct {
|
||||
entity_t entities[MAP_ENTITY_COUNT_MAX];
|
||||
uint8_t entityCount;
|
||||
|
||||
uint8_t width, height;
|
||||
maplayer_t base;
|
||||
maplayer_t overlay;
|
||||
} map_t;
|
||||
|
||||
extern map_t testMap;
|
||||
|
16
src/rpg/world/tile.h
Normal file
16
src/rpg/world/tile.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
TILE_TYPE_NULL,
|
||||
} tiletype_t;
|
||||
|
||||
typedef struct {
|
||||
tiletype_t type;
|
||||
} tile_t;
|
@@ -21,6 +21,9 @@ void timeInit(void) {
|
||||
// Set these to something non-zero.
|
||||
TIME.time = TIME_STEP;
|
||||
TIME.delta = TIME_STEP;
|
||||
|
||||
TIME.fixedDelta = TIME_STEP;
|
||||
TIME.fixedTime = TIME_STEP;
|
||||
}
|
||||
|
||||
void timeUpdate(void) {
|
||||
@@ -36,4 +39,14 @@ void timeUpdate(void) {
|
||||
TIME.delta = delta;
|
||||
assertTrue(TIME.delta >= 0.0f, "Time delta is negative");
|
||||
TIME.time += TIME.delta;
|
||||
|
||||
// Perform a fixed time step.
|
||||
if(TIME.time - TIME.fixedTime >= TIME_STEP) {
|
||||
TIME.fixedUpdate = true;
|
||||
TIME.fixedDelta = TIME_STEP;
|
||||
TIME.fixedTime += TIME_STEP;
|
||||
} else {
|
||||
TIME.fixedDelta = 0.0f;
|
||||
TIME.fixedUpdate = false;
|
||||
}
|
||||
}
|
@@ -11,6 +11,10 @@
|
||||
typedef struct {
|
||||
float_t delta;
|
||||
float_t time;
|
||||
|
||||
bool_t fixedUpdate;
|
||||
float_t fixedDelta;
|
||||
float_t fixedTime;
|
||||
} dusktime_t;
|
||||
|
||||
extern dusktime_t TIME;
|
||||
|
Reference in New Issue
Block a user