diff --git a/CMakeLists.txt b/CMakeLists.txt index ddfa0d6..abf4ed3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,8 +20,19 @@ set(libdir "\${exec_prefix}/lib") set(includedir "\${prefix}/include") # Add include directories -include_directories(${SDL3_INCLUDE_DIRS}) -add_executable(akgltest src/akgltest.c) +include_directories(${SDL3_INCLUDE_DIRS} include/) +add_executable(akgltest + src/actors.c + src/audio.c + src/events.c + src/controllers.c + src/gamemodes.c + src/init.c + src/SDL_AppInit.c + src/SDL_AppQuit.c + src/SDL_AppIterate.c + src/main.c +) target_link_libraries(akgltest PRIVATE diff --git a/assets/characters/menupointer.json b/assets/characters/menupointer.json new file mode 100644 index 0000000..e8a61d8 --- /dev/null +++ b/assets/characters/menupointer.json @@ -0,0 +1,68 @@ +{ + "name": "menupointer", + "movementspeed": 8, + "velocity_x": 0, + "velocity_y": 0, + "sprite_mappings": [ + { + "state": [ + "AKGL_ACTOR_STATE_ALIVE", + "AKGL_ACTOR_STATE_FACE_UP", + "AKGL_ACTOR_STATE_MOVING_UP" + ], + "sprite": "menupointer" + }, + { + "state": [ + "AKGL_ACTOR_STATE_ALIVE", + "AKGL_ACTOR_STATE_FACE_DOWN", + "AKGL_ACTOR_STATE_MOVING_DOWN" + ], + "sprite": "menupointer" + }, + { + "state": [ + "AKGL_ACTOR_STATE_ALIVE", + "AKGL_ACTOR_STATE_FACE_UP" + ], + "sprite": "menupointer" + }, + { + "state": [ + "AKGL_ACTOR_STATE_ALIVE", + "AKGL_ACTOR_STATE_FACE_DOWN" + ], + "sprite": "menupointer" + }, + { + "state": [ + "AKGL_ACTOR_STATE_ALIVE", + "AKGL_ACTOR_STATE_FACE_LEFT", + "AKGL_ACTOR_STATE_MOVING_LEFT" + ], + "sprite": "menupointer" + }, + { + "state": [ + "AKGL_ACTOR_STATE_ALIVE", + "AKGL_ACTOR_STATE_FACE_RIGHT", + "AKGL_ACTOR_STATE_MOVING_RIGHT" + ], + "sprite": "menupointer" + }, + { + "state": [ + "AKGL_ACTOR_STATE_ALIVE", + "AKGL_ACTOR_STATE_FACE_LEFT" + ], + "sprite": "menupointer" + }, + { + "state": [ + "AKGL_ACTOR_STATE_ALIVE", + "AKGL_ACTOR_STATE_FACE_RIGHT" + ], + "sprite": "menupointer" + } + ] +} diff --git a/assets/ffbg2.jpg b/assets/ffbg2.jpg new file mode 100644 index 0000000..97c3a08 Binary files /dev/null and b/assets/ffbg2.jpg differ diff --git a/assets/imagemap.tmj b/assets/imagemap.tmj index 1949b63..4d17e7d 100644 --- a/assets/imagemap.tmj +++ b/assets/imagemap.tmj @@ -4,7 +4,7 @@ "layers":[ { "id":4, - "image":"../assets/ffbg2-scaled.png", + "image":"ffbg2-scaled.png", "locked":true, "name":"Image Layer 1", "offsetx":5.6843418860808e-14, @@ -30,7 +30,7 @@ "name":"character", "type":"string", "value":"little guy" - }, + }, { "name":"state", "type":"int", @@ -57,7 +57,7 @@ { "name":"state", "type":"int", - "value":272 + "value":276 }], "rotation":0, "type":"actor", @@ -70,14 +70,14 @@ "height":32, "id":16, "name":"p_foreground", + "properties":[ + { + "name":"scale", + "type":"float", + "value":1.5 + }], "rotation":0, "type":"perspective", - "properties": [ - { - "name": "scale", - "type": "number", - "value": 1.5 - }], "visible":true, "width":790, "x":0, @@ -87,14 +87,14 @@ "height":12, "id":17, "name":"p_vanishing", + "properties":[ + { + "name":"scale", + "type":"float", + "value":0.75 + }], "rotation":0, "type":"perspective", - "properties": [ - { - "name": "scale", - "type": "number", - "value": 0.75 - }], "visible":true, "width":53, "x":270.5, @@ -118,7 +118,7 @@ { "columns":48, "firstgid":1, - "image":"../assets/World_A1.png", + "image":"World_A1.png", "imageheight":576, "imagewidth":768, "margin":0, @@ -132,4 +132,4 @@ "type":"map", "version":"1.8", "width":64 -} +} \ No newline at end of file diff --git a/assets/menupointer.png b/assets/menupointer.png new file mode 100644 index 0000000..14caf9f Binary files /dev/null and b/assets/menupointer.png differ diff --git a/assets/sidescroller.tmj b/assets/sidescroller.tmj new file mode 100644 index 0000000..cbce02b --- /dev/null +++ b/assets/sidescroller.tmj @@ -0,0 +1,100 @@ +{ "compressionlevel":-1, + "height":15, + "infinite":false, + "layers":[ + { + "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 0, 0, 0, 0, 0, 0, 1, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9], + "height":15, + "id":1, + "name":"Tile Layer 1", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":20, + "x":0, + "y":0 + }, + { + "draworder":"topdown", + "id":3, + "name":"Object Layer 1", + "objects":[ + { + "gid":211, + "height":16, + "id":1, + "name":"player", + "properties":[ + { + "name":"character", + "type":"string", + "value":"little guy" + }, + { + "name":"state", + "type":"int", + "value":24 + }], + "rotation":0, + "type":"actor", + "visible":true, + "width":16, + "x":304.261511065887, + "y":258.471635716103 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + }, + { + "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "height":15, + "id":2, + "name":"Tile Layer 2", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":20, + "x":0, + "y":0 + }], + "nextlayerid":4, + "nextobjectid":2, + "orientation":"orthogonal", + "renderorder":"right-down", + "tiledversion":"1.8.2", + "tileheight":32, + "tilesets":[ + { + "columns":8, + "firstgid":1, + "image":"sidescrollertiles.png", + "imageheight":256, + "imagewidth":256, + "margin":0, + "name":"sidescroller", + "spacing":0, + "tilecount":64, + "tileheight":32, + "tilewidth":32 + }, + { + "columns":48, + "firstgid":65, + "image":"World_A1.png", + "imageheight":576, + "imagewidth":768, + "margin":0, + "name":"World_A1", + "spacing":0, + "tilecount":1728, + "tileheight":16, + "tilewidth":16 + }], + "tilewidth":32, + "type":"map", + "version":"1.8", + "width":20 +} \ No newline at end of file diff --git a/assets/sprites/menupointer.json b/assets/sprites/menupointer.json new file mode 100644 index 0000000..3708045 --- /dev/null +++ b/assets/sprites/menupointer.json @@ -0,0 +1,16 @@ +{ + "spritesheet": { + "filename": "../menupointer.png", + "frame_width": 50, + "frame_height": 49 + }, + "name": "menupointer", + "width": 50, + "height": 49, + "speed": 0, + "loop": false, + "loopReverse": false, + "frames": [ + 0 + ] +} diff --git a/assets/tilemap.tmj b/assets/tilemap.tmj index 3028762..8eeb1c9 100644 --- a/assets/tilemap.tmj +++ b/assets/tilemap.tmj @@ -58,7 +58,7 @@ { "name":"state", "type":"int", - "value":272 + "value":276 }], "rotation":0, "type":"actor", diff --git a/deps/libakgl b/deps/libakgl index 6314ad7..d87c5d2 160000 --- a/deps/libakgl +++ b/deps/libakgl @@ -1 +1 @@ -Subproject commit 6314ad7f26595b2d2c2af77fc2237166a926d7f8 +Subproject commit d87c5d2c20ce4d3c1c0343459f46222305d98faa diff --git a/deps/libakstdlib b/deps/libakstdlib index def4175..b8ef8b0 160000 --- a/deps/libakstdlib +++ b/deps/libakstdlib @@ -1 +1 @@ -Subproject commit def4175d0a4d0beb78b020f48f49638b604e506e +Subproject commit b8ef8b0dd28aa7d7536fa9c3cd430c4bb7671953 diff --git a/include/akgltest.h b/include/akgltest.h new file mode 100644 index 0000000..0992f72 --- /dev/null +++ b/include/akgltest.h @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define AKGLTEST_STATE_WAITFORINPUT 1 << 8 +#define AKGLTEST_STATE_LOADING 1 << 9 +#define AKGLTEST_STATE_RUNNING 1 << 10 +#define AKGLTEST_STATE_MAPMENU 1 << 11 +#define AKGLTEST_STATE_QUIT 1 << 12 + +#define AKGLTEST_CONTROLMAP_MENU 0 +#define AKGLTEST_CONTROLMAP_INGAMEACTOR 1 + + +extern int menuselection; +extern int maxmenu; +extern int kbid; +extern int jsid; + +extern int numchars; +extern char *characterpaths[2]; + +extern int numsounds; +extern char *soundfiles[2]; + +extern int numsprites; +extern char *spritepaths[9]; + +extern char dirnamebuf[1024]; + +akerr_ErrorContext AKERR_NOIGNORE *akgltest_controller_bind_universal(char *actorname, int mapid, int kbid, int jsid); +akerr_ErrorContext AKERR_NOIGNORE *akgltest_controller_get_defaults(void *appstate, SDL_Event *event); +akerr_ErrorContext AKERR_NOIGNORE *akgltest_init_menupointer(void); +akerr_ErrorContext AKERR_NOIGNORE *akgltest_init_player(void); +akerr_ErrorContext AKERR_NOIGNORE *akgltest_iterate_mapmenu(void); +akerr_ErrorContext AKERR_NOIGNORE *akgltest_iterate_running(void); +akerr_ErrorContext AKERR_NOIGNORE *akgltest_iterate_waitforinput(void); +akerr_ErrorContext AKERR_NOIGNORE *akgltest_load_assets(); +akerr_ErrorContext AKERR_NOIGNORE *akgltest_menupointer_logic_movement(akgl_Actor *obj, SDL_Time curtime); +akerr_ErrorContext AKERR_NOIGNORE *akgltest_release_actor(char *actorname); +akerr_ErrorContext AKERR_NOIGNORE *akgltest_set_actor_visible(char *actorname, bool visible); +akerr_ErrorContext AKERR_NOIGNORE *akgltest_set_gamemode_menu(akgl_Actor *appstate, SDL_Event *event); +akerr_ErrorContext AKERR_NOIGNORE *akgltest_set_gamemode_running(akgl_Actor *appstate, SDL_Event *event); +akerr_ErrorContext AKERR_NOIGNORE *music_toggle(akgl_Actor *obj, SDL_Event *event); +akerr_ErrorContext AKERR_NOIGNORE *quit_game(akgl_Actor *obj, SDL_Event *event); +akerr_ErrorContext AKERR_NOIGNORE *savegame(akgl_Actor *obj, SDL_Event *event); +akerr_ErrorContext AKERR_NOIGNORE *user_breakpoint(akgl_Actor *obj, SDL_Event *event); diff --git a/include/demo.h b/include/demo.h new file mode 100644 index 0000000..7279e39 --- /dev/null +++ b/include/demo.h @@ -0,0 +1,8 @@ +#define AKGLTEST_STATE_WAITFORINPUT 1 << 8 +#define AKGLTEST_STATE_LOADING 1 << 9 +#define AKGLTEST_STATE_RUNNING 1 << 10 +#define AKGLTEST_STATE_MAPMENU 1 << 11 +#define AKGLTEST_STATE_QUIT 1 << 12 + +#define AKGLTEST_CONTROLMAP_MENU 0 +#define AKGLTEST_CONTROLMAP_INGAMEACTOR 1 diff --git a/src/SDL_AppInit.c b/src/SDL_AppInit.c new file mode 100644 index 0000000..847d272 --- /dev/null +++ b/src/SDL_AppInit.c @@ -0,0 +1,60 @@ +#include + +SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) +{ + akgl_Actor *actorptr = NULL; + *appstate = (void *)&game.state; + PREPARE_ERROR(e); + + AKGL_BITMASK_ADD(game.state.flags, AKGLTEST_STATE_LOADING); + + ATTEMPT { + FAIL_ZERO_BREAK(e, appstate, AKERR_NULLPOINTER, "NULL appstate pointer"); + + strcpy((char *)&game.name, "sdl3-gametest"); + strcpy((char *)&game.version, "0.0.1"); + strcpy((char *)&game.uri, "net.aklabs.games.sdl3-gametest"); + + //CATCH(e, akgl_game_load("assets/savegame.bin")); + CATCH(e, akgl_game_init()); + CATCH(e, akgl_game_state_lock()); + CATCH(e, akgl_registry_load_properties("assets/properties.json")); + CATCH(e, akgl_render_init2d(&renderer)); + CATCH(e, akgl_physics_init_sidescroller(&physics)); + CATCH(e, akgl_controller_list_keyboards()); + + CATCH(e, akgltest_load_assets()); + + CATCH(e, akgl_heap_next_actor(&actorptr)); + CATCH(e, akgl_actor_initialize((akgl_Actor *)actorptr, "player")); + actorptr->basechar = SDL_GetPointerProperty( + AKGL_REGISTRY_CHARACTER, + "little guy", + NULL); + FAIL_ZERO_BREAK(e, actorptr->basechar, AKERR_REGISTRY, "Can't load character 'little guy' from the registry"); + actorptr->movement_controls_face = false; + actorptr->state = (AKGL_ACTOR_STATE_ALIVE | AKGL_ACTOR_STATE_FACE_LEFT); + actorptr->x = 320; + actorptr->y = 240; + actorptr->visible = false; + + strcpy((char *)&dirnamebuf, "assets/memories.mp3"); + CATCH(e, akgl_load_start_bgm((char *)&dirnamebuf)); + CATCH(e, music_toggle(NULL, NULL)); + + CATCH(e, akgl_text_loadfont("C64Pro", "assets/C64_Pro-STYLE.ttf", 18)); + + + } CLEANUP { + IGNORE(akgl_game_state_unlock()); + } PROCESS(e) { + } HANDLE_DEFAULT(e) { + LOG_ERROR(e); + return SDL_APP_FAILURE; + } FINISH_NORETURN(e); + + AKGL_BITMASK_DEL(game.state.flags, AKGLTEST_STATE_LOADING); + AKGL_BITMASK_ADD(game.state.flags, AKGLTEST_STATE_WAITFORINPUT); + + return SDL_APP_CONTINUE; +} diff --git a/src/SDL_AppIterate.c b/src/SDL_AppIterate.c new file mode 100644 index 0000000..0f6b9ff --- /dev/null +++ b/src/SDL_AppIterate.c @@ -0,0 +1,29 @@ +#include + +SDL_AppResult SDL_AppIterate(void *appstate) +{ + //SDL_FRect dest; + //b2Vec2 position; + + PREPARE_ERROR(e); + + ATTEMPT { + CATCH(e, akgl_game_state_lock()); + if ( AKGL_BITMASK_HAS(game.state.flags, AKGLTEST_STATE_QUIT) ) { + return SDL_APP_FAILURE; + } else if ( AKGL_BITMASK_HAS(game.state.flags, AKGLTEST_STATE_RUNNING) ) { + CATCH(e, akgltest_iterate_running()); + } else if ( AKGL_BITMASK_HAS(game.state.flags, AKGLTEST_STATE_WAITFORINPUT) ) { + CATCH(e, akgltest_iterate_waitforinput()); + } else if ( AKGL_BITMASK_HAS(game.state.flags, AKGLTEST_STATE_MAPMENU) ) { + CATCH(e, akgltest_iterate_mapmenu()); + } + } CLEANUP { + IGNORE(akgl_game_state_unlock()); + } PROCESS(e) { + } HANDLE_DEFAULT(e) { + LOG_ERROR(e); + return SDL_APP_FAILURE; + } FINISH_NORETURN(e); + return SDL_APP_CONTINUE; +} diff --git a/src/SDL_AppQuit.c b/src/SDL_AppQuit.c new file mode 100644 index 0000000..84a63d2 --- /dev/null +++ b/src/SDL_AppQuit.c @@ -0,0 +1,14 @@ +#include + +void SDL_AppQuit(void *appstate, SDL_AppResult result) +{ + /* SDL will clean up the window/renderer for us. */ + // SDL_DestroyTexture(ball.texture); + //b2DestroyWorld(physicsWorldId); + SDL_Log("Freeing music resources"); + if ( bgm != NULL ) { + //Mix_FreeMusic(bgm); + } + SDL_Log("Quitting mixer"); + // Mix_Quit(); +} diff --git a/src/actors.c b/src/actors.c new file mode 100644 index 0000000..67fe1fd --- /dev/null +++ b/src/actors.c @@ -0,0 +1,86 @@ +#include + +akerr_ErrorContext AKERR_NOIGNORE *akgltest_menupointer_logic_movement(akgl_Actor *obj, SDL_Time curtime) +{ + PREPARE_ERROR(e); + FAIL_ZERO_RETURN(e, obj, AKERR_NULLPOINTER, "NULL actor"); + if ( AKGL_BITMASK_HAS(obj->state, AKGL_ACTOR_STATE_MOVING_DOWN) ) { + if ( menuselection < maxmenu ) { + menuselection += 1; + } else { + menuselection = 0; + } + } else if ( AKGL_BITMASK_HAS(obj->state, AKGL_ACTOR_STATE_MOVING_UP) ) { + if ( menuselection == 0 ) { + menuselection = maxmenu; + } else { + menuselection -= 1; + } + } + obj->y = 85 + (menuselection * 100); + AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_MOVING_UP | AKGL_ACTOR_STATE_MOVING_DOWN)); + SUCCEED_RETURN(e); +} + +akerr_ErrorContext AKERR_NOIGNORE *akgltest_init_menupointer(void) +{ + PREPARE_ERROR(e); + akgl_Actor *actorptr = NULL; + PASS(e, akgl_heap_next_actor(&actorptr)); + PASS(e, akgl_actor_initialize((akgl_Actor *)actorptr, "menupointer")); + actorptr->basechar = SDL_GetPointerProperty( + AKGL_REGISTRY_CHARACTER, + "menupointer", + NULL); + FAIL_ZERO_RETURN(e, actorptr->basechar, AKERR_REGISTRY, "menupointer character missing"); + actorptr->movementlogicfunc = &akgltest_menupointer_logic_movement; + actorptr->movement_controls_face = false; + actorptr->state = (AKGL_ACTOR_STATE_ALIVE | AKGL_ACTOR_STATE_FACE_DOWN); + actorptr->x = 50; + actorptr->y = 100; + actorptr->layer = 1; + actorptr->visible = false; + SUCCEED_RETURN(e); +} + +akerr_ErrorContext AKERR_NOIGNORE *akgltest_init_player(void) +{ + PREPARE_ERROR(e); + akgl_Actor *actor = NULL; + + akgl_Actor *actorptr = NULL; + PASS(e, akgl_heap_next_actor(&actorptr)); + PASS(e, akgl_actor_initialize((akgl_Actor *)actorptr, "player")); + actorptr->basechar = SDL_GetPointerProperty( + AKGL_REGISTRY_CHARACTER, + "little guy", + NULL); + FAIL_ZERO_RETURN(e, actorptr->basechar, AKERR_REGISTRY, "little guy character missing"); + actorptr->movement_controls_face = false; + actorptr->state = (AKGL_ACTOR_STATE_ALIVE | AKGL_ACTOR_STATE_FACE_LEFT); + actorptr->x = 320; + actorptr->y = 240; + actorptr->layer = 1; + actorptr->visible = false; + SUCCEED_RETURN(e); +} + +akerr_ErrorContext AKERR_NOIGNORE *akgltest_release_actor(char *actorname) +{ + PREPARE_ERROR(e); + akgl_Actor *actor = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, actorname, NULL); + FAIL_ZERO_RETURN(e, actor, AKERR_REGISTRY, "%s", actorname); + PASS(e, akgl_heap_release_actor(actor)); + SUCCEED_RETURN(e); +} + +akerr_ErrorContext AKERR_NOIGNORE *akgltest_set_actor_visible(char *actorname, bool visible) +{ + PREPARE_ERROR(e); + akgl_Actor *actorptr = NULL; + actorptr = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, actorname, NULL); + FAIL_ZERO_RETURN(e, actorptr, AKERR_NULLPOINTER, "%s missing in registry", actorname); + actorptr->visible = visible; + SUCCEED_RETURN(e); +} + diff --git a/src/akgltest.c b/src/akgltest.c index 23fccc1..7d81614 100644 --- a/src/akgltest.c +++ b/src/akgltest.c @@ -18,6 +18,8 @@ #include #include +#include + #define AKGLTEST_STATE_WAITFORINPUT 1 << 8 #define AKGLTEST_STATE_LOADING 1 << 9 #define AKGLTEST_STATE_RUNNING 1 << 10 @@ -28,7 +30,9 @@ #define AKGLTEST_CONTROLMAP_INGAMEACTOR 1 int menuselection = 0; -int maxmenu = 2; +int maxmenu = 3; +int kbid = 0; +int jsid = 0; int numchars = 2; char *characterpaths[] = { @@ -57,143 +61,20 @@ char *spritepaths[] = { char dirnamebuf[1024]; -akerr_ErrorContext AKERR_NOIGNORE *akgltest_set_gamemode_menu(akgl_Actor *appstate, SDL_Event *event) -{ - akgl_Actor *menupointer = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, "menupointer", NULL); - akgl_Actor *player = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, "player", NULL); - PREPARE_ERROR(e); - PASS(e, akgl_tilemap_release(&gamemap)); - FAIL_ZERO_RETURN(e, player, AKERR_NULLPOINTER, "missing actor"); - FAIL_ZERO_RETURN(e, menupointer, AKERR_NULLPOINTER, "missing actor"); - AKGL_BITMASK_DEL(game.state.flags, AKGLTEST_STATE_WAITFORINPUT); - AKGL_BITMASK_DEL(game.state.flags, AKGLTEST_STATE_RUNNING); - // Reset all the actors back to empty (except the player and menupointer) - for ( int i = 0 ; i < AKGL_MAX_HEAP_ACTOR; i++ ) { - if ( &HEAP_ACTOR[i] != player && &HEAP_ACTOR[i] != menupointer ) { - PASS(e, akgl_heap_release_actor(&HEAP_ACTOR[i])); - //SDL_ClearProperty(AKGL_REGISTRY_ACTOR, (char *)&HEAP_ACTOR[i].name); - //memset(&HEAP_ACTOR[i], 0x00, sizeof(akgl_Actor)); - } else { - SDL_Log("Preserving menupointer and actor (%p)", &HEAP_ACTOR[i]); - } - } - GAME_ControlMaps[AKGLTEST_CONTROLMAP_INGAMEACTOR].target = NULL; - GAME_ControlMaps[AKGLTEST_CONTROLMAP_MENU].target = menupointer; - menupointer->visible = true; - AKGL_BITMASK_ADD(game.state.flags, AKGLTEST_STATE_MAPMENU); - SUCCEED_RETURN(e); -} - -akerr_ErrorContext AKERR_NOIGNORE *akgltest_set_gamemode_running(akgl_Actor *appstate, SDL_Event *event) -{ - akgl_Actor *menupointer = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, "menupointer", NULL); - akgl_Actor *actorptr = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, "player", NULL); - PREPARE_ERROR(e); - FAIL_ZERO_RETURN(e, menupointer, AKERR_NULLPOINTER, "missing actor"); - FAIL_ZERO_RETURN(e, actorptr, AKERR_NULLPOINTER, "missing actor"); - AKGL_BITMASK_DEL(game.state.flags, AKGLTEST_STATE_WAITFORINPUT); - AKGL_BITMASK_ADD(game.state.flags, AKGLTEST_STATE_MAPMENU); - GAME_ControlMaps[AKGLTEST_CONTROLMAP_INGAMEACTOR].target = actorptr; - GAME_ControlMaps[AKGLTEST_CONTROLMAP_MENU].target = NULL; - menupointer->visible = false; - actorptr->visible = true; - - AKGL_BITMASK_DEL(game.state.flags, AKGLTEST_STATE_MAPMENU); - if ( menuselection == 0 ) { - strcpy((char *)&dirnamebuf, "assets/imagemap.tmj"); - PASS(e, akgl_tilemap_load((char *)&dirnamebuf, (akgl_Tilemap *)&gamemap)); - } else if ( menuselection == 1 ) { - strcpy((char *)&dirnamebuf, "assets/tilemap.tmj"); - PASS(e, akgl_tilemap_load((char *)&dirnamebuf, (akgl_Tilemap *)&gamemap)); - } else if ( menuselection == 2 ) { - AKGL_BITMASK_DEL(game.state.flags, AKGLTEST_STATE_RUNNING); - AKGL_BITMASK_ADD(game.state.flags, AKGLTEST_STATE_QUIT); - } - AKGL_BITMASK_ADD(game.state.flags, AKGLTEST_STATE_RUNNING); - SUCCEED_RETURN(e); -} - -akerr_ErrorContext AKERR_NOIGNORE *akgltest_menupointer_logic_movement(akgl_Actor *obj, SDL_Time curtime) -{ - PREPARE_ERROR(e); - FAIL_ZERO_RETURN(e, obj, AKERR_NULLPOINTER, "NULL actor"); - if ( AKGL_BITMASK_HAS(obj->state, AKGL_ACTOR_STATE_MOVING_DOWN) ) { - if ( menuselection < maxmenu ) { - menuselection += 1; - } else { - menuselection = 0; - } - } else if ( AKGL_BITMASK_HAS(obj->state, AKGL_ACTOR_STATE_MOVING_UP) ) { - if ( menuselection == 0 ) { - menuselection = maxmenu; - } else { - menuselection -= 1; - } - } - obj->y = 85 + (menuselection * 100); - AKGL_BITMASK_DEL(obj->state, (AKGL_ACTOR_STATE_MOVING_UP | AKGL_ACTOR_STATE_MOVING_DOWN)); - SUCCEED_RETURN(e); -} - -akerr_ErrorContext AKERR_NOIGNORE *music_toggle(akgl_Actor *obj, SDL_Event *event) -{ - SDL_PropertiesID bgmprops = 0; - PREPARE_ERROR(errctx); - if ( MIX_TrackPlaying(akgl_tracks[AKGL_GAME_AUDIO_TRACK_BGM]) ) { - FAIL_ZERO_RETURN( - errctx, - MIX_StopTrack(akgl_tracks[AKGL_GAME_AUDIO_TRACK_BGM], 0), - AKGL_ERR_SDL, - "%s", - SDL_GetError()); - } else { - SDL_SetNumberProperty(bgmprops, MIX_PROP_PLAY_LOOPS_NUMBER, -1); - FAIL_ZERO_RETURN( - errctx, - MIX_PlayTrack(akgl_tracks[AKGL_GAME_AUDIO_TRACK_BGM], bgmprops), - AKGL_ERR_SDL, - "%s", - SDL_GetError()); - } - SUCCEED_RETURN(errctx); -} - -akerr_ErrorContext AKERR_NOIGNORE *savegame(akgl_Actor *obj, SDL_Event *event) -{ - return akgl_game_save("assets/savegame.bin"); -} - -akerr_ErrorContext AKERR_NOIGNORE *quit_game(akgl_Actor *obj, SDL_Event *event) -{ - PREPARE_ERROR(errctx); - AKGL_BITMASK_ADD(game.state.flags, AKGLTEST_STATE_QUIT); - SDL_Log("Quitting game"); - SUCCEED_RETURN(errctx); -} akerr_ErrorContext AKERR_NOIGNORE *akgltest_load_assets() { - PREPARE_ERROR(errctx); + PREPARE_ERROR(e); for ( int i = 0; i < numsprites ; i++) { strcpy((char *)&dirnamebuf, spritepaths[i]); SDL_Log("Loading sprite %s (%d of %d)....", (char *)&dirnamebuf, i, numsprites); - PASS(errctx, akgl_sprite_load_json((char *)&dirnamebuf)); + PASS(e, akgl_sprite_load_json((char *)&dirnamebuf)); } for ( int i = 0; i < numchars ; i++ ) { strcpy((char *)&dirnamebuf, characterpaths[i]); SDL_Log("Loading character %s (%d of %d)....", (char *)&dirnamebuf, i, numchars); - PASS(errctx, akgl_character_load_json((char *)&dirnamebuf)); + PASS(e, akgl_character_load_json((char *)&dirnamebuf)); } - SUCCEED_RETURN(errctx); -} - -akerr_ErrorContext AKERR_NOIGNORE *akgltest_set_actor_visible(char *actorname, bool visible) -{ - PREPARE_ERROR(e); - akgl_Actor *actorptr = NULL; - actorptr = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, actorname, NULL); - FAIL_ZERO_RETURN(e, actorptr, AKERR_NULLPOINTER, "%s missing in registry", actorname); - actorptr->visible = visible; SUCCEED_RETURN(e); } @@ -201,46 +82,33 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) { akgl_Actor *actorptr = NULL; *appstate = (void *)&game.state; - PREPARE_ERROR(errctx); + PREPARE_ERROR(e); AKGL_BITMASK_ADD(game.state.flags, AKGLTEST_STATE_LOADING); ATTEMPT { - FAIL_ZERO_BREAK(errctx, appstate, AKERR_NULLPOINTER, "NULL appstate pointer"); + FAIL_ZERO_BREAK(e, appstate, AKERR_NULLPOINTER, "NULL appstate pointer"); strcpy((char *)&game.name, "sdl3-gametest"); strcpy((char *)&game.version, "0.0.1"); strcpy((char *)&game.uri, "net.aklabs.games.sdl3-gametest"); - //CATCH(errctx, akgl_game_load("assets/savegame.bin")); - CATCH(errctx, akgl_game_init()); - CATCH(errctx, akgl_registry_load_properties("assets/properties.json")); - CATCH(errctx, akgl_render_init2d(&renderer)); - CATCH(errctx, akgl_controller_list_keyboards()); + //CATCH(e, akgl_game_load("assets/savegame.bin")); + CATCH(e, akgl_game_init()); + CATCH(e, akgl_registry_load_properties("assets/properties.json")); + CATCH(e, akgl_render_init2d(&renderer)); + CATCH(e, akgl_physics_init_sidescroller(&physics)); + CATCH(e, akgl_controller_list_keyboards()); - CATCH(errctx, akgltest_load_assets()); - - CATCH(errctx, akgl_heap_next_actor(&actorptr)); - CATCH(errctx, akgl_actor_initialize((akgl_Actor *)actorptr, "menupointer")); - actorptr->basechar = SDL_GetPointerProperty( - AKGL_REGISTRY_CHARACTER, - "menupointer", - NULL); - FAIL_ZERO_BREAK(errctx, actorptr->basechar, AKERR_REGISTRY, "menupointer character missing"); - actorptr->movementlogicfunc = &akgltest_menupointer_logic_movement; - actorptr->movement_controls_face = false; - actorptr->state = (AKGL_ACTOR_STATE_ALIVE | AKGL_ACTOR_STATE_FACE_DOWN); - actorptr->x = 50; - actorptr->y = 100; - actorptr->visible = false; - - CATCH(errctx, akgl_heap_next_actor(&actorptr)); - CATCH(errctx, akgl_actor_initialize((akgl_Actor *)actorptr, "player")); + CATCH(e, akgltest_load_assets()); + + CATCH(e, akgl_heap_next_actor(&actorptr)); + CATCH(e, akgl_actor_initialize((akgl_Actor *)actorptr, "player")); actorptr->basechar = SDL_GetPointerProperty( AKGL_REGISTRY_CHARACTER, "little guy", NULL); - FAIL_ZERO_BREAK(errctx, actorptr->basechar, AKERR_REGISTRY, "Can't load character 'little guy' from the registry"); + FAIL_ZERO_BREAK(e, actorptr->basechar, AKERR_REGISTRY, "Can't load character 'little guy' from the registry"); actorptr->movement_controls_face = false; actorptr->state = (AKGL_ACTOR_STATE_ALIVE | AKGL_ACTOR_STATE_FACE_LEFT); actorptr->x = 320; @@ -248,18 +116,18 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) actorptr->visible = false; strcpy((char *)&dirnamebuf, "assets/memories.mp3"); - CATCH(errctx, akgl_load_start_bgm((char *)&dirnamebuf)); - CATCH(errctx, music_toggle(NULL, NULL)); + CATCH(e, akgl_load_start_bgm((char *)&dirnamebuf)); + CATCH(e, music_toggle(NULL, NULL)); - CATCH(errctx, akgl_text_loadfont("C64Pro", "assets/C64_Pro-STYLE.ttf", 18)); + CATCH(e, akgl_text_loadfont("C64Pro", "assets/C64_Pro-STYLE.ttf", 18)); } CLEANUP { - } PROCESS(errctx) { - } HANDLE_DEFAULT(errctx) { - LOG_ERROR(errctx); + } PROCESS(e) { + } HANDLE_DEFAULT(e) { + LOG_ERROR(e); return SDL_APP_FAILURE; - } FINISH_NORETURN(errctx); + } FINISH_NORETURN(e); AKGL_BITMASK_DEL(game.state.flags, AKGLTEST_STATE_LOADING); AKGL_BITMASK_ADD(game.state.flags, AKGLTEST_STATE_WAITFORINPUT); @@ -267,230 +135,6 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) return SDL_APP_CONTINUE; } -akerr_ErrorContext AKERR_NOIGNORE *akgltest_controller_bind_universal(char *actorname, int mapid, int kbid, int jsid) -{ - akgl_Control control; - PREPARE_ERROR(e); - - PASS(e, akgl_controller_default(mapid, actorname, kbid, jsid)); - // set custom control maps */ - memset((void *)&control, 0x00, sizeof(akgl_Control)); - - // Quit - control.key = SDLK_ESCAPE; - control.event_on = SDL_EVENT_KEY_DOWN; - control.handler_on = &akgltest_set_gamemode_menu; - PASS(e, akgl_controller_pushmap(mapid, &control)); - - // Toggle the music - control.key = SDLK_M; - control.event_on = SDL_EVENT_KEY_DOWN; - control.handler_on = &music_toggle; - PASS(e, akgl_controller_pushmap(mapid, &control)); - - // Save the game - control.key = SDLK_S; - control.event_on = SDL_EVENT_KEY_DOWN; - control.handler_on = &savegame; - PASS(e, akgl_controller_pushmap(AKGLTEST_CONTROLMAP_INGAMEACTOR, &control)); - - // Menu selection - control.key = SDLK_RETURN; - control.event_on = SDL_EVENT_KEY_DOWN; - control.handler_on = &akgltest_set_gamemode_running; - PASS(e, akgl_controller_pushmap(AKGLTEST_CONTROLMAP_MENU, &control)); - - if ( jsid != 0 ) { - // Gamepad Menu selection. Use whatever button they pushed as the action - control.button = SDL_GAMEPAD_BUTTON_START; - control.event_on = SDL_EVENT_GAMEPAD_BUTTON_UP; - control.handler_on = &akgltest_set_gamemode_running; - PASS(e, akgl_controller_pushmap(AKGLTEST_CONTROLMAP_MENU, &control)); - - // Toggle the music - control.button = SDL_GAMEPAD_BUTTON_SOUTH; - control.event_on = SDL_EVENT_GAMEPAD_BUTTON_UP; - control.handler_on = &music_toggle; - PASS(e, akgl_controller_pushmap(mapid, &control)); - - // Quit - control.button = SDL_GAMEPAD_BUTTON_EAST; - control.event_on = SDL_EVENT_GAMEPAD_BUTTON_UP; - control.handler_on = &akgltest_set_gamemode_menu; - PASS(e, akgl_controller_pushmap(mapid, &control)); - } - SUCCEED_RETURN(e); -} - - -akerr_ErrorContext AKERR_NOIGNORE *akgltest_controller_get_defaults(void *appstate, SDL_Event *event) -{ - akgl_Control control; - int kbid = 0; - int jsid = 0; - - PREPARE_ERROR(e); - - if (event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN || event->type == SDL_EVENT_GAMEPAD_BUTTON_UP) { - jsid = event->gbutton.which; - } else if (event->type == SDL_EVENT_KEY_DOWN || event->type == SDL_EVENT_KEY_UP) { - kbid = event->key.which; - } - - PASS(e, akgltest_controller_bind_universal("player", AKGLTEST_CONTROLMAP_MENU, kbid, jsid)); - PASS(e, akgltest_controller_bind_universal("menupointer", AKGLTEST_CONTROLMAP_INGAMEACTOR, kbid, jsid)); - - SUCCEED_RETURN(e); -} - -SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) -{ - PREPARE_ERROR(errctx); - - ATTEMPT { - FAIL_ZERO_BREAK(errctx, appstate, AKERR_NULLPOINTER, "NULL appstate pointer"); - FAIL_ZERO_BREAK(errctx, event, AKERR_NULLPOINTER, "NULL event pointer"); - - if ( event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN || - event->type == SDL_EVENT_GAMEPAD_BUTTON_UP || - event->type == SDL_EVENT_KEY_DOWN || - event->type == SDL_EVENT_KEY_UP ) { - if ( AKGL_BITMASK_HAS(game.state.flags, AKGLTEST_STATE_WAITFORINPUT) ) { - // get the player's default keyboard or gamepad id from the event - CATCH(errctx, akgltest_controller_get_defaults(appstate, event)); - CATCH(errctx, akgltest_set_gamemode_menu(appstate, event)); - } else { - CATCH(errctx, akgl_controller_handle_event(appstate, event)); - } - } - if (event->type == SDL_EVENT_QUIT) { - return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ - } - } CLEANUP { - } PROCESS(errctx) { - } FINISH_NORETURN(errctx); - return SDL_APP_CONTINUE; /* carry on with the program! */ -} - -akerr_ErrorContext AKERR_NOIGNORE *akgltest_iterate_mapmenu(void) -{ - akgl_Actor *menupointer = NULL; - PREPARE_ERROR(e); - ATTEMPT { - CATCH(e, renderer.frame_start(&renderer)) - SDL_SetRenderDrawColor(renderer.sdl_renderer, 0, 0, 0, 255); - SDL_RenderClear(renderer.sdl_renderer); - PASS(e, akgl_text_rendertextat( - SDL_GetPointerProperty( - AKGL_REGISTRY_FONT, - "C64Pro", - NULL), - "IMAGE MAP DEMO", - (SDL_Color){255, 255, 255, 255}, - 0, - 150, - 100) - ); - PASS(e, akgl_text_rendertextat( - SDL_GetPointerProperty( - AKGL_REGISTRY_FONT, - "C64Pro", - NULL), - "TILE MAP DEMO", - (SDL_Color){255, 255, 255, 255}, - 0, - 150, - 200) - ); - PASS(e, akgl_text_rendertextat( - SDL_GetPointerProperty( - AKGL_REGISTRY_FONT, - "C64Pro", - NULL), - "QUIT GAME", - (SDL_Color){255, 255, 255, 255}, - 0, - 150, - 300) - ); - menupointer = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, "menupointer", NULL); - FAIL_ZERO_BREAK(e, menupointer, AKERR_NULLPOINTER, "actor missing from registry"); - menupointer->visible = true; - CATCH(e, menupointer->updatefunc(menupointer)); - CATCH(e, menupointer->movementlogicfunc(menupointer, 0)); - CATCH(e, menupointer->renderfunc(menupointer)); - CATCH(e, renderer.frame_end(&renderer)) - } CLEANUP { - } PROCESS(e) { - } FINISH(e, true); - - SUCCEED_RETURN(e); -} - -akerr_ErrorContext AKERR_NOIGNORE *akgltest_iterate_waitforinput(void) -{ - - PREPARE_ERROR(errctx); - - akgl_game_updateFPS(); - - PASS(errctx, akgl_text_rendertextat( - SDL_GetPointerProperty( - AKGL_REGISTRY_FONT, - "C64Pro", - NULL), - "PRESS ANY KEY OR JOYSTICK BUTTON", - (SDL_Color){255, 255, 255, 255}, - 0, - 40, - 120) - ); - PASS(errctx, renderer.frame_end(&renderer)); - SUCCEED_RETURN(errctx); -} - -akerr_ErrorContext AKERR_NOIGNORE *akgltest_iterate_running(void) -{ - int i = 0; - akgl_Iterator opflags; - char fpsText[32]; - - PREPARE_ERROR(errctx); - - akgl_game_updateFPS(); - - AKGL_BITMASK_CLEAR(opflags.flags); - AKGL_BITMASK_ADD(opflags.flags, AKGL_ITERATOR_OP_UPDATE); - AKGL_BITMASK_ADD(opflags.flags, AKGL_ITERATOR_OP_RENDER); - AKGL_BITMASK_ADD(opflags.flags, AKGL_ITERATOR_OP_LAYERMASK); - AKGL_BITMASK_ADD(opflags.flags, AKGL_ITERATOR_OP_TILEMAPSCALE); - - for ( i = 0; i < AKGL_TILEMAP_MAX_LAYERS; i++ ) { - opflags.layerid = i; - PASS(errctx, akgl_tilemap_draw((akgl_Tilemap *)&gamemap, &camera, i)); - SDL_EnumerateProperties(AKGL_REGISTRY_ACTOR, &akgl_registry_iterate_actor, (void *)&opflags); - } - ATTEMPT { - memset((char *)&fpsText, 0x00, 32); - snprintf((char *)&fpsText, 31, "FPS : %d", game.fps); - PASS(errctx, akgl_text_rendertextat( - SDL_GetPointerProperty( - AKGL_REGISTRY_FONT, - "C64Pro", - NULL), - (char *)&fpsText, - (SDL_Color){255, 255, 255, 255}, - 0, - 450, - 10) - ); - } CLEANUP { - SDL_RenderPresent(renderer.sdl_renderer); - } PROCESS(errctx) { - } HANDLE_DEFAULT(errctx) { - } FINISH(errctx, true); - SUCCEED_RETURN(errctx); -} SDL_AppResult SDL_AppIterate(void *appstate) { diff --git a/src/audio.c b/src/audio.c new file mode 100644 index 0000000..af4c2b0 --- /dev/null +++ b/src/audio.c @@ -0,0 +1,24 @@ +#include + +akerr_ErrorContext AKERR_NOIGNORE *music_toggle(akgl_Actor *obj, SDL_Event *event) +{ + SDL_PropertiesID bgmprops = 0; + PREPARE_ERROR(e); + if ( MIX_TrackPlaying(akgl_tracks[AKGL_GAME_AUDIO_TRACK_BGM]) ) { + FAIL_ZERO_RETURN( + e, + MIX_StopTrack(akgl_tracks[AKGL_GAME_AUDIO_TRACK_BGM], 0), + AKGL_ERR_SDL, + "%s", + SDL_GetError()); + } else { + SDL_SetNumberProperty(bgmprops, MIX_PROP_PLAY_LOOPS_NUMBER, -1); + FAIL_ZERO_RETURN( + e, + MIX_PlayTrack(akgl_tracks[AKGL_GAME_AUDIO_TRACK_BGM], bgmprops), + AKGL_ERR_SDL, + "%s", + SDL_GetError()); + } + SUCCEED_RETURN(e); +} diff --git a/src/controllers.c b/src/controllers.c new file mode 100644 index 0000000..97714ba --- /dev/null +++ b/src/controllers.c @@ -0,0 +1,71 @@ +#include + +akerr_ErrorContext AKERR_NOIGNORE *akgltest_controller_bind_universal(char *actorname, int mapid, int kbid, int jsid) +{ + akgl_Control control; + PREPARE_ERROR(e); + + PASS(e, akgl_controller_default(mapid, actorname, kbid, jsid)); + // set custom control maps */ + memset((void *)&control, 0x00, sizeof(akgl_Control)); + + // Quit + control.key = SDLK_ESCAPE; + control.event_on = SDL_EVENT_KEY_DOWN; + control.handler_on = &akgltest_set_gamemode_menu; + PASS(e, akgl_controller_pushmap(mapid, &control)); + + // Toggle the music + control.key = SDLK_M; + control.event_on = SDL_EVENT_KEY_DOWN; + control.handler_on = &music_toggle; + PASS(e, akgl_controller_pushmap(mapid, &control)); + + // Save the game + control.key = SDLK_S; + control.event_on = SDL_EVENT_KEY_DOWN; + control.handler_on = &savegame; + PASS(e, akgl_controller_pushmap(AKGLTEST_CONTROLMAP_INGAMEACTOR, &control)); + + // Menu selection + control.key = SDLK_RETURN; + control.event_on = SDL_EVENT_KEY_DOWN; + control.handler_on = &akgltest_set_gamemode_running; + PASS(e, akgl_controller_pushmap(AKGLTEST_CONTROLMAP_MENU, &control)); + + if ( jsid != 0 ) { + // Gamepad Menu selection. Use whatever button they pushed as the action + control.button = SDL_GAMEPAD_BUTTON_START; + control.event_on = SDL_EVENT_GAMEPAD_BUTTON_UP; + control.handler_on = &akgltest_set_gamemode_running; + PASS(e, akgl_controller_pushmap(AKGLTEST_CONTROLMAP_MENU, &control)); + + // Toggle the music + control.button = SDL_GAMEPAD_BUTTON_SOUTH; + control.event_on = SDL_EVENT_GAMEPAD_BUTTON_UP; + control.handler_on = &music_toggle; + PASS(e, akgl_controller_pushmap(mapid, &control)); + + // Quit + control.button = SDL_GAMEPAD_BUTTON_EAST; + control.event_on = SDL_EVENT_GAMEPAD_BUTTON_UP; + control.handler_on = &akgltest_set_gamemode_menu; + PASS(e, akgl_controller_pushmap(mapid, &control)); + } + SUCCEED_RETURN(e); +} + +akerr_ErrorContext AKERR_NOIGNORE *akgltest_controller_get_defaults(void *appstate, SDL_Event *event) +{ + akgl_Control control; + + PREPARE_ERROR(e); + + if (event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN || event->type == SDL_EVENT_GAMEPAD_BUTTON_UP) { + jsid = event->gbutton.which; + } else if (event->type == SDL_EVENT_KEY_DOWN || event->type == SDL_EVENT_KEY_UP) { + kbid = event->key.which; + } + + SUCCEED_RETURN(e); +} diff --git a/src/events.c b/src/events.c new file mode 100644 index 0000000..f0216d6 --- /dev/null +++ b/src/events.c @@ -0,0 +1,45 @@ +#include + +akerr_ErrorContext AKERR_NOIGNORE *savegame(akgl_Actor *obj, SDL_Event *event) +{ + return akgl_game_save("assets/savegame.bin"); +} + +akerr_ErrorContext AKERR_NOIGNORE *quit_game(akgl_Actor *obj, SDL_Event *event) +{ + PREPARE_ERROR(e); + AKGL_BITMASK_ADD(game.state.flags, AKGLTEST_STATE_QUIT); + SDL_Log("Quitting game"); + SUCCEED_RETURN(e); +} + +SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) +{ + PREPARE_ERROR(e); + + ATTEMPT { + CATCH(e, akgl_game_state_lock()); + FAIL_ZERO_BREAK(e, appstate, AKERR_NULLPOINTER, "NULL appstate pointer"); + FAIL_ZERO_BREAK(e, event, AKERR_NULLPOINTER, "NULL event pointer"); + + if ( AKGL_BITMASK_HAS(game.state.flags, AKGLTEST_STATE_WAITFORINPUT) ) { + if ( event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN || + event->type == SDL_EVENT_GAMEPAD_BUTTON_UP || + event->type == SDL_EVENT_KEY_DOWN || + event->type == SDL_EVENT_KEY_UP ) { + // get the player's default keyboard or gamepad id from the event + CATCH(e, akgltest_controller_get_defaults(appstate, event)); + CATCH(e, akgltest_set_gamemode_menu(appstate, event)); + } + } else { + CATCH(e, akgl_controller_handle_event(appstate, event)); + } + if (event->type == SDL_EVENT_QUIT) { + return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ + } + } CLEANUP { + IGNORE(akgl_game_state_unlock()); + } PROCESS(e) { + } FINISH_NORETURN(e); + return SDL_APP_CONTINUE; /* carry on with the program! */ +} diff --git a/src/gamemodes.c b/src/gamemodes.c new file mode 100644 index 0000000..506f6ae --- /dev/null +++ b/src/gamemodes.c @@ -0,0 +1,173 @@ +#include + +akerr_ErrorContext AKERR_NOIGNORE *akgltest_set_gamemode_menu(akgl_Actor *appstate, SDL_Event *event) +{ + PREPARE_ERROR(e); + AKGL_BITMASK_DEL(game.state.flags, AKGLTEST_STATE_WAITFORINPUT); + AKGL_BITMASK_DEL(game.state.flags, AKGLTEST_STATE_RUNNING); + PASS(e, akgl_tilemap_release(&gamemap)); + PASS(e, akgl_registry_init_actor()); + PASS(e, akgl_heap_init_actor()); + PASS(e, akgltest_init_menupointer()); + akgl_Actor *menupointer = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, "menupointer", NULL); + GAME_ControlMaps[AKGLTEST_CONTROLMAP_INGAMEACTOR].target = NULL; + GAME_ControlMaps[AKGLTEST_CONTROLMAP_MENU].target = menupointer; + menupointer->visible = true; + + PASS(e, aksl_memset((void *)GAME_ControlMaps, 0x00, (sizeof(akgl_ControlMap) * AKGL_MAX_CONTROL_MAPS))); + PASS(e, akgltest_controller_bind_universal("menupointer", AKGLTEST_CONTROLMAP_MENU, kbid, jsid)); + PASS(e, aksl_memset((void *)&gamemap, 0x00, sizeof(akgl_Tilemap))); + AKGL_BITMASK_ADD(game.state.flags, AKGLTEST_STATE_MAPMENU); + SUCCEED_RETURN(e); +} + +akerr_ErrorContext AKERR_NOIGNORE *akgltest_set_gamemode_running(akgl_Actor *appstate, SDL_Event *event) +{ + PREPARE_ERROR(e); + AKGL_BITMASK_DEL(game.state.flags, AKGLTEST_STATE_WAITFORINPUT); + AKGL_BITMASK_DEL(game.state.flags, AKGLTEST_STATE_MAPMENU); + PASS(e, akgl_registry_init_actor()); + PASS(e, akgl_heap_init_actor()); + PASS(e, akgltest_init_player()); + PASS(e, aksl_memset((void *)GAME_ControlMaps, 0x00, (sizeof(akgl_ControlMap) * AKGL_MAX_CONTROL_MAPS))); + PASS(e, akgltest_controller_bind_universal("player", AKGLTEST_CONTROLMAP_INGAMEACTOR, kbid, jsid)); + akgl_Actor *actorptr = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, "player", NULL); + GAME_ControlMaps[AKGLTEST_CONTROLMAP_INGAMEACTOR].target = actorptr; + GAME_ControlMaps[AKGLTEST_CONTROLMAP_MENU].target = NULL; + actorptr->visible = true; + + if ( menuselection == 0 ) { + strcpy((char *)&dirnamebuf, "assets/imagemap.tmj"); + PASS(e, akgl_tilemap_load((char *)&dirnamebuf, (akgl_Tilemap *)&gamemap)); + } else if ( menuselection == 1 ) { + strcpy((char *)&dirnamebuf, "assets/tilemap.tmj"); + PASS(e, akgl_tilemap_load((char *)&dirnamebuf, (akgl_Tilemap *)&gamemap)); + } else if ( menuselection == 2 ) { + strcpy((char *)&dirnamebuf, "assets/sidescroller.tmj"); + PASS(e, akgl_tilemap_load((char *)&dirnamebuf, (akgl_Tilemap *)&gamemap)); + } else if ( menuselection == 3 ) { + AKGL_BITMASK_DEL(game.state.flags, AKGLTEST_STATE_RUNNING); + AKGL_BITMASK_ADD(game.state.flags, AKGLTEST_STATE_QUIT); + } + AKGL_BITMASK_ADD(game.state.flags, AKGLTEST_STATE_RUNNING); + SUCCEED_RETURN(e); +} + +akerr_ErrorContext AKERR_NOIGNORE *akgltest_iterate_mapmenu(void) +{ + akgl_Actor *menupointer = NULL; + akgl_Iterator opflags = { + .flags = 0, + .layerid = 0 + }; + PREPARE_ERROR(e); + ATTEMPT { + CATCH(e, renderer.frame_start(&renderer)) + + SDL_SetRenderDrawColor(renderer.sdl_renderer, 0, 0, 0, 255); + SDL_RenderClear(renderer.sdl_renderer); + PASS(e, akgl_text_rendertextat( + SDL_GetPointerProperty( + AKGL_REGISTRY_FONT, + "C64Pro", + NULL), + "IMAGE MAP DEMO", + (SDL_Color){255, 255, 255, 255}, + 0, + 150, + 100) + ); + PASS(e, akgl_text_rendertextat( + SDL_GetPointerProperty( + AKGL_REGISTRY_FONT, + "C64Pro", + NULL), + "TILE MAP DEMO", + (SDL_Color){255, 255, 255, 255}, + 0, + 150, + 200) + ); + PASS(e, akgl_text_rendertextat( + SDL_GetPointerProperty( + AKGL_REGISTRY_FONT, + "C64Pro", + NULL), + "SIDESCROLLER MAP DEMO", + (SDL_Color){255, 255, 255, 255}, + 0, + 150, + 300) + ); + PASS(e, akgl_text_rendertextat( + SDL_GetPointerProperty( + AKGL_REGISTRY_FONT, + "C64Pro", + NULL), + "QUIT GAME", + (SDL_Color){255, 255, 255, 255}, + 0, + 150, + 400) + ); + menupointer = SDL_GetPointerProperty(AKGL_REGISTRY_ACTOR, "menupointer", NULL); + FAIL_ZERO_BREAK(e, menupointer, AKERR_NULLPOINTER, "actor missing from registry"); + menupointer->visible = true; + CATCH(e, akgl_game_update(&opflags)); + CATCH(e, renderer.frame_end(&renderer)) + } CLEANUP { + } PROCESS(e) { + } FINISH(e, true); + + SUCCEED_RETURN(e); +} + +akerr_ErrorContext AKERR_NOIGNORE *akgltest_iterate_waitforinput(void) +{ + + PREPARE_ERROR(e); + + akgl_game_updateFPS(); + + PASS(e, akgl_text_rendertextat( + SDL_GetPointerProperty( + AKGL_REGISTRY_FONT, + "C64Pro", + NULL), + "PRESS ANY KEY OR JOYSTICK BUTTON", + (SDL_Color){255, 255, 255, 255}, + 0, + 40, + 120) + ); + PASS(e, renderer.frame_end(&renderer)); + SUCCEED_RETURN(e); +} + +akerr_ErrorContext AKERR_NOIGNORE *akgltest_iterate_running(void) +{ + int i = 0; + akgl_Iterator opflags; + char fpsText[32]; + + PREPARE_ERROR(e); + PASS(e, renderer.frame_start(&renderer)); + + PASS(e, akgl_game_update(NULL)); + + memset((char *)&fpsText, 0x00, 32); + snprintf((char *)&fpsText, 31, "FPS : %d", game.fps); + PASS(e, akgl_text_rendertextat( + SDL_GetPointerProperty( + AKGL_REGISTRY_FONT, + "C64Pro", + NULL), + (char *)&fpsText, + (SDL_Color){255, 255, 255, 255}, + 0, + 450, + 10) + ); + PASS(e, renderer.frame_end(&renderer)); + SUCCEED_RETURN(e); +} diff --git a/src/init.c b/src/init.c new file mode 100644 index 0000000..921b4d9 --- /dev/null +++ b/src/init.c @@ -0,0 +1,18 @@ +#include + +akerr_ErrorContext AKERR_NOIGNORE *akgltest_load_assets() +{ + PREPARE_ERROR(e); + for ( int i = 0; i < numsprites ; i++) { + strcpy((char *)&dirnamebuf, spritepaths[i]); + SDL_Log("Loading sprite %s (%d of %d)....", (char *)&dirnamebuf, i, numsprites); + PASS(e, akgl_sprite_load_json((char *)&dirnamebuf)); + } + for ( int i = 0; i < numchars ; i++ ) { + strcpy((char *)&dirnamebuf, characterpaths[i]); + SDL_Log("Loading character %s (%d of %d)....", (char *)&dirnamebuf, i, numchars); + PASS(e, akgl_character_load_json((char *)&dirnamebuf)); + } + SUCCEED_RETURN(e); +} + diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..6af2bde --- /dev/null +++ b/src/main.c @@ -0,0 +1,36 @@ +#define SDL_MAIN_USE_CALLBACKS + +#include + +int menuselection = 0; +int maxmenu = 3; +int kbid = 0; +int jsid = 0; + +int numchars = 2; +char *characterpaths[] = { + "assets/characters/littleguy.json", + "assets/characters/menupointer.json" +}; + +int numsounds = 2; +char *soundfiles[] = { + "assets/vgmenuhighlight.wav", + "assets/vgmenuselect.wav" +}; + +int numsprites = 9; +char *spritepaths[] = { + "assets/sprites/menupointer.json", + "assets/sprites/little_guy_walking_left.json", + "assets/sprites/little_guy_walking_right.json", + "assets/sprites/little_guy_walking_up.json", + "assets/sprites/little_guy_walking_down.json", + "assets/sprites/little_guy_facing_left.json", + "assets/sprites/little_guy_facing_right.json", + "assets/sprites/little_guy_facing_up.json", + "assets/sprites/little_guy_facing_down.json" +}; + +char dirnamebuf[1024]; +