Added a font registry, a text rendering helper, and an FPS counter function
This commit is contained in:
@@ -7,6 +7,7 @@ find_package(PkgConfig REQUIRED)
|
|||||||
find_package(SDL3 REQUIRED)
|
find_package(SDL3 REQUIRED)
|
||||||
find_package(SDL3_image REQUIRED)
|
find_package(SDL3_image REQUIRED)
|
||||||
find_package(SDL3_mixer REQUIRED)
|
find_package(SDL3_mixer REQUIRED)
|
||||||
|
find_package(SDL3_ttf REQUIRED)
|
||||||
find_package(akerror REQUIRED)
|
find_package(akerror REQUIRED)
|
||||||
find_package(jansson REQUIRED)
|
find_package(jansson REQUIRED)
|
||||||
find_package(box2d REQUIRED)
|
find_package(box2d REQUIRED)
|
||||||
@@ -36,6 +37,7 @@ include_directories(${SDL3_INCLUDE_DIRS})
|
|||||||
add_library(sdl3game SHARED
|
add_library(sdl3game SHARED
|
||||||
src/actor.c
|
src/actor.c
|
||||||
src/actor_state_string_names.c
|
src/actor_state_string_names.c
|
||||||
|
src/text.c
|
||||||
src/assets.c
|
src/assets.c
|
||||||
src/character.c
|
src/character.c
|
||||||
src/draw.c
|
src/draw.c
|
||||||
@@ -81,23 +83,25 @@ target_link_libraries(sdl3game
|
|||||||
SDL3::SDL3
|
SDL3::SDL3
|
||||||
SDL3_image::SDL3_image
|
SDL3_image::SDL3_image
|
||||||
SDL3_mixer::SDL3_mixer
|
SDL3_mixer::SDL3_mixer
|
||||||
|
SDL3_ttf::SDL3_ttf
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(test_actor PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
target_link_libraries(test_actor PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
||||||
target_link_libraries(test_bitmasks PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
target_link_libraries(test_bitmasks PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
||||||
target_link_libraries(test_character PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
target_link_libraries(test_character PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
||||||
target_link_libraries(test_registry PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
target_link_libraries(test_registry PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
||||||
target_link_libraries(test_sprite PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
target_link_libraries(test_sprite PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
||||||
target_link_libraries(test_staticstring PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
target_link_libraries(test_staticstring PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
||||||
target_link_libraries(test_tilemap PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
target_link_libraries(test_tilemap PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
||||||
target_link_libraries(test_util PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
target_link_libraries(test_util PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
||||||
|
|
||||||
target_link_libraries(charviewer PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
target_link_libraries(charviewer PRIVATE akerror::akerror sdl3game SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image SDL3_mixer::SDL3_mixer box2d::box2d jansson::jansson -lm)
|
||||||
|
|
||||||
set(main_lib_dest "lib/sdl3game-${MY_LIBRARY_VERSION}")
|
set(main_lib_dest "lib/sdl3game-${MY_LIBRARY_VERSION}")
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/sdl3game.pc DESTINATION "lib/pkgconfig/")
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/sdl3game.pc DESTINATION "lib/pkgconfig/")
|
||||||
install(TARGETS sdl3game DESTINATION "lib/")
|
install(TARGETS sdl3game DESTINATION "lib/")
|
||||||
install(FILES "include/sdl3game/actor.h" DESTINATION "include/sdl3game/")
|
install(FILES "include/sdl3game/actor.h" DESTINATION "include/sdl3game/")
|
||||||
|
install(FILES "include/sdl3game/text.h" DESTINATION "include/sdl3game/")
|
||||||
install(FILES "include/sdl3game/assets.h" DESTINATION "include/sdl3game/")
|
install(FILES "include/sdl3game/assets.h" DESTINATION "include/sdl3game/")
|
||||||
install(FILES "include/sdl3game/character.h" DESTINATION "include/sdl3game/")
|
install(FILES "include/sdl3game/character.h" DESTINATION "include/sdl3game/")
|
||||||
install(FILES "include/sdl3game/error.h" DESTINATION "include/sdl3game/")
|
install(FILES "include/sdl3game/error.h" DESTINATION "include/sdl3game/")
|
||||||
|
|||||||
2
TODO.txt
2
TODO.txt
@@ -1,5 +1,3 @@
|
|||||||
Character velocity is tied to CPU speed, not constant
|
|
||||||
|
|
||||||
Rendering should move to the SDL GPU renderer so i can do lighting and particles etc
|
Rendering should move to the SDL GPU renderer so i can do lighting and particles etc
|
||||||
- Example suitable for my most primitive use case: https://github.com/TheSpydog/SDL_gpu_examples/blob/main/Examples/Blit2DArray.c
|
- Example suitable for my most primitive use case: https://github.com/TheSpydog/SDL_gpu_examples/blob/main/Examples/Blit2DArray.c
|
||||||
- Try vulkan and D3D tutorials to come up to speed on the moving pieces, then figure ou the details from the examples and API docs
|
- Try vulkan and D3D tutorials to come up to speed on the moving pieces, then figure ou the details from the examples and API docs
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef _SDL_GAMECONTROLLERDB_H_
|
#ifndef _SDL_GAMECONTROLLERDB_H_
|
||||||
#define _SDL_GAMECONTROLLERDB_H_
|
#define _SDL_GAMECONTROLLERDB_H_
|
||||||
|
|
||||||
// Taken from https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/refs/heads/master/gamecontrollerdb.txt on Tue May 5 08:39:19 PM EDT 2026
|
// Taken from https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/refs/heads/master/gamecontrollerdb.txt on Wed May 6 11:06:20 AM EDT 2026
|
||||||
|
|
||||||
#define SDL_GAMECONTROLLER_DB_LEN 2225
|
#define SDL_GAMECONTROLLER_DB_LEN 2225
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,12 @@
|
|||||||
#include <SDL3_mixer/SDL_mixer.h>
|
#include <SDL3_mixer/SDL_mixer.h>
|
||||||
#include "tilemap.h"
|
#include "tilemap.h"
|
||||||
|
|
||||||
|
#define GAME_AUDIO_TRACK_BGM 1
|
||||||
|
#define GAME_AUDIO_MAX_TRACKS 64
|
||||||
|
|
||||||
|
#define TIME_ONESEC_NS 1000000000
|
||||||
|
#define TIME_ONESEC_MS 1000000
|
||||||
|
|
||||||
/* ==================== GAME STATE VARIABLES =================== */
|
/* ==================== GAME STATE VARIABLES =================== */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -23,11 +29,15 @@ typedef struct {
|
|||||||
int screenwidth;
|
int screenwidth;
|
||||||
int screenheight;
|
int screenheight;
|
||||||
GameState state;
|
GameState state;
|
||||||
|
int fps;
|
||||||
|
SDL_Time gameStartTime;
|
||||||
|
SDL_Time lastIterTime;
|
||||||
|
SDL_Time lastFPSTime;
|
||||||
|
int framesSinceUpdate;
|
||||||
MIX_Mixer *mixer;
|
MIX_Mixer *mixer;
|
||||||
MIX_Track *tracks[64];
|
MIX_Track *tracks[GAME_AUDIO_MAX_TRACKS];
|
||||||
} Game;
|
} Game;
|
||||||
|
|
||||||
#define GAME_AUDIO_TRACK_BGM 1
|
|
||||||
|
|
||||||
extern SDL_Window *window;
|
extern SDL_Window *window;
|
||||||
extern SDL_Renderer *renderer;
|
extern SDL_Renderer *renderer;
|
||||||
@@ -42,5 +52,6 @@ extern Game game;
|
|||||||
#define BITMASK_CLEAR(x) x = 0;
|
#define BITMASK_CLEAR(x) x = 0;
|
||||||
|
|
||||||
akerr_ErrorContext AKERR_NOIGNORE *GAME_init();
|
akerr_ErrorContext AKERR_NOIGNORE *GAME_init();
|
||||||
|
void GAME_updateFPS();
|
||||||
|
|
||||||
#endif //_GAME_H_
|
#endif //_GAME_H_
|
||||||
|
|||||||
@@ -8,8 +8,12 @@ extern SDL_PropertiesID REGISTRY_SPRITE;
|
|||||||
extern SDL_PropertiesID REGISTRY_SPRITESHEET;
|
extern SDL_PropertiesID REGISTRY_SPRITESHEET;
|
||||||
extern SDL_PropertiesID REGISTRY_CHARACTER;
|
extern SDL_PropertiesID REGISTRY_CHARACTER;
|
||||||
extern SDL_PropertiesID REGISTRY_ACTOR_STATE_STRINGS;
|
extern SDL_PropertiesID REGISTRY_ACTOR_STATE_STRINGS;
|
||||||
|
extern SDL_PropertiesID REGISTRY_FONT;
|
||||||
|
extern SDL_PropertiesID REGISTRY_MUSIC;
|
||||||
|
|
||||||
akerr_ErrorContext AKERR_NOIGNORE *registry_init();
|
akerr_ErrorContext AKERR_NOIGNORE *registry_init();
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *registry_init_music();
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *registry_init_font();
|
||||||
akerr_ErrorContext AKERR_NOIGNORE *registry_init_actor();
|
akerr_ErrorContext AKERR_NOIGNORE *registry_init_actor();
|
||||||
akerr_ErrorContext AKERR_NOIGNORE *registry_init_sprite();
|
akerr_ErrorContext AKERR_NOIGNORE *registry_init_sprite();
|
||||||
akerr_ErrorContext AKERR_NOIGNORE *registry_init_spritesheet();
|
akerr_ErrorContext AKERR_NOIGNORE *registry_init_spritesheet();
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ akerr_ErrorContext *character_load_json(char *filename)
|
|||||||
);
|
);
|
||||||
CATCH(errctx, character_load_json_inner(json, obj));
|
CATCH(errctx, character_load_json_inner(json, obj));
|
||||||
CATCH(errctx, get_json_integer_value(json, "movementspeed", (int *)&obj->movementspeed));
|
CATCH(errctx, get_json_integer_value(json, "movementspeed", (int *)&obj->movementspeed));
|
||||||
obj->movementspeed = obj->movementspeed * 1000000;
|
obj->movementspeed = obj->movementspeed * TIME_ONESEC_MS;
|
||||||
CATCH(errctx, get_json_number_value(json, "velocity_x", &obj->vx));
|
CATCH(errctx, get_json_number_value(json, "velocity_x", &obj->vx));
|
||||||
CATCH(errctx, get_json_number_value(json, "velocity_y", &obj->vy));
|
CATCH(errctx, get_json_number_value(json, "velocity_y", &obj->vy));
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
|
|||||||
27
src/game.c
27
src/game.c
@@ -1,6 +1,7 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <SDL3_image/SDL_image.h>
|
#include <SDL3_image/SDL_image.h>
|
||||||
#include <SDL3_mixer/SDL_mixer.h>
|
#include <SDL3_mixer/SDL_mixer.h>
|
||||||
|
#include <SDL3_ttf/SDL_ttf.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <akerror.h>
|
#include <akerror.h>
|
||||||
|
|
||||||
@@ -32,6 +33,9 @@ akerr_ErrorContext AKERR_NOIGNORE *GAME_init()
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
PREPARE_ERROR(errctx);
|
PREPARE_ERROR(errctx);
|
||||||
ATTEMPT {
|
ATTEMPT {
|
||||||
|
game.gameStartTime = SDL_GetTicksNS();
|
||||||
|
game.lastIterTime = game.gameStartTime;
|
||||||
|
game.lastFPSTime = game.gameStartTime;
|
||||||
FAIL_ZERO_BREAK(errctx, strlen((char *)&game.name), AKERR_NULLPOINTER, "Must provide game name");
|
FAIL_ZERO_BREAK(errctx, strlen((char *)&game.name), AKERR_NULLPOINTER, "Must provide game name");
|
||||||
FAIL_ZERO_BREAK(errctx, strlen((char *)&game.version), AKERR_NULLPOINTER, "Must provide game version");
|
FAIL_ZERO_BREAK(errctx, strlen((char *)&game.version), AKERR_NULLPOINTER, "Must provide game version");
|
||||||
FAIL_ZERO_BREAK(errctx, strlen((char *)&game.uri), AKERR_NULLPOINTER, "Must provide game uri");
|
FAIL_ZERO_BREAK(errctx, strlen((char *)&game.uri), AKERR_NULLPOINTER, "Must provide game uri");
|
||||||
@@ -40,6 +44,8 @@ akerr_ErrorContext AKERR_NOIGNORE *GAME_init()
|
|||||||
CATCH(errctx, registry_init_sprite());
|
CATCH(errctx, registry_init_sprite());
|
||||||
CATCH(errctx, registry_init_spritesheet());
|
CATCH(errctx, registry_init_spritesheet());
|
||||||
CATCH(errctx, registry_init_character());
|
CATCH(errctx, registry_init_character());
|
||||||
|
CATCH(errctx, registry_init_font());
|
||||||
|
CATCH(errctx, registry_init_music());
|
||||||
CATCH(errctx, registry_init_actor_state_strings());
|
CATCH(errctx, registry_init_actor_state_strings());
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
@@ -87,9 +93,28 @@ akerr_ErrorContext AKERR_NOIGNORE *GAME_init()
|
|||||||
"Unable to create mixer device: %s",
|
"Unable to create mixer device: %s",
|
||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
|
|
||||||
|
FAIL_ZERO_RETURN(
|
||||||
|
errctx,
|
||||||
|
TTF_Init(),
|
||||||
|
AKERR_SDL,
|
||||||
|
"Couldn't initialize front engine: %s",
|
||||||
|
SDL_GetError());
|
||||||
|
|
||||||
camera.x = 0;
|
camera.x = 0;
|
||||||
camera.y = 0;
|
camera.y = 0;
|
||||||
camera.w = game.screenwidth;
|
camera.w = game.screenwidth;
|
||||||
camera.h = game.screenheight;
|
camera.h = game.screenheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GAME_updateFPS()
|
||||||
|
{
|
||||||
|
SDL_Time curTime;
|
||||||
|
curTime = SDL_GetTicksNS();
|
||||||
|
if ( (curTime - game.lastFPSTime) > TIME_ONESEC_NS ) {
|
||||||
|
game.fps = game.framesSinceUpdate;
|
||||||
|
game.framesSinceUpdate = 0;
|
||||||
|
game.lastFPSTime = curTime;
|
||||||
|
}
|
||||||
|
game.framesSinceUpdate += 1;
|
||||||
|
game.lastIterTime = curTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ SDL_PropertiesID REGISTRY_ACTOR_STATE_STRINGS;
|
|||||||
SDL_PropertiesID REGISTRY_SPRITE;
|
SDL_PropertiesID REGISTRY_SPRITE;
|
||||||
SDL_PropertiesID REGISTRY_SPRITESHEET;
|
SDL_PropertiesID REGISTRY_SPRITESHEET;
|
||||||
SDL_PropertiesID REGISTRY_CHARACTER;
|
SDL_PropertiesID REGISTRY_CHARACTER;
|
||||||
|
SDL_PropertiesID REGISTRY_MUSIC;
|
||||||
|
SDL_PropertiesID REGISTRY_FONT;
|
||||||
|
|
||||||
akerr_ErrorContext *registry_init()
|
akerr_ErrorContext *registry_init()
|
||||||
{
|
{
|
||||||
@@ -21,6 +23,8 @@ akerr_ErrorContext *registry_init()
|
|||||||
CATCH(errctx, registry_init_character());
|
CATCH(errctx, registry_init_character());
|
||||||
CATCH(errctx, registry_init_actor());
|
CATCH(errctx, registry_init_actor());
|
||||||
CATCH(errctx, registry_init_actor_state_strings());
|
CATCH(errctx, registry_init_actor_state_strings());
|
||||||
|
CATCH(errctx, registry_init_font());
|
||||||
|
CATCH(errctx, registry_init_music());
|
||||||
} CLEANUP {
|
} CLEANUP {
|
||||||
} PROCESS(errctx) {
|
} PROCESS(errctx) {
|
||||||
} FINISH(errctx, true);
|
} FINISH(errctx, true);
|
||||||
@@ -35,6 +39,22 @@ akerr_ErrorContext *registry_init_actor()
|
|||||||
SUCCEED_RETURN(errctx);
|
SUCCEED_RETURN(errctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext AKERR_NOIGNORE *registry_init_font()
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
REGISTRY_FONT = SDL_CreateProperties();
|
||||||
|
FAIL_ZERO_RETURN(errctx, REGISTRY_FONT, AKERR_NULLPOINTER, "Error initializing font registry");
|
||||||
|
SUCCEED_RETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
akerr_ErrorContext *registry_init_music()
|
||||||
|
{
|
||||||
|
PREPARE_ERROR(errctx);
|
||||||
|
REGISTRY_MUSIC = SDL_CreateProperties();
|
||||||
|
FAIL_ZERO_RETURN(errctx, REGISTRY_MUSIC, AKERR_NULLPOINTER, "Error initializing music registry");
|
||||||
|
SUCCEED_RETURN(errctx);
|
||||||
|
}
|
||||||
|
|
||||||
akerr_ErrorContext *registry_init_actor_state_strings()
|
akerr_ErrorContext *registry_init_actor_state_strings()
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ akerr_ErrorContext *sprite_load_json(char *filename)
|
|||||||
CATCH(errctx, get_json_integer_value((json_t *)json, "width", &obj->width));
|
CATCH(errctx, get_json_integer_value((json_t *)json, "width", &obj->width));
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)json, "height", &obj->height));
|
CATCH(errctx, get_json_integer_value((json_t *)json, "height", &obj->height));
|
||||||
CATCH(errctx, get_json_integer_value((json_t *)json, "speed", (int *)&obj->speed));
|
CATCH(errctx, get_json_integer_value((json_t *)json, "speed", (int *)&obj->speed));
|
||||||
obj->speed = obj->speed * 1000000;
|
obj->speed = obj->speed * TIME_ONESEC_MS;
|
||||||
CATCH(errctx, get_json_boolean_value((json_t *)json, "loop", &obj->loop));
|
CATCH(errctx, get_json_boolean_value((json_t *)json, "loop", &obj->loop));
|
||||||
CATCH(errctx, get_json_boolean_value((json_t *)json, "loopReverse", &obj->loopReverse));
|
CATCH(errctx, get_json_boolean_value((json_t *)json, "loopReverse", &obj->loopReverse));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user