3 Commits

17 changed files with 409 additions and 197 deletions

View File

@@ -69,6 +69,8 @@ add_library(akgl SHARED
src/heap.c src/heap.c
src/json_helpers.c src/json_helpers.c
src/registry.c src/registry.c
src/renderer.c
src/physics.c
src/sprite.c src/sprite.c
src/staticstring.c src/staticstring.c
src/tilemap.c src/tilemap.c
@@ -142,6 +144,8 @@ install(FILES "include/akgl/controller.h" DESTINATION "include/akgl/")
install(FILES "include/akgl/heap.h" DESTINATION "include/akgl/") install(FILES "include/akgl/heap.h" DESTINATION "include/akgl/")
install(FILES "include/akgl/iterator.h" DESTINATION "include/akgl/") install(FILES "include/akgl/iterator.h" DESTINATION "include/akgl/")
install(FILES "include/akgl/json_helpers.h" DESTINATION "include/akgl/") install(FILES "include/akgl/json_helpers.h" DESTINATION "include/akgl/")
install(FILES "include/akgl/renderer.h" DESTINATION "include/akgl/")
install(FILES "include/akgl/physics.h" DESTINATION "include/akgl/")
install(FILES "include/akgl/registry.h" DESTINATION "include/akgl/") install(FILES "include/akgl/registry.h" DESTINATION "include/akgl/")
install(FILES "include/akgl/sprite.h" DESTINATION "include/akgl/") install(FILES "include/akgl/sprite.h" DESTINATION "include/akgl/")
install(FILES "include/akgl/staticstring.h" DESTINATION "include/akgl/") install(FILES "include/akgl/staticstring.h" DESTINATION "include/akgl/")

View File

@@ -1,9 +1,9 @@
#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 Tue May 26 01:00:21 PM EDT 2026 // Taken from https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/refs/heads/master/gamecontrollerdb.txt on Tue Jun 2 04:45:53 PM EDT 2026
#define AKGL_SDL_GAMECONTROLLER_DB_LEN 2228 #define AKGL_SDL_GAMECONTROLLER_DB_LEN 2229
const char *SDL_GAMECONTROLLER_DB[] = { const char *SDL_GAMECONTROLLER_DB[] = {
"03000000300f00000a01000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows", "03000000300f00000a01000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows",
@@ -708,7 +708,7 @@ const char *SDL_GAMECONTROLLER_DB[] = {
"03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows", "03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows",
"03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows", "03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows",
"030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows", "030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows",
"03000000632500002705000000000000,ShanWan Q36,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,righttrigger:b9,start:b11,x:b3,y:b4,platform:Windows", "03000000632500002705000000000000,ShanWan Gamepad,a:b0,b:b1,x:b3,y:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,-lefty:-a1,+lefty:+a2,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,righttrigger:b9,start:b11,leftstick:b13,rightstick:b14,platform:Windows",
"03000000f82100001900000000000000,Shogun Bros Chameleon X1,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows", "03000000f82100001900000000000000,Shogun Bros Chameleon X1,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows",
"03000000120c00001c1e000000000000,SnakeByte 4S PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows", "03000000120c00001c1e000000000000,SnakeByte 4S PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows",
"03000000140300000918000000000000,SNES Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows", "03000000140300000918000000000000,SNES Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows",
@@ -780,6 +780,7 @@ const char *SDL_GAMECONTROLLER_DB[] = {
"030000005f140000c501000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", "030000005f140000c501000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows",
"03000000b80500000210000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows", "03000000b80500000210000000000000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows",
"030000005f1400002a01000000000000,Trust Predator GM1200,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,x:b3,y:b4,platform:Windows", "030000005f1400002a01000000000000,Trust Predator GM1200,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,x:b3,y:b4,platform:Windows",
"03000000580400000a10000000000000,Trust Sight Fighter,a:b0,b:b1,x:b3,y:b4,back:b5,start:b2,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,lefttrigger:b8,righttrigger:b9,platform:Windows",
"030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows", "030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows",
"03000000411200000450000000000000,Twin Shock,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows", "03000000411200000450000000000000,Twin Shock,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows",
"03000000d90400000200000000000000,TwinShock PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows", "03000000d90400000200000000000000,TwinShock PS2 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows",

View File

@@ -76,16 +76,25 @@ typedef struct akgl_Actor {
float32_t vx; float32_t vx;
float32_t vy; float32_t vy;
float32_t vz; float32_t vz;
// Gravity. Forces acting on the actor on a given axis due to the forces // Environmental velocity. These are the forces acting on the actor by the
// of gravity and drag. // environment (such as gravity and atmospheric drag)
float32_t gx; float32_t ex;
float32_t gy; float32_t ey;
float32_t gz; float32_t ez;
// Thrust. Energy originating only from the actor's own acceleration on a // Thrust. Energy originating only from the actor's own acceleration on a
// given axis, before the effects of gravity and drag. // given axis, before the effects of gravity and drag.
float32_t tx; float32_t tx;
float32_t ty; float32_t ty;
float32_t tz; float32_t tz;
// Acceleration. These are borrowed from the base character object.
// A given axis resets to 0 when the actor stops moving in a given axis.
float32_t ax;
float32_t ay;
float32_t az;
// Max speed. These are borrowed from the base character object.
float32_t sx;
float32_t sy;
float32_t sz;
// Position. // Position.
float32_t x; float32_t x;
float32_t y; float32_t y;

View File

@@ -44,14 +44,19 @@ typedef struct {
} akgl_Game; } akgl_Game;
extern SDL_Window *window; extern SDL_Window *window;
extern akgl_Tilemap gamemap;
extern MIX_Audio *bgm; extern MIX_Audio *bgm;
extern MIX_Mixer *akgl_mixer; extern MIX_Mixer *akgl_mixer;
extern MIX_Track *akgl_tracks[AKGL_GAME_AUDIO_MAX_TRACKS]; extern MIX_Track *akgl_tracks[AKGL_GAME_AUDIO_MAX_TRACKS];
extern SDL_FRect camera; extern SDL_FRect _akgl_camera;
extern akgl_Game game; extern akgl_Game game;
extern akgl_RenderBackend renderer; extern akgl_RenderBackend _akgl_renderer;
extern akgl_PhysicsBackend physics; extern akgl_PhysicsBackend _akgl_physics;
extern akgl_Tilemap _akgl_gamemap;
extern akgl_Tilemap *gamemap;
extern akgl_RenderBackend *renderer;
extern akgl_PhysicsBackend *physics;
extern SDL_FRect *camera;
#define AKGL_BITMASK_HAS(x, y) (x & y) == y #define AKGL_BITMASK_HAS(x, y) (x & y) == y
#define AKGL_BITMASK_HASNOT(x, y) (x & y) != y #define AKGL_BITMASK_HASNOT(x, y) (x & y) != y

View File

@@ -8,10 +8,13 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_object_value(json_t *obj, char
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_boolean_value(json_t *obj, char *key, bool *dest); akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_boolean_value(json_t *obj, char *key, bool *dest);
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_integer_value(json_t *obj, char *key, int *dest); akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_integer_value(json_t *obj, char *key, int *dest);
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_number_value(json_t *obj, char *key, float *dest); akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_number_value(json_t *obj, char *key, float *dest);
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_double_value(json_t *obj, char *key, double *dest);
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_string_value(json_t *obj, char *key, akgl_String **dest); akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_string_value(json_t *obj, char *key, akgl_String **dest);
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_array_value(json_t *obj, char *key, json_t **dest); akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_array_value(json_t *obj, char *key, json_t **dest);
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_array_index_object(json_t *array, int index, json_t **dest); akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_array_index_object(json_t *array, int index, json_t **dest);
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_array_index_integer(json_t *array, int index, int *dest); akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_array_index_integer(json_t *array, int index, int *dest);
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_array_index_string(json_t *array, int index, akgl_String **dest); akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_array_index_string(json_t *array, int index, akgl_String **dest);
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_with_default(akerr_ErrorContext *e, void *defval, void *dest, uint32_t defsize);
#endif // _JSON_HELPERS_H_ #endif // _JSON_HELPERS_H_

View File

@@ -5,6 +5,7 @@
#include <akerror.h> #include <akerror.h>
#include <akgl/actor.h> #include <akgl/actor.h>
#include <akgl/iterator.h> #include <akgl/iterator.h>
#include <akgl/staticstring.h>
typedef struct akgl_PhysicsBackend { typedef struct akgl_PhysicsBackend {
akerr_ErrorContext AKERR_NOIGNORE *(*simulate)(struct akgl_PhysicsBackend *self, akgl_Iterator *opflags); akerr_ErrorContext AKERR_NOIGNORE *(*simulate)(struct akgl_PhysicsBackend *self, akgl_Iterator *opflags);
@@ -20,7 +21,6 @@ typedef struct akgl_PhysicsBackend {
double gravity_z; double gravity_z;
SDL_Time gravity_time; SDL_Time gravity_time;
SDL_Time timer_gravity; SDL_Time timer_gravity;
} akgl_PhysicsBackend; } akgl_PhysicsBackend;
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_gravity(akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt); akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_gravity(akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt);
@@ -29,11 +29,12 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_null_move(akgl_PhysicsBackend *s
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_init_null(akgl_PhysicsBackend *self); 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, float32_t dt); akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_arcade_gravity(akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt);
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_collide(akgl_PhysicsBackend *self, akgl_Actor *a1, akgl_Actor *a2); akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_arcade_collide(akgl_PhysicsBackend *self, akgl_Actor *a1, akgl_Actor *a2);
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_move(akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt); akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_arcade_move(akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt);
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_init_sidescroller(akgl_PhysicsBackend *self); akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_init_arcade(akgl_PhysicsBackend *self);
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_factory(akgl_PhysicsBackend *self, akgl_String *type);
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_simulate(akgl_PhysicsBackend *self, akgl_Iterator *opflags); akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_simulate(akgl_PhysicsBackend *self, akgl_Iterator *opflags);

View File

@@ -2,8 +2,9 @@
#define _TILEMAP_H_ #define _TILEMAP_H_
#include <limits.h> #include <limits.h>
#include "actor.h" #include <akgl/actor.h>
#include "staticstring.h" #include <akgl/staticstring.h>
#include <akgl/physics.h>
#include <jansson.h> #include <jansson.h>
#define AKGL_TILEMAP_MAX_WIDTH 512 #define AKGL_TILEMAP_MAX_WIDTH 512
@@ -98,6 +99,10 @@ typedef struct {
float p_rate; float p_rate;
akgl_Tileset tilesets[AKGL_TILEMAP_MAX_TILESETS]; akgl_Tileset tilesets[AKGL_TILEMAP_MAX_TILESETS];
akgl_TilemapLayer layers[AKGL_TILEMAP_MAX_LAYERS]; akgl_TilemapLayer layers[AKGL_TILEMAP_MAX_LAYERS];
// Different levels may have different physics.
bool use_own_physics;
akgl_PhysicsBackend physics;
} akgl_Tilemap; } akgl_Tilemap;
akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_load(char *fname, akgl_Tilemap *dest); akerr_ErrorContext AKERR_NOIGNORE *akgl_tilemap_load(char *fname, akgl_Tilemap *dest);

View File

@@ -51,6 +51,10 @@ akerr_ErrorContext *akgl_actor_set_character(akgl_Actor *obj, char *basecharname
obj->basechar = SDL_GetPointerProperty(AKGL_REGISTRY_CHARACTER, basecharname, NULL); obj->basechar = SDL_GetPointerProperty(AKGL_REGISTRY_CHARACTER, basecharname, NULL);
FAIL_ZERO_RETURN(errctx, obj->basechar, AKERR_NULLPOINTER, "Character not found in the registry"); FAIL_ZERO_RETURN(errctx, obj->basechar, AKERR_NULLPOINTER, "Character not found in the registry");
obj->ax = 0;
obj->ay = 0;
obj->sx = obj->basechar->sx;
obj->sy = obj->basechar->sy;
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
@@ -113,14 +117,25 @@ akerr_ErrorContext *akgl_actor_logic_changeframe(akgl_Actor *obj, akgl_Sprite *c
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
// raises AKGL_ERR_LOGICINTERRUPT if we don't want the physics object to process us // raises AKGL_ERR_LOGICINTERRUPT if we don't want the physics simulator to process us
akerr_ErrorContext *akgl_actor_logic_movement(akgl_Actor *obj, float32_t dt) akerr_ErrorContext *akgl_actor_logic_movement(akgl_Actor *actor, float32_t dt)
{ {
PREPARE_ERROR(errctx); PREPARE_ERROR(errctx);
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "obj"); FAIL_ZERO_RETURN(errctx, actor, AKERR_NULLPOINTER, "actor");
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "obj->basechar"); FAIL_ZERO_RETURN(errctx, actor, AKERR_NULLPOINTER, "actor->basechar");
// Effectively a NOOP, this is handled by the physics engine now actor->sx = actor->basechar->sx;
// These functions are still present in case the library user wants per-actor behavior actor->sy = actor->basechar->sy;
actor->sz = actor->basechar->sz;
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_LEFT) ) {
actor->ax = -actor->basechar->ax;
} else if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_RIGHT) ) {
actor->ax = actor->basechar->ax;
}
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_UP) ) {
actor->ay = -actor->basechar->ay;
} else if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_DOWN) ) {
actor->ay = actor->basechar->ay;
}
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
@@ -195,7 +210,7 @@ akerr_ErrorContext *akgl_actor_render(akgl_Actor *obj)
ATTEMPT { ATTEMPT {
CATCH(errctx, akgl_character_sprite_get(obj->basechar, obj->state, &curSprite)); CATCH(errctx, akgl_character_sprite_get(obj->basechar, obj->state, &curSprite));
CATCH(errctx, actor_visible(obj, &camera, &visible)); CATCH(errctx, actor_visible(obj, camera, &visible));
} CLEANUP { } CLEANUP {
} PROCESS(errctx) { } PROCESS(errctx) {
} HANDLE(errctx, AKERR_KEY) { } HANDLE(errctx, AKERR_KEY) {
@@ -227,16 +242,16 @@ akerr_ErrorContext *akgl_actor_render(akgl_Actor *obj)
} FINISH(errctx, true); } FINISH(errctx, true);
if ( obj->parent != NULL ) { if ( obj->parent != NULL ) {
dest.x = (obj->parent->x + obj->x - camera.x); dest.x = (obj->parent->x + obj->x - camera->x);
dest.y = (obj->parent->y + obj->y - camera.y); dest.y = (obj->parent->y + obj->y - camera->y);
} else { } else {
dest.x = (obj->x - camera.x); dest.x = (obj->x - camera->x);
dest.y = (obj->y - camera.y); dest.y = (obj->y - camera->y);
} }
dest.w = curSprite->width * obj->scale; dest.w = curSprite->width * obj->scale;
dest.h = curSprite->width * obj->scale; dest.h = curSprite->width * obj->scale;
PASS(errctx, renderer.draw_texture(&renderer, curSprite->sheet->texture, &src, &dest, 0, NULL, SDL_FLIP_NONE)); PASS(errctx, renderer->draw_texture(renderer, curSprite->sheet->texture, &src, &dest, 0, NULL, SDL_FLIP_NONE));
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
@@ -262,10 +277,12 @@ akerr_ErrorContext *akgl_actor_add_child(akgl_Actor *obj, akgl_Actor *child)
akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_left_on(akgl_Actor *obj, SDL_Event *event) akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_left_on(akgl_Actor *obj, SDL_Event *event)
{ {
PREPARE_ERROR(errctx); PREPARE_ERROR(errctx);
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL actor"); FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "actor");
FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "NULL event"); FAIL_ZERO_RETURN(errctx, event, AKERR_NULLPOINTER, "event");
FAIL_ZERO_RETURN(errctx, obj->basechar, AKERR_NULLPOINTER, "actor->basechar");
//SDL_Log("event %d (button %d / key %d) moves actor left", event->type, event->gbutton.which, event->key.key); //SDL_Log("event %d (button %d / key %d) moves actor left", event->type, event->gbutton.which, event->key.key);
AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_FACE_ALL | AKGL_ACTOR_STATE_MOVING_ALL)); AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_FACE_ALL | AKGL_ACTOR_STATE_MOVING_ALL));
obj->ax = -(obj->basechar->ax);
AKGL_BITMASK_ADD(obj->state, (AKGL_ACTOR_STATE_MOVING_LEFT | AKGL_ACTOR_STATE_FACE_LEFT)); AKGL_BITMASK_ADD(obj->state, (AKGL_ACTOR_STATE_MOVING_LEFT | AKGL_ACTOR_STATE_FACE_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);
@@ -277,6 +294,8 @@ 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->ax = 0;
obj->ex = 0;
obj->tx = 0; obj->tx = 0;
obj->vx = 0; obj->vx = 0;
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_LEFT); AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_LEFT);
@@ -289,7 +308,9 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_right_on(akgl_Actor *obj, SDL
PREPARE_ERROR(errctx); PREPARE_ERROR(errctx);
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");
FAIL_ZERO_RETURN(errctx, obj->basechar, AKERR_NULLPOINTER, "actor->basechar");
//SDL_Log("event %d (button %d / key %d) moves actor right", event->type, event->gbutton.which, event->key.key); //SDL_Log("event %d (button %d / key %d) moves actor right", event->type, event->gbutton.which, event->key.key);
obj->ax = obj->basechar->ax;
AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_FACE_ALL | AKGL_ACTOR_STATE_MOVING_ALL)); AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_FACE_ALL | AKGL_ACTOR_STATE_MOVING_ALL));
AKGL_BITMASK_ADD(obj->state, (AKGL_ACTOR_STATE_MOVING_RIGHT | AKGL_ACTOR_STATE_FACE_RIGHT)); AKGL_BITMASK_ADD(obj->state, (AKGL_ACTOR_STATE_MOVING_RIGHT | AKGL_ACTOR_STATE_FACE_RIGHT));
//SDL_Log("new target actor state: %b", obj->state); //SDL_Log("new target actor state: %b", obj->state);
@@ -302,6 +323,8 @@ 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->ax = 0;
obj->ex = 0;
obj->tx = 0; obj->tx = 0;
obj->vx = 0; obj->vx = 0;
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_RIGHT); AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_RIGHT);
@@ -315,6 +338,7 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_up_on(akgl_Actor *obj, SDL_Ev
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) moves actor up", event->type, event->gbutton.which, event->key.key); //SDL_Log("event %d (button %d / key %d) moves actor up", event->type, event->gbutton.which, event->key.key);
obj->ay = -(obj->basechar->ay);
AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_FACE_ALL | AKGL_ACTOR_STATE_MOVING_ALL)); AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_FACE_ALL | AKGL_ACTOR_STATE_MOVING_ALL));
AKGL_BITMASK_ADD(obj->state, (AKGL_ACTOR_STATE_FACE_UP | AKGL_ACTOR_STATE_MOVING_UP)); AKGL_BITMASK_ADD(obj->state, (AKGL_ACTOR_STATE_FACE_UP | AKGL_ACTOR_STATE_MOVING_UP));
//SDL_Log("new target actor state: %b", obj->state); //SDL_Log("new target actor state: %b", obj->state);
@@ -327,6 +351,8 @@ 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->ay = 0;
obj->ey = 0;
obj->ty = 0; obj->ty = 0;
obj->vy = 0; obj->vy = 0;
AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_UP); AKGL_BITMASK_DEL(obj->state, AKGL_ACTOR_STATE_MOVING_UP);
@@ -340,6 +366,7 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_down_on(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) moves actor down", event->type, event->gbutton.which, event->key.key); //SDL_Log("event %d (button %d / key %d) moves actor down", event->type, event->gbutton.which, event->key.key);
obj->ay = obj->basechar->ay;
AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_FACE_ALL | AKGL_ACTOR_STATE_MOVING_ALL)); AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_FACE_ALL | AKGL_ACTOR_STATE_MOVING_ALL));
AKGL_BITMASK_ADD(obj->state, (AKGL_ACTOR_STATE_MOVING_DOWN | AKGL_ACTOR_STATE_FACE_DOWN)); AKGL_BITMASK_ADD(obj->state, (AKGL_ACTOR_STATE_MOVING_DOWN | AKGL_ACTOR_STATE_FACE_DOWN));
//SDL_Log("new target actor state: %b", obj->state); //SDL_Log("new target actor state: %b", obj->state);
@@ -353,6 +380,8 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_Actor_cmhf_down_off(akgl_Actor *obj, SDL
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->ty = 0; obj->ty = 0;
obj->ey = 0;
obj->ay = 0;
obj->vy = 0; 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);

