Physics simulation engine implemented, basic cases (null and 2d SideScroller) works
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
#ifndef _SDL_GAMECONTROLLERDB_H_
|
#ifndef _SDL_GAMECONTROLLERDB_H_
|
||||||
#define _SDL_GAMECONTROLLERDB_H_
|
#define _SDL_GAMECONTROLLERDB_H_
|
||||||
|
|
||||||
// Taken from https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/refs/heads/master/gamecontrollerdb.txt on Mon May 25 09:28:01 PM EDT 2026
|
// Taken from https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/refs/heads/master/gamecontrollerdb.txt on Tue May 26 10:27:58 AM EDT 2026
|
||||||
|
|
||||||
#define AKGL_SDL_GAMECONTROLLER_DB_LEN 2228
|
#define AKGL_SDL_GAMECONTROLLER_DB_LEN 2228
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
#define AKGL_ACTOR_STATE_MOVING_RIGHT 1 << 8 // 256 0000 0001 0000 0000
|
#define AKGL_ACTOR_STATE_MOVING_RIGHT 1 << 8 // 256 0000 0001 0000 0000
|
||||||
#define AKGL_ACTOR_STATE_MOVING_UP 1 << 9 // 512 0000 0010 0000 0000
|
#define AKGL_ACTOR_STATE_MOVING_UP 1 << 9 // 512 0000 0010 0000 0000
|
||||||
#define AKGL_ACTOR_STATE_MOVING_DOWN 1 << 10 // 1024 0000 0100 0000 0000
|
#define AKGL_ACTOR_STATE_MOVING_DOWN 1 << 10 // 1024 0000 0100 0000 0000
|
||||||
#define AKGL_ACTOR_STATE_UNDEFINED_11 1 << 11 // 2048 0000 1000 0000 0000
|
#define AKGL_ACTOR_STATE_MOVING_IN 1 << 11 // 2048 0000 1000 0000 0000
|
||||||
#define AKGL_ACTOR_STATE_UNDEFINED_12 1 << 12 // 4096 0001 0000 0000 0000
|
#define AKGL_ACTOR_STATE_MOVING_OUT 1 << 12 // 4096 0001 0000 0000 0000
|
||||||
#define AKGL_ACTOR_STATE_UNDEFINED_13 1 << 13 // 8192 0010 0000 0000 0000
|
#define AKGL_ACTOR_STATE_UNDEFINED_13 1 << 13 // 8192 0010 0000 0000 0000
|
||||||
#define AKGL_ACTOR_STATE_UNDEFINED_14 1 << 14 // 16384 0100 0000 0000 0000
|
#define AKGL_ACTOR_STATE_UNDEFINED_14 1 << 14 // 16384 0100 0000 0000 0000
|
||||||
#define AKGL_ACTOR_STATE_UNDEFINED_15 1 << 15 // 32768 1000 0000 0000 0000
|
#define AKGL_ACTOR_STATE_UNDEFINED_15 1 << 15 // 32768 1000 0000 0000 0000
|
||||||
@@ -71,7 +71,9 @@ typedef struct akgl_Actor {
|
|||||||
void *actorData;
|
void *actorData;
|
||||||
bool visible;
|
bool visible;
|
||||||
SDL_Time movetimer;
|
SDL_Time movetimer;
|
||||||
float32_t mass;
|
float32_t vx;
|
||||||
|
float32_t vy;
|
||||||
|
float32_t vz;
|
||||||
float32_t x;
|
float32_t x;
|
||||||
float32_t y;
|
float32_t y;
|
||||||
float32_t z;
|
float32_t z;
|
||||||
|
|||||||
@@ -12,9 +12,13 @@ typedef struct akgl_Character {
|
|||||||
uint8_t refcount;
|
uint8_t refcount;
|
||||||
char name[AKGL_SPRITE_MAX_CHARACTER_NAME_LENGTH];
|
char name[AKGL_SPRITE_MAX_CHARACTER_NAME_LENGTH];
|
||||||
SDL_PropertiesID state_sprites;
|
SDL_PropertiesID state_sprites;
|
||||||
uint64_t movementspeed;
|
uint64_t speedtime;
|
||||||
float32_t vx;
|
float32_t ax;
|
||||||
float32_t vy;
|
float32_t ay;
|
||||||
|
float32_t az;
|
||||||
|
float32_t sx;
|
||||||
|
float32_t sy;
|
||||||
|
float32_t sz;
|
||||||
akerr_ErrorContext AKERR_NOIGNORE *(*sprite_add)(struct akgl_Character *, akgl_Sprite *, int);
|
akerr_ErrorContext AKERR_NOIGNORE *(*sprite_add)(struct akgl_Character *, akgl_Sprite *, int);
|
||||||
akerr_ErrorContext AKERR_NOIGNORE *(*sprite_get)(struct akgl_Character *, int, akgl_Sprite **);
|
akerr_ErrorContext AKERR_NOIGNORE *(*sprite_get)(struct akgl_Character *, int, akgl_Sprite **);
|
||||||
} akgl_Character;
|
} akgl_Character;
|
||||||
|
|||||||
40
include/akgl/physics.h
Normal file
40
include/akgl/physics.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#ifndef _PHYSICS_H_
|
||||||
|
#define _PHYSICS_H_
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <akerror.h>
|
||||||
|
#include <akgl/actor.h>
|
||||||
|
#include <akgl/iterator.h>
|
||||||
|
|
||||||
|
typedef struct akgl_PhysicsBackend {
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *(*simulate)(struct akgl_PhysicsBackend *self, akgl_Iterator *opflags);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *(*gravity)(struct akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *(*collide)(struct akgl_PhysicsBackend *self, akgl_Actor *a1, akgl_Actor *a2);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *(*move)(struct akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime);
|
||||||
|
|
||||||
|
double drag_x;
|
||||||
|
double drag_y;
|
||||||
|
double drag_z;
|
||||||
|
double gravity_x;
|
||||||
|
double gravity_y;
|
||||||
|
double gravity_z;
|
||||||
|
SDL_Time gravity_time;
|
||||||
|
SDL_Time timer_gravity;
|
||||||
|
|
||||||
|
} akgl_PhysicsBackend;
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_gravity(akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_collide(akgl_PhysicsBackend *self, akgl_Actor *a1, akgl_Actor *a2);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_move(akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_init_null(akgl_PhysicsBackend *self);
|
||||||
|
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_gravity(akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_collide(akgl_PhysicsBackend *self, akgl_Actor *a1, akgl_Actor *a2);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_move(akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime);
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_init_sidescroller(akgl_PhysicsBackend *self);
|
||||||
|
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_simulate(akgl_PhysicsBackend *self, akgl_Iterator *opflags);
|
||||||
|
|
||||||
|
#endif // _PHYSICS_H_
|
||||||
13
src/actor.c
13
src/actor.c
@@ -117,7 +117,14 @@ akerr_ErrorContext *akgl_actor_logic_changeframe(akgl_Actor *obj, akgl_Sprite *c
|
|||||||
akerr_ErrorContext *akgl_actor_logic_movement(akgl_Actor *obj, SDL_Time curtime)
|
akerr_ErrorContext *akgl_actor_logic_movement(akgl_Actor *obj, SDL_Time curtime)
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "Null actor reference");
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "obj");
|
||||||
|
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "obj->basechar");
|
||||||
|
if ( obj->vx > obj->basechar->sx ) {
|
||||||
|
obj->vx = obj->basechar->sx;
|
||||||
|
}
|
||||||
|
if ( obj->vy > obj->basechar->sy ) {
|
||||||
|
obj->vy = obj->basechar->sy;
|
||||||
|
}
|
||||||
// Effectively a NOOP, this is handled by the physics engine now
|
// Effectively a NOOP, this is handled by the physics engine now
|
||||||
// These functions are still present in case the library user wants per-actor behavior
|
// These functions are still present in case the library user wants per-actor behavior
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
@@ -276,6 +283,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, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||||
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
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);
|
//SDL_Log("event %d (button %d / key %d) stops moving actor left", event->type, event->gbutton.which, event->key.key);
|
||||||
|
obj->vx = 0;
|
||||||
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_LEFT);
|
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_LEFT);
|
||||||
//SDL_Log("new target actor state: %b", obj->state);
|
//SDL_Log("new target actor state: %b", obj->state);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
@@ -299,6 +307,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, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||||
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
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);
|
//SDL_Log("event %d (button %d / key %d) stops moving actor right", event->type, event->gbutton.which, event->key.key);
|
||||||
|
obj->vx = 0;
|
||||||
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_RIGHT);
|
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_RIGHT);
|
||||||
//SDL_Log("new target actor state: %b", obj->state);
|
//SDL_Log("new target actor state: %b", obj->state);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
@@ -322,6 +331,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, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||||
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
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);
|
//SDL_Log("event %d (button %d / key %d) stops moving actor up", event->type, event->gbutton.which, event->key.key);
|
||||||
|
obj->vy = 0;
|
||||||
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_UP);
|
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_UP);
|
||||||
//SDL_Log("new target actor state: %b", obj->state);
|
//SDL_Log("new target actor state: %b", obj->state);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
@@ -345,6 +355,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, obj, AKERR_NULLPOINTER, "NULL actor");
|
||||||
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event");
|
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);
|
//SDL_Log("event %d (button %d / key %d) stops moving actor down", event->type, event->gbutton.which, event->key.key);
|
||||||
|
obj->vy = 0;
|
||||||
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_DOWN);
|
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_DOWN);
|
||||||
//SDL_Log("new target actor state: %b", obj->state);
|
//SDL_Log("new target actor state: %b", obj->state);
|
||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
|
|||||||
@@ -185,10 +185,12 @@ akerr_ErrorContext *akgl_character_load_json(char *filename)
|
|||||||
"Error while loading character from %s on line %d: %s", filename, error.line, error.text
|
"Error while loading character from %s on line %d: %s", filename, error.line, error.text
|
||||||
);
|
);
|
||||||
CATCH(errctx, akgl_character_load_json_inner(json, obj));
|
CATCH(errctx, akgl_character_load_json_inner(json, obj));
|
||||||
CATCH(errctx, akgl_get_json_integer_value(json, "movementspeed", (int *)&obj->movementspeed));
|
CATCH(errctx, akgl_get_json_integer_value(json, "speedtime", (int *)&obj->speedtime));
|
||||||
obj->movementspeed = obj->movementspeed * AKGL_TIME_ONESEC_MS;
|
obj->speedtime = obj->speedtime * AKGL_TIME_ONESEC_MS;
|
||||||
CATCH(errctx, akgl_get_json_number_value(json, "velocity_x", &obj->vx));
|
CATCH(errctx, akgl_get_json_number_value(json, "speed_x", &obj->sx));
|
||||||
CATCH(errctx, akgl_get_json_number_value(json, "velocity_y", &obj->vy));
|
CATCH(errctx, akgl_get_json_number_value(json, "speed_y", &obj->sy));
|
||||||
|
CATCH(errctx, akgl_get_json_number_value(json, "acceleration_x", &obj->ax));
|
||||||
|
CATCH(errctx, akgl_get_json_number_value(json, "acceleration_y", &obj->ay));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
//IGNORE(akgl_heap_release_string(tmpstr));
|
//IGNORE(akgl_heap_release_string(tmpstr));
|
||||||
if ( errctx != NULL ) {
|
if ( errctx != NULL ) {
|
||||||
|
|||||||
186
src/physics.c
Normal file
186
src/physics.c
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
#include <akstdlib.h>
|
||||||
|
#include <akgl/physics.h>
|
||||||
|
#include <akgl/actor.h>
|
||||||
|
#include <akgl/game.h>
|
||||||
|
#include <akgl/error.h>
|
||||||
|
#include <akgl/heap.h>
|
||||||
|
#include <akgl/registry.h>
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_gravity(akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime)
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(e);
|
||||||
|
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||||
|
SUCCEED_RETURN(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_collide(akgl_PhysicsBackend *self, akgl_Actor *a1, akgl_Actor *a2)
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(e);
|
||||||
|
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||||
|
SUCCEED_RETURN(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_move(struct akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime)
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(e);
|
||||||
|
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||||
|
SUCCEED_RETURN(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_init_null(akgl_PhysicsBackend *self)
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(e);
|
||||||
|
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||||
|
|
||||||
|
self->gravity = akgl_physics_null_gravity;
|
||||||
|
self->collide = akgl_physics_null_collide;
|
||||||
|
self->move = akgl_physics_null_move;
|
||||||
|
self->simulate = akgl_physics_simulate;
|
||||||
|
|
||||||
|
SUCCEED_RETURN(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_gravity(akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
|
||||||
|
//Gravity is applied in units per second. So we apply
|
||||||
|
// (unit / milliseconds per second) * (milliseconds since last update)
|
||||||
|
actor->vx += ((self->gravity_x / AKGL_TIME_ONESEC_NS) * (curtime - self->gravity_time));
|
||||||
|
actor->vy += ((self->gravity_y / AKGL_TIME_ONESEC_NS) * (curtime - self->gravity_time));
|
||||||
|
actor->vz += ((self->gravity_z / AKGL_TIME_ONESEC_NS) * (curtime - self->gravity_time));
|
||||||
|
|
||||||
|
// Apply atmospheric drag
|
||||||
|
actor->vx -= actor->vx * self->drag_x * (curtime - self->gravity_time);
|
||||||
|
actor->vy -= actor->vy * self->drag_x * (curtime - self->gravity_time);
|
||||||
|
actor->vz -= actor->vz * self->drag_x * (curtime - self->gravity_time);
|
||||||
|
// Need a euler function
|
||||||
|
SUCCEED_RETURN(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_collide(akgl_PhysicsBackend *self, akgl_Actor *a1, akgl_Actor *a2)
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(e);
|
||||||
|
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||||
|
FAIL_RETURN(e, AKERR_API, "Not implemented");
|
||||||
|
SUCCEED_RETURN(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_move(struct akgl_PhysicsBackend *self, akgl_Actor *actor, SDL_Time curtime)
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(e);
|
||||||
|
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||||
|
FAIL_ZERO_RETURN(e, actor, AKERR_NULLPOINTER, "actor");
|
||||||
|
|
||||||
|
if ( actor->parent != NULL ) {
|
||||||
|
// Children don't move independently of their parents, they just have an offset
|
||||||
|
SUCCEED_RETURN(e);
|
||||||
|
} else if ( actor->basechar == NULL ) {
|
||||||
|
SUCCEED_RETURN(e);
|
||||||
|
} else {
|
||||||
|
if ( (curtime - actor->movetimer) >= actor->basechar->speedtime ) {
|
||||||
|
actor->movetimer = curtime;
|
||||||
|
ATTEMPT {
|
||||||
|
CATCH(e, actor->movementlogicfunc(actor,curtime));
|
||||||
|
} CLEANUP {
|
||||||
|
} PROCESS(e) {
|
||||||
|
} HANDLE(e, AKGL_ERR_LOGICINTERRUPT) {
|
||||||
|
// The actor told us NOT to process them, they handled their own update
|
||||||
|
SUCCEED_RETURN(e);
|
||||||
|
} FINISH(e, true);
|
||||||
|
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_LEFT) ) {
|
||||||
|
actor->x += -actor->vx;
|
||||||
|
}
|
||||||
|
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_RIGHT) ) {
|
||||||
|
actor->x += actor->vx;
|
||||||
|
}
|
||||||
|
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_UP) ) {
|
||||||
|
actor->y += -actor->vy;
|
||||||
|
}
|
||||||
|
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_DOWN) ) {
|
||||||
|
actor->y += actor->vy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SUCCEED_RETURN(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_init_sidescroller(akgl_PhysicsBackend *self)
|
||||||
|
{
|
||||||
|
akgl_String *tmp;
|
||||||
|
PREPARE_ERROR(e);
|
||||||
|
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||||
|
PASS(e, akgl_heap_next_string(&tmp));
|
||||||
|
|
||||||
|
self->gravity = akgl_physics_ss_gravity;
|
||||||
|
self->collide = akgl_physics_ss_collide;
|
||||||
|
self->move = akgl_physics_ss_move;
|
||||||
|
self->simulate = akgl_physics_simulate;
|
||||||
|
|
||||||
|
ATTEMPT {
|
||||||
|
CATCH(e, akgl_get_property("physics.gravity.x", &tmp, "0.0"));
|
||||||
|
CATCH(e, aksl_atof(tmp->data, &self->gravity_x));
|
||||||
|
CATCH(e, akgl_get_property("physics.gravity.y", &tmp, "0.0"));
|
||||||
|
CATCH(e, aksl_atof(tmp->data, &self->gravity_y));
|
||||||
|
CATCH(e, akgl_get_property("physics.gravity.z", &tmp, "0.0"));
|
||||||
|
CATCH(e, aksl_atof(tmp->data, &self->gravity_z));
|
||||||
|
CATCH(e, akgl_get_property("physics.drag.x", &tmp, "0.0"));
|
||||||
|
CATCH(e, aksl_atof(tmp->data, &self->drag_x));
|
||||||
|
CATCH(e, akgl_get_property("physics.drag.y", &tmp, "0.0"));
|
||||||
|
CATCH(e, aksl_atof(tmp->data, &self->drag_y));
|
||||||
|
CATCH(e, akgl_get_property("physics.drag.z", &tmp, "0.0"));
|
||||||
|
CATCH(e, aksl_atof(tmp->data, &self->drag_z));
|
||||||
|
} CLEANUP {
|
||||||
|
IGNORE(akgl_heap_release_string(tmp));
|
||||||
|
} PROCESS(e) {
|
||||||
|
} FINISH(e, true);
|
||||||
|
|
||||||
|
SUCCEED_RETURN(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_simulate(akgl_PhysicsBackend *self, akgl_Iterator *opflags)
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(e);
|
||||||
|
akgl_Iterator defflags = {
|
||||||
|
.flags = 0,
|
||||||
|
.layerid = 0
|
||||||
|
};
|
||||||
|
SDL_Time curtime = SDL_GetTicksNS();
|
||||||
|
akgl_Actor *actor = NULL;
|
||||||
|
|
||||||
|
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
|
||||||
|
FAIL_ZERO_RETURN(e, self->move, AKERR_NULLPOINTER, "self->move");
|
||||||
|
|
||||||
|
if ( opflags == NULL ) {
|
||||||
|
opflags = &defflags;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int i = 0; i < AKGL_MAX_HEAP_ACTOR; i++ ) {
|
||||||
|
actor = &HEAP_ACTOR[i];
|
||||||
|
if ( actor->refcount == 0 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( AKGL_BITMASK_HAS(opflags->flags, AKGL_ITERATOR_OP_LAYERMASK) ) {
|
||||||
|
if ( actor->layer != opflags->layerid ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
PASS(e, self->gravity(self, actor, curtime));
|
||||||
|
PASS(e, self->move(self, actor, curtime));
|
||||||
|
self->gravity_time = curtime;
|
||||||
|
}
|
||||||
|
SUCCEED_RETURN(e);
|
||||||
|
}
|
||||||
@@ -10,14 +10,14 @@
|
|||||||
#include <akgl/actor.h>
|
#include <akgl/actor.h>
|
||||||
#include <akgl/json_helpers.h>
|
#include <akgl/json_helpers.h>
|
||||||
|
|
||||||
SDL_PropertiesID AKGL_REGISTRY_ACTOR;
|
SDL_PropertiesID AKGL_REGISTRY_ACTOR = 0;
|
||||||
SDL_PropertiesID AKGL_REGISTRY_ACTOR_STATE_STRINGS;
|
SDL_PropertiesID AKGL_REGISTRY_ACTOR_STATE_STRINGS = 0;
|
||||||
SDL_PropertiesID AKGL_REGISTRY_SPRITE;
|
SDL_PropertiesID AKGL_REGISTRY_SPRITE = 0;
|
||||||
SDL_PropertiesID AKGL_REGISTRY_SPRITESHEET;
|
SDL_PropertiesID AKGL_REGISTRY_SPRITESHEET = 0;
|
||||||
SDL_PropertiesID AKGL_REGISTRY_CHARACTER;
|
SDL_PropertiesID AKGL_REGISTRY_CHARACTER = 0;
|
||||||
SDL_PropertiesID AKGL_REGISTRY_MUSIC;
|
SDL_PropertiesID AKGL_REGISTRY_MUSIC = 0;
|
||||||
SDL_PropertiesID AKGL_REGISTRY_FONT;
|
SDL_PropertiesID AKGL_REGISTRY_FONT = 0;
|
||||||
SDL_PropertiesID AKGL_REGISTRY_PROPERTIES;
|
SDL_PropertiesID AKGL_REGISTRY_PROPERTIES = 0;
|
||||||
|
|
||||||
akerr_ErrorContext *akgl_registry_init()
|
akerr_ErrorContext *akgl_registry_init()
|
||||||
{
|
{
|
||||||
@@ -39,7 +39,7 @@ akerr_ErrorContext *akgl_registry_init()
|
|||||||
akerr_ErrorContext *akgl_registry_init_actor()
|
akerr_ErrorContext *akgl_registry_init_actor()
|
||||||
{
|
{
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
if ( AKGL_REGISTRY_ACTOR != NULL ) {
|
if ( AKGL_REGISTRY_ACTOR != 0 ) {
|
||||||
SDL_DestroyProperties(AKGL_REGISTRY_ACTOR);
|
SDL_DestroyProperties(AKGL_REGISTRY_ACTOR);
|
||||||
}
|
}
|
||||||
AKGL_REGISTRY_ACTOR = SDL_CreateProperties();
|
AKGL_REGISTRY_ACTOR = SDL_CreateProperties();
|
||||||
|
|||||||
Reference in New Issue
Block a user