From 115f3bad6258196dbd215ea6f225b2e32d5ec8f9 Mon Sep 17 00:00:00 2001 From: Andrew Kesterson Date: Tue, 26 May 2026 13:05:51 -0400 Subject: [PATCH] WIP --- include/akgl/SDL_GameControllerDB.h | 2 +- include/akgl/actor.h | 17 ++++++++- src/actor.c | 6 ++- src/physics.c | 59 +++++++++++++++++------------ 4 files changed, 56 insertions(+), 28 deletions(-) diff --git a/include/akgl/SDL_GameControllerDB.h b/include/akgl/SDL_GameControllerDB.h index 91d0e04..73114ce 100644 --- a/include/akgl/SDL_GameControllerDB.h +++ b/include/akgl/SDL_GameControllerDB.h @@ -1,7 +1,7 @@ #ifndef _SDL_GAMECONTROLLERDB_H_ #define _SDL_GAMECONTROLLERDB_H_ -// Taken from https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/refs/heads/master/gamecontrollerdb.txt on Tue May 26 11:21:36 AM EDT 2026 +// Taken from https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/refs/heads/master/gamecontrollerdb.txt on Tue May 26 01:00:21 PM EDT 2026 #define AKGL_SDL_GAMECONTROLLER_DB_LEN 2228 diff --git a/include/akgl/actor.h b/include/akgl/actor.h index cfa4fda..160fcc9 100644 --- a/include/akgl/actor.h +++ b/include/akgl/actor.h @@ -71,9 +71,22 @@ typedef struct akgl_Actor { void *actorData; bool visible; SDL_Time movetimer; + // Velocity. Combined effect of all forces acting on the actor resulting + // in energy along an axis. float32_t vx; float32_t vy; float32_t vz; + // Gravity. Forces acting on the actor on a given axis due to the forces + // of gravity and drag. + float32_t gx; + float32_t gy; + float32_t gz; + // Thrust. Energy originating only from the actor's own acceleration on a + // given axis, before the effects of gravity and drag. + float32_t tx; + float32_t ty; + float32_t tz; + // Position. float32_t x; float32_t y; float32_t z; @@ -83,7 +96,7 @@ typedef struct akgl_Actor { akerr_ErrorContext AKERR_NOIGNORE *(*updatefunc)(struct akgl_Actor *obj); akerr_ErrorContext AKERR_NOIGNORE *(*renderfunc)(struct akgl_Actor *obj); akerr_ErrorContext AKERR_NOIGNORE *(*facefunc)(struct akgl_Actor *obj); - akerr_ErrorContext AKERR_NOIGNORE *(*movementlogicfunc)(struct akgl_Actor *obj, SDL_Time curtimems); + akerr_ErrorContext AKERR_NOIGNORE *(*movementlogicfunc)(struct akgl_Actor *obj, float32_t dt); akerr_ErrorContext AKERR_NOIGNORE *(*changeframefunc)(struct akgl_Actor *obj, akgl_Sprite *curSprite, SDL_Time curtimems); akerr_ErrorContext AKERR_NOIGNORE *(*addchild)(struct akgl_Actor *obj, struct akgl_Actor *child); } akgl_Actor; @@ -92,7 +105,7 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_initialize(akgl_Actor *obj, char * akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_set_character(akgl_Actor *obj, char *basecharname); akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_render(akgl_Actor *obj); akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_update(akgl_Actor *obj); -akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_logic_movement(akgl_Actor *obj, SDL_Time curtimems); +akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_logic_movement(akgl_Actor *obj, float32_t dt); akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_logic_changeframe(akgl_Actor *obj, akgl_Sprite *curSprite, SDL_Time curtimems); akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_automatic_face(akgl_Actor *obj); akerr_ErrorContext AKERR_NOIGNORE *akgl_actor_add_child(akgl_Actor *obj, akgl_Actor *child); diff --git a/src/actor.c b/src/actor.c index c4f1283..f329c18 100644 --- a/src/actor.c +++ b/src/actor.c @@ -114,7 +114,7 @@ akerr_ErrorContext *akgl_actor_logic_changeframe(akgl_Actor *obj, akgl_Sprite *c } // raises AKGL_ERR_LOGICINTERRUPT if we don't want the physics object to process us -akerr_ErrorContext *akgl_actor_logic_movement(akgl_Actor *obj, SDL_Time curtime) +akerr_ErrorContext *akgl_actor_logic_movement(akgl_Actor *obj, float32_t dt) { PREPARE_ERROR(errctx); FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "obj"); @@ -277,6 +277,7 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_left_off(akgl_Actor *obj, SDL FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor"); FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event"); //SDL_Log("event %d (button %d / key %d) stops moving actor left", event->type, event->gbutton.which, event->key.key); + obj->tx = 0; obj->vx = 0; AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_LEFT); //SDL_Log("new target actor state: %b", obj->state); @@ -301,6 +302,7 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_right_off(akgl_Actor *obj, SD FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor"); FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event"); //SDL_Log("event %d (button %d / key %d) stops moving actor right", event->type, event->gbutton.which, event->key.key); + obj->tx = 0; obj->vx = 0; AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_RIGHT); //SDL_Log("new target actor state: %b", obj->state); @@ -325,6 +327,7 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_up_off(akgl_Actor *obj, SDL_E FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor"); FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event"); //SDL_Log("event %d (button %d / key %d) stops moving actor up", event->type, event->gbutton.which, event->key.key); + obj->ty = 0; obj->vy = 0; AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_UP); //SDL_Log("new target actor state: %b", obj->state); @@ -349,6 +352,7 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_down_off(akgl_Actor *obj, SDL FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor"); FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event"); //SDL_Log("event %d (button %d / key %d) stops moving actor down", event->type, event->gbutton.which, event->key.key); + obj->ty = 0; obj->vy = 0; AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_DOWN); //SDL_Log("new target actor state: %b", obj->state); diff --git a/src/physics.c b/src/physics.c index 4f19855..b5b2ae8 100644 --- a/src/physics.c +++ b/src/physics.c @@ -45,21 +45,20 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_gravity(akgl_PhysicsBackend * { PREPARE_ERROR(e); FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self"); - // Do nothing - // Calculate the drop of all relevant actors which is a function of their mass and the - // world's gravity + FAIL_ZERO_RETURN(e, actor, AKERR_NULLPOINTER, "actor"); + + // Assume the X origin is - (screen left) + actor->gx -= (self->gravity_x * dt); + // Assume Y origin is + (down screen) + actor->gy += (self->gravity_y * dt); + // Assume Z origin is - (behind the camera) + actor->gz -= (self->gravity_z * dt); - //Gravity is applied in units per second. So we apply - // (unit / milliseconds per second) * (milliseconds since last update) - actor->vx += self->gravity_x * dt; - actor->vy += self->gravity_y * dt; - actor->vz += self->gravity_z * dt; + // Counteract velocity with atmospheric drag + actor->gx += actor->vx * self->drag_x * dt; + actor->gy -= actor->vy * self->drag_y * dt; + actor->gz += actor->vz * self->drag_z * dt; - // Apply atmospheric drag - actor->vx -= actor->vx * self->drag_x * dt; - actor->vy -= actor->vy * self->drag_y * dt; - actor->vz -= actor->vz * self->drag_z * dt; - // Need a euler function SUCCEED_RETURN(e); } @@ -77,16 +76,16 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_move(struct akgl_PhysicsBacke FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self"); FAIL_ZERO_RETURN(e, actor, AKERR_NULLPOINTER, "actor"); if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_LEFT) ) { - actor->x += -actor->vx; + actor->x += (-actor->vx * dt) + (actor->gx * dt); } if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_RIGHT) ) { - actor->x += actor->vx; + actor->x += (actor->vx * dt) + (actor->gx * dt); } if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_UP) ) { - actor->y += -actor->vy; + actor->y += (-actor->vy * dt) + (actor->gy * dt); } if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_DOWN) ) { - actor->y += actor->vy; + actor->y += (actor->vy * dt) + (actor->gy * dt); } SUCCEED_RETURN(e); @@ -133,7 +132,7 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_simulate(akgl_PhysicsBackend *se .layerid = 0 }; SDL_Time curtime = SDL_GetTicksNS(); - float32_t dt = (curtime - self->gravity_time) / AKGL_TIME_ONESEC_NS; + float32_t dt = (float32_t)(curtime - self->gravity_time) / (float32_t)AKGL_TIME_ONESEC_NS; akgl_Actor *actor = NULL; FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self"); @@ -162,20 +161,32 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_simulate(akgl_PhysicsBackend *se } if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_LEFT) || AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_RIGHT) ) { - actor->vx += actor->basechar->ax * dt; + actor->tx += actor->basechar->ax * dt; } if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_UP) || AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_DOWN) ) { - actor->vy += actor->basechar->ay * dt; + actor->ty += actor->basechar->ay * dt; } - if ( actor->vx > actor->basechar->sx ) { + // velocity equals thrust unless thrust exceeds max speed + if ( actor->tx > actor->basechar->sx ) { actor->vx = actor->basechar->sx; + } else { + actor->vx = actor->tx; } - if ( actor->vy > actor->basechar->sy ) { + if ( actor->ty > actor->basechar->sy ) { actor->vy = actor->basechar->sy; + } else { + actor->vy = actor->ty; } - //PASS(e, self->gravity(self, actor, dt)); - PASS(e, self->move(self, actor, dt)); + ATTEMPT { + CATCH(e, actor->movementlogicfunc(actor, dt)); + PASS(e, self->gravity(self, actor, dt)); + PASS(e, self->move(self, actor, dt)); + } CLEANUP { + } PROCESS(e) { + } HANDLE(e, AKGL_ERR_LOGICINTERRUPT) { + // noop + } FINISH(e, true); } self->gravity_time = curtime; SUCCEED_RETURN(e);