View File

@@ -20,11 +20,11 @@ void akgl_draw_background(int w, int h)
for (x = 0; x < w; x += dx) { for (x = 0; x < w; x += dx) {
/* use an 8x8 checkerboard pattern */ /* use an 8x8 checkerboard pattern */
i = (((x ^ y) >> 3) & 1); i = (((x ^ y) >> 3) & 1);
SDL_SetRenderDrawColor(renderer.sdl_renderer, col[i].r, col[i].g, col[i].b, col[i].a); SDL_SetRenderDrawColor(renderer->sdl_renderer, col[i].r, col[i].g, col[i].b, col[i].a);
rect.x = (float)x; rect.x = (float)x;
rect.y = (float)y; rect.y = (float)y;
SDL_RenderFillRect(renderer.sdl_renderer, &rect); SDL_RenderFillRect(renderer->sdl_renderer, &rect);
} }
} }
} }

View File

@@ -19,17 +19,22 @@
#include <akgl/SDL_GameControllerDB.h> #include <akgl/SDL_GameControllerDB.h>
SDL_Window *window = NULL; SDL_Window *window = NULL;
akgl_RenderBackend renderer;
akgl_PhysicsBackend physics; // Currently active objects
akgl_Frame ball; akgl_RenderBackend *renderer;
akgl_Frame paddle1; akgl_PhysicsBackend *physics;
akgl_Frame paddle2; SDL_FRect *camera;
akgl_Frame table; akgl_Tilemap *gamemap;
akgl_Tilemap gamemap;
// Default objects
akgl_RenderBackend _akgl_renderer;
akgl_PhysicsBackend _akgl_physics;
SDL_FRect _akgl_camera;
akgl_Tilemap _akgl_gamemap;
MIX_Audio *bgm = NULL; MIX_Audio *bgm = NULL;
MIX_Mixer *akgl_mixer = NULL; MIX_Mixer *akgl_mixer = NULL;
MIX_Track *akgl_tracks[AKGL_GAME_AUDIO_MAX_TRACKS]; MIX_Track *akgl_tracks[AKGL_GAME_AUDIO_MAX_TRACKS];
SDL_FRect camera;
akgl_Game game; akgl_Game game;
void akgl_game_lowfps(void) void akgl_game_lowfps(void)
@@ -45,31 +50,26 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_game_init()
int i = 0; int i = 0;
PREPARE_ERROR(e); PREPARE_ERROR(e);
ATTEMPT { strncpy((char *)&game.libversion, AKGL_VERSION, 32);
strncpy((char *)&game.libversion, AKGL_VERSION, 32); game.gameStartTime = SDL_GetTicksNS();
game.gameStartTime = SDL_GetTicksNS(); game.lastIterTime = game.gameStartTime;
game.lastIterTime = game.gameStartTime; game.lastFPSTime = game.gameStartTime;
game.lastFPSTime = game.gameStartTime; game.lowfpsfunc = &akgl_game_lowfps;
game.lowfpsfunc = &akgl_game_lowfps; game.statelock = SDL_CreateMutex();
game.statelock = SDL_CreateMutex(); FAIL_ZERO_RETURN(e, game.statelock, AKGL_ERR_SDL, "%s", SDL_GetError());
FAIL_ZERO_RETURN(e, game.statelock, AKGL_ERR_SDL, "%s", SDL_GetError()); PASS(e, akgl_game_state_lock());
CATCH(e, akgl_game_state_lock()); FAIL_ZERO_RETURN(e, strlen((char *)&game.name), AKERR_NULLPOINTER, "Must provide game name");
FAIL_ZERO_BREAK(e, strlen((char *)&game.name), AKERR_NULLPOINTER, "Must provide game name"); FAIL_ZERO_RETURN(e, strlen((char *)&game.version), AKERR_NULLPOINTER, "Must provide game version");
FAIL_ZERO_BREAK(e, strlen((char *)&game.version), AKERR_NULLPOINTER, "Must provide game version"); FAIL_ZERO_RETURN(e, strlen((char *)&game.uri), AKERR_NULLPOINTER, "Must provide game uri");
FAIL_ZERO_BREAK(e, strlen((char *)&game.uri), AKERR_NULLPOINTER, "Must provide game uri"); PASS(e, akgl_heap_init());
CATCH(e, akgl_heap_init()); PASS(e, akgl_registry_init_actor());
CATCH(e, akgl_registry_init_actor()); PASS(e, akgl_registry_init_sprite());
CATCH(e, akgl_registry_init_sprite()); PASS(e, akgl_registry_init_spritesheet());
CATCH(e, akgl_registry_init_spritesheet()); PASS(e, akgl_registry_init_character());
CATCH(e, akgl_registry_init_character()); PASS(e, akgl_registry_init_font());
CATCH(e, akgl_registry_init_font()); PASS(e, akgl_registry_init_music());
CATCH(e, akgl_registry_init_music()); PASS(e, akgl_registry_init_properties());
CATCH(e, akgl_registry_init_properties()); PASS(e, akgl_registry_init_actor_state_strings());
CATCH(e, akgl_registry_init_actor_state_strings());
} CLEANUP {
//IGNORE(akgl_game_state_unlock());
} PROCESS(e) {
} FINISH(e, true)
SDL_SetAppMetadata(game.name, game.version, game.uri); SDL_SetAppMetadata(game.name, game.version, game.uri);
@@ -113,6 +113,12 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_game_init()
AKGL_ERR_SDL, AKGL_ERR_SDL,
"Couldn't initialize front engine: %s", "Couldn't initialize front engine: %s",
SDL_GetError()); SDL_GetError());
camera = &_akgl_camera;
renderer = &_akgl_renderer;
physics = &_akgl_physics;
gamemap = &_akgl_gamemap;
PASS(e, akgl_game_state_unlock()); PASS(e, akgl_game_state_unlock());
SUCCEED_RETURN(e); SUCCEED_RETURN(e);
} }
@@ -432,15 +438,15 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_game_update(akgl_Iterator *opflags)
continue; continue;
} }
if ( AKGL_BITMASK_HAS(opflags->flags, AKGL_ITERATOR_OP_TILEMAPSCALE) ) { if ( AKGL_BITMASK_HAS(opflags->flags, AKGL_ITERATOR_OP_TILEMAPSCALE) ) {
PASS(e, akgl_tilemap_scale_actor(&gamemap, actor)); PASS(e, akgl_tilemap_scale_actor(gamemap, actor));
} else { } else {
actor->scale = 1.0; actor->scale = 1.0;
} }
PASS(e, actor->updatefunc(actor)); PASS(e, actor->updatefunc(actor));
} }
} }
PASS(e, physics.simulate(&physics, NULL)); PASS(e, physics->simulate(physics, NULL));
PASS(e, renderer.draw_world(&renderer, NULL)); PASS(e, renderer->draw_world(renderer, NULL));
PASS(e, akgl_game_state_unlock()); PASS(e, akgl_game_state_unlock());
SUCCEED_RETURN(e); SUCCEED_RETURN(e);
} }

View File

@@ -52,6 +52,17 @@ akerr_ErrorContext *akgl_get_json_number_value(json_t *obj, char *key, float *de
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_double_value(json_t *obj, char *key, double *dest)
{
PREPARE_ERROR(errctx);
FAIL_ZERO_RETURN(errctx, obj, AKERR_NULLPOINTER, "NULL pointer reference");
json_t *value = json_object_get(obj, key);
FAIL_ZERO_RETURN(errctx, value, AKERR_KEY, "Key %s not found in object", key);
FAIL_ZERO_RETURN(errctx, (json_is_number(value)), AKERR_TYPE, "Key %s in object has incorrect type", key);
*dest = json_number_value(value);
SUCCEED_RETURN(errctx);
}
akerr_ErrorContext *akgl_get_json_string_value(json_t *obj, char *key, akgl_String **dest) akerr_ErrorContext *akgl_get_json_string_value(json_t *obj, char *key, akgl_String **dest)
{ {
json_t *value = NULL; json_t *value = NULL;
@@ -129,3 +140,26 @@ akerr_ErrorContext *akgl_get_json_array_index_string(json_t *array, int index, a
strncpy((char *)&(*dest)->data, json_string_value(value), AKGL_MAX_STRING_LENGTH); strncpy((char *)&(*dest)->data, json_string_value(value), AKGL_MAX_STRING_LENGTH);
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
akerr_ErrorContext AKERR_NOIGNORE *akgl_get_json_with_default(akerr_ErrorContext *err, void *defval, void *dest, uint32_t defsize)
{
PREPARE_ERROR(e);
if ( err == NULL ) {
SUCCEED_RETURN(e);
}
int docopy = 0;
FAIL_ZERO_RETURN(e, err, AKERR_NULLPOINTER, "err");
FAIL_ZERO_RETURN(e, defval, AKERR_NULLPOINTER, "defval");
FAIL_ZERO_RETURN(e, dest, AKERR_NULLPOINTER, "dest");
ATTEMPT {
} CLEANUP {
} PROCESS(err) {
} HANDLE_GROUP(err, AKERR_KEY) {
} HANDLE_GROUP(err, AKERR_INDEX) {
memcpy(dest, defval, defsize);
} FINISH(err, true);
SUCCEED_RETURN(e);
}

View File

@@ -1,3 +1,4 @@
#include <math.h>
#include <akstdlib.h> #include <akstdlib.h>
#include <akgl/physics.h> #include <akgl/physics.h>
#include <akgl/actor.h> #include <akgl/actor.h>
@@ -41,28 +42,29 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_init_null(akgl_PhysicsBackend *s
} }
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_gravity(akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt) akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_arcade_gravity(akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt)
{ {
PREPARE_ERROR(e); PREPARE_ERROR(e);
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self"); FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
FAIL_ZERO_RETURN(e, actor, AKERR_NULLPOINTER, "actor"); FAIL_ZERO_RETURN(e, actor, AKERR_NULLPOINTER, "actor");
// Assume the X origin is - (screen left) if ( self->gravity_x != 0 ) {
actor->gx -= (self->gravity_x * dt); // Assume the X origin is - (screen left)
// Assume Y origin is + (down screen) actor->ex -= (self->gravity_x * dt);
actor->gy += (self->gravity_y * dt); }
// Assume Z origin is - (behind the camera) if ( self->gravity_y != 0 ) {
actor->gz -= (self->gravity_z * dt); // Assume Y origin is + (down screen)
actor->ey += (self->gravity_y * dt);
// Counteract velocity with atmospheric drag }
actor->gx += actor->vx * self->drag_x * dt; if ( self->gravity_z != 0 ) {
actor->gy -= actor->vy * self->drag_y * dt; // Assume Z origin is - (behind the camera)
actor->gz += actor->vz * self->drag_z * dt; actor->ez -= (self->gravity_z * dt);
}
SUCCEED_RETURN(e); SUCCEED_RETURN(e);
} }
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_collide(akgl_PhysicsBackend *self, akgl_Actor *a1, akgl_Actor *a2) akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_arcade_collide(akgl_PhysicsBackend *self, akgl_Actor *a1, akgl_Actor *a2)
{ {
PREPARE_ERROR(e); PREPARE_ERROR(e);
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self"); FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
@@ -70,37 +72,27 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_collide(akgl_PhysicsBackend *
SUCCEED_RETURN(e); SUCCEED_RETURN(e);
} }
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_ss_move(struct akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt) akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_arcade_move(struct akgl_PhysicsBackend *self, akgl_Actor *actor, float32_t dt)
{ {
PREPARE_ERROR(e); PREPARE_ERROR(e);
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self"); FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
FAIL_ZERO_RETURN(e, actor, AKERR_NULLPOINTER, "actor"); FAIL_ZERO_RETURN(e, actor, AKERR_NULLPOINTER, "actor");
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_LEFT) ) { actor->x += actor->vx * dt;
actor->x += (-actor->vx * dt) + (actor->gx * dt); actor->y += actor->vy * dt;
} actor->z += actor->vz * dt;
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_RIGHT) ) {
actor->x += (actor->vx * dt) + (actor->gx * dt);
}
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_UP) ) {
actor->y += (-actor->vy * dt) + (actor->gy * dt);
}
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_DOWN) ) {
actor->y += (actor->vy * dt) + (actor->gy * dt);
}
SUCCEED_RETURN(e); SUCCEED_RETURN(e);
} }
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_init_sidescroller(akgl_PhysicsBackend *self) akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_init_arcade(akgl_PhysicsBackend *self)
{ {
akgl_String *tmp; akgl_String *tmp;
PREPARE_ERROR(e); PREPARE_ERROR(e);
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self"); FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
PASS(e, akgl_heap_next_string(&tmp)); PASS(e, akgl_heap_next_string(&tmp));
self->gravity = akgl_physics_ss_gravity; self->gravity = akgl_physics_arcade_gravity;
self->collide = akgl_physics_ss_collide; self->collide = akgl_physics_arcade_collide;
self->move = akgl_physics_ss_move; self->move = akgl_physics_arcade_move;
self->simulate = akgl_physics_simulate; self->simulate = akgl_physics_simulate;
ATTEMPT { ATTEMPT {
@@ -150,6 +142,9 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_simulate(akgl_PhysicsBackend *se
} }
if ( actor->parent != NULL ) { if ( actor->parent != NULL ) {
// Children don't move independently of their parents, they just have an offset // Children don't move independently of their parents, they just have an offset
actor->x = actor->parent->x + actor->vx;
actor->y = actor->parent->y + actor->vy;
actor->z = actor->parent->z + actor->vz;
continue; continue;
} else if ( actor->basechar == NULL ) { } else if ( actor->basechar == NULL ) {
continue; continue;
@@ -159,28 +154,58 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_simulate(akgl_PhysicsBackend *se
continue; continue;
} }
} }
// thrust is a function of acceleration on a given axis
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_LEFT) || if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_LEFT) ||
AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_RIGHT) ) { AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_RIGHT) ) {
actor->tx += actor->basechar->ax * dt; actor->tx += actor->ax * dt;
} }
if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_UP) || if ( AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_UP) ||
AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_DOWN) ) { AKGL_BITMASK_HAS(actor->state, AKGL_ACTOR_STATE_MOVING_DOWN) ) {
actor->ty += actor->basechar->ay * dt; actor->ty += actor->ay * dt;
} }
// velocity equals thrust unless thrust exceeds max speed // velocity equals thrust unless thrust exceeds max speed
if ( actor->tx > actor->basechar->sx ) { if ( fabsf(actor->tx) > fabsf(actor->sx) ) {
actor->vx = actor->basechar->sx; if ( actor->tx < 0 ) {
} else { actor->tx = -actor->sx;
actor->vx = actor->tx; } else {
actor->tx = actor->sx;
}
} }
if ( actor->ty > actor->basechar->sy ) { if ( fabsf(actor->ty) > fabsf(actor->sy) ) {
actor->vy = actor->basechar->sy; if ( actor->ty < 0 ) {
} else { actor->ty = -actor->sy;
actor->vy = actor->ty; } else {
actor->ty = actor->sy;
}
}
if ( fabsf(actor->tz) > fabsf(actor->sz) ) {
if ( actor->tz < 0 ) {
actor->tz = -actor->sz;
} else {
actor->tz = actor->sz;
}
} }
ATTEMPT { ATTEMPT {
CATCH(e, actor->movementlogicfunc(actor, dt)); CATCH(e, actor->movementlogicfunc(actor, dt));
PASS(e, self->gravity(self, actor, dt)); PASS(e, self->gravity(self, actor, dt));
// Counteract velocity with atmospheric drag
if ( self->drag_x != 0 ) {
actor->ex -= actor->ex * self->drag_x * dt;
}
if ( self->drag_y != 0 ) {
actor->ey -= actor->ey * self->drag_y * dt;
}
if ( self->drag_z != 0 ) {
actor->ez -= actor->ez * self->drag_z * dt;
}
actor->vx = actor->ex + actor->tx;
actor->vy = actor->ey + actor->ty;
actor->vz = actor->ez + actor->tz;
PASS(e, self->move(self, actor, dt)); PASS(e, self->move(self, actor, dt));
} CLEANUP { } CLEANUP {
} PROCESS(e) { } PROCESS(e) {
@@ -191,3 +216,21 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_simulate(akgl_PhysicsBackend *se
self->gravity_time = curtime; self->gravity_time = curtime;
SUCCEED_RETURN(e); SUCCEED_RETURN(e);
} }
akerr_ErrorContext AKERR_NOIGNORE *akgl_physics_factory(akgl_PhysicsBackend *self, akgl_String *type)
{
uint32_t hashval;
PREPARE_ERROR(e);
FAIL_ZERO_RETURN(e, self, AKERR_NULLPOINTER, "self");
FAIL_ZERO_RETURN(e, type, AKERR_NULLPOINTER, "type");
if ( strncmp(type->data, "null", 4) == 0) {
PASS(e, akgl_physics_init_null(self));
SUCCEED_RETURN(e);
}
if ( strncmp(type->data, "arcade", 6) == 0) {
PASS(e, akgl_physics_init_arcade(self));
SUCCEED_RETURN(e);
}
FAIL_RETURN(e, AKERR_KEY, "Invalid physics engine %s", type->data);
}

View File

@@ -33,10 +33,10 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_render_init2d(akgl_RenderBackend *self)
"Couldn't create window/renderer: %s", "Couldn't create window/renderer: %s",
SDL_GetError()); SDL_GetError());
camera.x = 0; camera->x = 0;
camera.y = 0; camera->y = 0;
camera.w = screenwidth; camera->w = screenwidth;
camera.h = screenheight; camera->h = screenheight;
self->shutdown = &akgl_render_2d_shutdown; self->shutdown = &akgl_render_2d_shutdown;
self->frame_start = &akgl_render_2d_frame_start; self->frame_start = &akgl_render_2d_frame_start;
@@ -117,8 +117,8 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_render_2d_draw_world(akgl_RenderBackend
PASS(e, aksl_memset((void *)opflags, 0x00, sizeof(akgl_Iterator))); PASS(e, aksl_memset((void *)opflags, 0x00, sizeof(akgl_Iterator)));
} }
for ( int i = 0; i < AKGL_TILEMAP_MAX_LAYERS ; i++ ) { for ( int i = 0; i < AKGL_TILEMAP_MAX_LAYERS ; i++ ) {
if ( i < gamemap.numlayers ) { if ( i < gamemap->numlayers ) {
PASS(e, akgl_tilemap_draw((akgl_Tilemap *)&gamemap, &camera, i)); PASS(e, akgl_tilemap_draw(gamemap, camera, i));
} }
for ( int j = 0; j < AKGL_MAX_HEAP_ACTOR ; j++ ) { for ( int j = 0; j < AKGL_MAX_HEAP_ACTOR ; j++ ) {
actor = &HEAP_ACTOR[j]; actor = &HEAP_ACTOR[j];

View File

@@ -174,7 +174,7 @@ akerr_ErrorContext *akgl_spritesheet_initialize(akgl_SpriteSheet *sheet, int spr
strncpy((char *)&sheet->name, filename, AKGL_SPRITE_SHEET_MAX_FILENAME_LENGTH); strncpy((char *)&sheet->name, filename, AKGL_SPRITE_SHEET_MAX_FILENAME_LENGTH);
//snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), filename); //snprintf((char *)&tmpstr->data, AKGL_MAX_STRING_LENGTH, "%s%s", SDL_GetBasePath(), filename);
sheet->texture = IMG_LoadTexture(renderer.sdl_renderer, filename); sheet->texture = IMG_LoadTexture(renderer->sdl_renderer, filename);
FAIL_ZERO_BREAK(errctx, sheet->texture, AKGL_ERR_SDL, "Failed loading asset %s : %s", filename, SDL_GetError()); FAIL_ZERO_BREAK(errctx, sheet->texture, AKGL_ERR_SDL, "Failed loading asset %s : %s", filename, SDL_GetError());
FAIL_ZERO_BREAK( FAIL_ZERO_BREAK(

View File

@@ -49,12 +49,12 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_text_rendertextat(TTF_Font *font, char *
color); color);
} }
FAIL_ZERO_RETURN(errctx, textsurf, AKERR_NULLPOINTER, "%s", SDL_GetError()); FAIL_ZERO_RETURN(errctx, textsurf, AKERR_NULLPOINTER, "%s", SDL_GetError());
texture = SDL_CreateTextureFromSurface(renderer.sdl_renderer, textsurf); texture = SDL_CreateTextureFromSurface(renderer->sdl_renderer, textsurf);
FAIL_ZERO_RETURN(errctx, texture, AKERR_NULLPOINTER, "%s", SDL_GetError()); FAIL_ZERO_RETURN(errctx, texture, AKERR_NULLPOINTER, "%s", SDL_GetError());
dest.x = x; dest.x = x;
dest.y = y; dest.y = y;
SDL_GetTextureSize(texture, &dest.w, &dest.h); SDL_GetTextureSize(texture, &dest.w, &dest.h);
PASS(errctx, renderer.draw_texture(&renderer, texture, NULL, &dest, 0, NULL, SDL_FLIP_NONE)); PASS(errctx, renderer->draw_texture(renderer, texture, NULL, &dest, 0, NULL, SDL_FLIP_NONE));
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
SDL_DestroySurface(textsurf); SDL_DestroySurface(textsurf);
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);

View File

@@ -64,14 +64,10 @@ akerr_ErrorContext *akgl_get_json_properties_string(json_t *obj, char *key, akgl
PREPARE_ERROR(errctx); PREPARE_ERROR(errctx);
json_t *property; json_t *property;
ATTEMPT { PASS(errctx, akgl_get_json_tilemap_property(obj, key, "string", &property));
CATCH(errctx, akgl_get_json_tilemap_property(obj, key, "string", &property)); PASS(errctx, akgl_heap_next_string(dest));
CATCH(errctx, akgl_heap_next_string(dest)); PASS(errctx, akgl_string_initialize(*dest, NULL));
CATCH(errctx, akgl_string_initialize(*dest, NULL)); PASS(errctx, akgl_get_json_string_value(property, "value", dest));
CATCH(errctx, akgl_get_json_string_value(property, "value", dest));
} CLEANUP {
} PROCESS(errctx) {
} FINISH(errctx, true);
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
@@ -80,12 +76,8 @@ akerr_ErrorContext *akgl_get_json_properties_integer(json_t *obj, char *key, int
{ {
PREPARE_ERROR(errctx); PREPARE_ERROR(errctx);
json_t *property = NULL; json_t *property = NULL;
ATTEMPT { PASS(errctx, akgl_get_json_tilemap_property(obj, key, "int", &property));
CATCH(errctx, akgl_get_json_tilemap_property(obj, key, "int", &property)); PASS(errctx, akgl_get_json_integer_value(property, "value", dest));
CATCH(errctx, akgl_get_json_integer_value(property, "value", dest));
} CLEANUP {
} PROCESS(errctx) {
} FINISH(errctx, true);
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
@@ -94,12 +86,8 @@ akerr_ErrorContext *akgl_get_json_properties_number(json_t *obj, char *key, floa
{ {
PREPARE_ERROR(errctx); PREPARE_ERROR(errctx);
json_t *property = NULL; json_t *property = NULL;
ATTEMPT { PASS(errctx, akgl_get_json_tilemap_property(obj, key, "number", &property));
CATCH(errctx, akgl_get_json_tilemap_property(obj, key, "number", &property)); PASS(errctx, akgl_get_json_number_value(property, "value", dest));
CATCH(errctx, akgl_get_json_number_value(property, "value", dest));
} CLEANUP {
} PROCESS(errctx) {
} FINISH(errctx, true);
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
@@ -108,12 +96,18 @@ akerr_ErrorContext *akgl_get_json_properties_float(json_t *obj, char *key, float
{ {
PREPARE_ERROR(errctx); PREPARE_ERROR(errctx);
json_t *property = NULL; json_t *property = NULL;
ATTEMPT { PASS(errctx, akgl_get_json_tilemap_property(obj, key, "float", &property));
CATCH(errctx, akgl_get_json_tilemap_property(obj, key, "float", &property)); PASS(errctx, akgl_get_json_number_value(property, "value", dest));
CATCH(errctx, akgl_get_json_number_value(property, "value", dest));
} CLEANUP { SUCCEED_RETURN(errctx);
} PROCESS(errctx) { }
} FINISH(errctx, true);
akerr_ErrorContext *akgl_get_json_properties_double(json_t *obj, char *key, double *dest)
{
PREPARE_ERROR(errctx);
json_t *property = NULL;
PASS(errctx, akgl_get_json_tilemap_property(obj, key, "float", &property));
PASS(errctx, akgl_get_json_double_value(property, "value", dest));
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
@@ -152,7 +146,7 @@ akerr_ErrorContext *akgl_tilemap_load_tilesets_each(json_t *tileset, akgl_Tilema
} PROCESS(e) { } PROCESS(e) {
} FINISH(e, true); } FINISH(e, true);
dest->tilesets[tsidx].texture = IMG_LoadTexture(renderer.sdl_renderer, (char *)&dest->tilesets[tsidx].imagefilename); dest->tilesets[tsidx].texture = IMG_LoadTexture(renderer->sdl_renderer, (char *)&dest->tilesets[tsidx].imagefilename);
FAIL_ZERO_RETURN(e, dest->tilesets[tsidx].texture, AKERR_NULLPOINTER, "Failed loading tileset image : %s", SDL_GetError()); FAIL_ZERO_RETURN(e, dest->tilesets[tsidx].texture, AKERR_NULLPOINTER, "Failed loading tileset image : %s", SDL_GetError());
SUCCEED_RETURN(e); SUCCEED_RETURN(e);
@@ -297,41 +291,36 @@ akerr_ErrorContext *akgl_tilemap_load_layer_objects(akgl_Tilemap *dest, json_t *
FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "NULL destination tilemap reference"); FAIL_ZERO_RETURN(errctx, dest, AKERR_NULLPOINTER, "NULL destination tilemap reference");
FAIL_ZERO_RETURN(errctx, root, AKERR_NULLPOINTER, "NULL tilemap root reference"); FAIL_ZERO_RETURN(errctx, root, AKERR_NULLPOINTER, "NULL tilemap root reference");
ATTEMPT { PASS(errctx, akgl_get_json_array_value(root, "objects", &layerdata));
CATCH(errctx, akgl_get_json_array_value(root, "objects", &layerdata)); len = json_array_size((json_t *)layerdata);
len = json_array_size((json_t *)layerdata); curlayer = &dest->layers[layerid];
curlayer = &dest->layers[layerid]; for ( j = 0; j < len; j++ ) {
for ( j = 0; j < len; j++ ) { PASS(errctx, akgl_get_json_array_index_object((json_t *)layerdata, j, &layerdatavalue));
CATCH(errctx, akgl_get_json_array_index_object((json_t *)layerdata, j, &layerdatavalue)); curobj = &curlayer->objects[j];
curobj = &curlayer->objects[j]; PASS(errctx, akgl_get_json_string_value((json_t *)layerdatavalue, "name", &tmpstr));
CATCH(errctx, akgl_get_json_string_value((json_t *)layerdatavalue, "name", &tmpstr)); strncpy((char *)curobj->name, tmpstr->data, AKGL_ACTOR_MAX_NAME_LENGTH);
strncpy((char *)curobj->name, tmpstr->data, AKGL_ACTOR_MAX_NAME_LENGTH); PASS(errctx, akgl_heap_release_string(tmpstr));
CATCH(errctx, akgl_heap_release_string(tmpstr)); PASS(errctx, akgl_get_json_number_value((json_t *)layerdatavalue, "x", &curobj->x));
CATCH(errctx, akgl_get_json_number_value((json_t *)layerdatavalue, "x", &curobj->x)); PASS(errctx, akgl_get_json_number_value((json_t *)layerdatavalue, "y", &curobj->y));
CATCH(errctx, akgl_get_json_number_value((json_t *)layerdatavalue, "y", &curobj->y)); PASS(errctx, akgl_get_json_boolean_value((json_t *)layerdatavalue, "visible", &curobj->visible));
CATCH(errctx, akgl_get_json_boolean_value((json_t *)layerdatavalue, "visible", &curobj->visible));
CATCH(errctx, akgl_get_json_string_value((json_t *)layerdatavalue, "type", &tmpstr)); PASS(errctx, akgl_get_json_string_value((json_t *)layerdatavalue, "type", &tmpstr));
if ( strcmp(tmpstr->data, "actor") == 0 ) { if ( strcmp(tmpstr->data, "actor") == 0 ) {
CATCH(errctx, akgl_tilemap_load_layer_object_actor(curobj, layerdatavalue, layerid, dirname)); PASS(errctx, akgl_tilemap_load_layer_object_actor(curobj, layerdatavalue, layerid, dirname));
} else if ( strcmp(tmpstr->data, "perspective") == 0 ) { } else if ( strcmp(tmpstr->data, "perspective") == 0 ) {
curobj->visible = false; curobj->visible = false;
if ( strcmp((char *)curobj->name, "p_foreground") == 0 ) { if ( strcmp((char *)curobj->name, "p_foreground") == 0 ) {
dest->p_foreground_y = curobj->y; dest->p_foreground_y = curobj->y;
CATCH(errctx, akgl_get_json_integer_value((json_t *)layerdatavalue, "height", &dest->p_foreground_h)); PASS(errctx, akgl_get_json_integer_value((json_t *)layerdatavalue, "height", &dest->p_foreground_h));
CATCH(errctx, akgl_get_json_properties_float((json_t *)layerdatavalue, "scale", &dest->p_foreground_scale)); PASS(errctx, akgl_get_json_properties_float((json_t *)layerdatavalue, "scale", &dest->p_foreground_scale));
} else if ( strcmp((char *)curobj->name, "p_vanishing") == 0 ) { } else if ( strcmp((char *)curobj->name, "p_vanishing") == 0 ) {
dest->p_vanishing_y = curobj->y; dest->p_vanishing_y = curobj->y;
CATCH(errctx, akgl_get_json_integer_value((json_t *)layerdatavalue, "height", &dest->p_vanishing_h)); PASS(errctx, akgl_get_json_integer_value((json_t *)layerdatavalue, "height", &dest->p_vanishing_h));
CATCH(errctx, akgl_get_json_properties_float((json_t *)layerdatavalue, "scale", &dest->p_vanishing_scale)); PASS(errctx, akgl_get_json_properties_float((json_t *)layerdatavalue, "scale", &dest->p_vanishing_scale));
}
} }
layerdatavalue = NULL;
} }
} CLEANUP { layerdatavalue = NULL;
} PROCESS(errctx) { }
} FINISH(errctx, true);
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
@@ -389,7 +378,7 @@ akerr_ErrorContext *akgl_tilemap_load_layer_image(akgl_Tilemap *dest, json_t *ro
); );
RESTORE_GCC_WARNINGS RESTORE_GCC_WARNINGS
dest->layers[layerid].texture = IMG_LoadTexture(renderer.sdl_renderer, (char *)fpath->data); dest->layers[layerid].texture = IMG_LoadTexture(renderer->sdl_renderer, (char *)fpath->data);
FAIL_ZERO_BREAK(errctx, dest->layers[layerid].texture, AKGL_ERR_SDL, "%s", SDL_GetError()); FAIL_ZERO_BREAK(errctx, dest->layers[layerid].texture, AKGL_ERR_SDL, "%s", SDL_GetError());
dest->layers[layerid].width = dest->layers[layerid].texture->w; dest->layers[layerid].width = dest->layers[layerid].texture->w;
dest->layers[layerid].height = dest->layers[layerid].texture->h; dest->layers[layerid].height = dest->layers[layerid].texture->h;
@@ -451,6 +440,88 @@ akerr_ErrorContext *akgl_tilemap_load_layers(akgl_Tilemap *dest, json_t *root, a
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
akerr_ErrorContext *akgl_tilemap_load_physics(akgl_Tilemap *dest, json_t *root)
{
PREPARE_ERROR(e);
json_t *props = NULL;
akgl_String *tmpval = NULL;
double defzero = 0.0;
ATTEMPT {
CATCH(e, akgl_heap_next_string(&tmpval));
CATCH(e, akgl_get_json_array_value((json_t *)root, "properties", &props));
} CLEANUP {
IGNORE(akgl_heap_release_string(tmpval));
} PROCESS(e) {
} HANDLE(e, AKERR_KEY) {
// Map has no properties, do nothing
SDL_Log("Map has no properties");
SUCCEED_RETURN(e);
} FINISH(e, true);
ATTEMPT {
CATCH(e, akgl_heap_next_string(&tmpval));
CATCH(e, akgl_get_json_properties_string(
root,
"physics.model",
&tmpval
)
);
PASS(e, akgl_physics_factory(&dest->physics, tmpval));
dest->use_own_physics = true;
CATCH(e, akgl_get_json_with_default(
akgl_get_json_properties_double(
root, "physics.gravity.x", &dest->physics.gravity_x
),
(void *)&defzero,
(void *)&dest->physics.gravity_x,
sizeof(double)));
CATCH(e, akgl_get_json_with_default(
akgl_get_json_properties_double(
root, "physics.gravity.y", &dest->physics.gravity_y
),
(void *)&defzero,
(void *)&dest->physics.gravity_y,
sizeof(double)));
CATCH(e, akgl_get_json_with_default(
akgl_get_json_properties_double(
root, "physics.gravity.z", &dest->physics.gravity_z
),
(void *)&defzero,
(void *)&dest->physics.gravity_z,
sizeof(double)));
CATCH(e, akgl_get_json_with_default(
akgl_get_json_properties_double(
root, "physics.drag.x", &dest->physics.drag_x
),
(void *)&defzero,
(void *)&dest->physics.drag_x,
sizeof(double)));
CATCH(e, akgl_get_json_with_default(
akgl_get_json_properties_double(
root, "physics.drag.y", &dest->physics.drag_y
),
(void *)&defzero,
(void *)&dest->physics.drag_y,
sizeof(double)));
CATCH(e, akgl_get_json_with_default(
akgl_get_json_properties_double(
root, "physics.drag.z", &dest->physics.drag_z
),
(void *)&defzero,
(void *)&dest->physics.drag_z,
sizeof(double)));
} CLEANUP {
IGNORE(akgl_heap_release_string(tmpval));
} PROCESS(e) {
} HANDLE(e, AKERR_KEY) {
SDL_Log("Map uses game physics");
} FINISH(e, true);
SUCCEED_RETURN(e);
}
akerr_ErrorContext *akgl_tilemap_load(char *fname, akgl_Tilemap *dest) akerr_ErrorContext *akgl_tilemap_load(char *fname, akgl_Tilemap *dest)
{ {
PREPARE_ERROR(errctx); PREPARE_ERROR(errctx);
@@ -484,6 +555,7 @@ akerr_ErrorContext *akgl_tilemap_load(char *fname, akgl_Tilemap *dest)
error.line, error.line,
error.text error.text
); );
CATCH(errctx, akgl_tilemap_load_physics(dest, json));
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "tileheight", &dest->tileheight)); CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "tileheight", &dest->tileheight));
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "tilewidth", &dest->tilewidth)); CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "tilewidth", &dest->tilewidth));
CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "height", &dest->height)); CATCH(errctx, akgl_get_json_integer_value((json_t *)json, "height", &dest->height));
@@ -573,7 +645,7 @@ akerr_ErrorContext *akgl_tilemap_draw(akgl_Tilemap *map, SDL_FRect *viewport, in
src.h = map->layers[layeridx].height; src.h = map->layers[layeridx].height;
dest.w = map->layers[layeridx].width; dest.w = map->layers[layeridx].width;
dest.h = map->layers[layeridx].height; dest.h = map->layers[layeridx].height;
PASS(errctx, renderer.draw_texture(&renderer, map->layers[layeridx].texture, &src, &dest, 0, NULL, SDL_FLIP_NONE)); PASS(errctx, renderer->draw_texture(renderer, map->layers[layeridx].texture, &src, &dest, 0, NULL, SDL_FLIP_NONE));
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }
@@ -628,7 +700,7 @@ akerr_ErrorContext *akgl_tilemap_draw(akgl_Tilemap *map, SDL_FRect *viewport, in
dest.y, dest.y,
dest.w, dest.w,
dest.h);*/ dest.h);*/
PASS(errctx, renderer.draw_texture(&renderer, map->tilesets[tilesetidx].texture, &src, &dest, 0, NULL, SDL_FLIP_NONE)); PASS(errctx, renderer->draw_texture(renderer, map->tilesets[tilesetidx].texture, &src, &dest, 0, NULL, SDL_FLIP_NONE));
} }
} }
dest.x += map->tilewidth; dest.x += map->tilewidth;
@@ -683,7 +755,7 @@ akerr_ErrorContext *akgl_tilemap_draw_tileset(akgl_Tilemap *map, int tilesetidx)
dest.y, dest.y,
dest.w, dest.w,
dest.h);*/ dest.h);*/
PASS(errctx, renderer.draw_texture(&renderer, map->tilesets[tilesetidx].texture, &src, &dest, 0, NULL, SDL_FLIP_NONE)); PASS(errctx, renderer->draw_texture(renderer, map->tilesets[tilesetidx].texture, &src, &dest, 0, NULL, SDL_FLIP_NONE));
} }
SUCCEED_RETURN(errctx); SUCCEED_RETURN(errctx);
} }

View File

@@ -202,9 +202,9 @@ akerr_ErrorContext *akgl_render_and_compare(SDL_Texture *t1, SDL_Texture *t2, in
FAIL_ZERO_BREAK(errctx, t2, AKERR_NULLPOINTER, "NULL texture"); FAIL_ZERO_BREAK(errctx, t2, AKERR_NULLPOINTER, "NULL texture");
CATCH(errctx, akgl_heap_next_string(&tmpstring)); CATCH(errctx, akgl_heap_next_string(&tmpstring));
SDL_RenderClear(renderer.sdl_renderer); SDL_RenderClear(renderer->sdl_renderer);
CATCH(errctx, renderer.draw_texture(&renderer, t1, &src, &dest, 0, NULL, SDL_FLIP_NONE)); CATCH(errctx, renderer->draw_texture(renderer, t1, &src, &dest, 0, NULL, SDL_FLIP_NONE));
s1 = SDL_RenderReadPixels(renderer.sdl_renderer, &read); s1 = SDL_RenderReadPixels(renderer->sdl_renderer, &read);
FAIL_ZERO_BREAK(errctx, s1, AKGL_ERR_SDL, "Failed to read pixels from renderer"); FAIL_ZERO_BREAK(errctx, s1, AKGL_ERR_SDL, "Failed to read pixels from renderer");
if ( writeout != NULL ) { if ( writeout != NULL ) {
@@ -218,10 +218,10 @@ akerr_ErrorContext *akgl_render_and_compare(SDL_Texture *t1, SDL_Texture *t2, in
SDL_GetError()); SDL_GetError());
} }
SDL_RenderClear(renderer.sdl_renderer); SDL_RenderClear(renderer->sdl_renderer);
CATCH(errctx, renderer.draw_texture(&renderer, t1, &src, &dest, 0, NULL, SDL_FLIP_NONE)); CATCH(errctx, renderer->draw_texture(renderer, t1, &src, &dest, 0, NULL, SDL_FLIP_NONE));
s2 = SDL_RenderReadPixels(renderer.sdl_renderer, &read); s2 = SDL_RenderReadPixels(renderer->sdl_renderer, &read);
FAIL_ZERO_BREAK(errctx, s2, AKGL_ERR_SDL, "Failed to read pixels from renderer"); FAIL_ZERO_BREAK(errctx, s2, AKGL_ERR_SDL, "Failed to read pixels from renderer");
CATCH(errctx, akgl_compare_sdl_surfaces(s1, s2)); CATCH(errctx, akgl_compare_sdl_surfaces(s1, s2));