From 5637fa18c82a4a3d68c33a4e28ae2d591e46cc92 Mon Sep 17 00:00:00 2001 From: asrael Date: Tue, 11 Nov 2025 23:26:51 -0600 Subject: [PATCH] add fps util for pxl8 in lua --- README.md | 1 + demo/mod/worldgen.fnl | 89 ++++++++++-------------------- src/lua/pxl8.lua | 5 ++ src/pxl8.c | 5 ++ src/pxl8_game.h | 1 + src/pxl8_script.c | 11 ++++ src/pxl8_script.h | 1 + src/pxl8_sdl3.c | 3 - tools/aseprite/tile-props/main.lua | 17 +----- 9 files changed, 57 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index 9523bbb..d68f117 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ ./pxl8.sh run [game.cart | project_dir] # Run pxl8 demo (or a specific game) ./pxl8.sh run [game.cart | project_dir] --repl # Run pxl8 demo (or a specific game) with a REPL ``` +**Note** The demo has keys 1-9 bound for different examples. > [!WARNING] > Heavy development. So... here be dragons :3 diff --git a/demo/mod/worldgen.fnl b/demo/mod/worldgen.fnl index d2ec8a3..1cbef1a 100644 --- a/demo/mod/worldgen.fnl +++ b/demo/mod/worldgen.fnl @@ -1,18 +1,12 @@ (local pxl8 (require :pxl8)) -(local debug-ui (require :mod.debug_ui)) (var world nil) (var cam-x 1000) -(var cam-y 64) +(local cam-y 64) (var cam-z 1000) (var cam-yaw 0) (var cam-pitch 0) (var bob-time 0) -(var show-debug-ui false) -(var affine false) -(var fps 0) -(var fps-accumulator 0) -(var fps-frame-count 0) (local move-speed 200) (local turn-speed 2.0) @@ -33,51 +27,38 @@ :iterations 4})] (if (< result 0) (pxl8.error (.. "Failed to generate cave - result: " result)) - (do - (let [floor-tex (pxl8.procgen_tex {:name "floor" - :seed 11111 - :width 64 - :height 64 - :base_color 20}) - ceiling-tex (pxl8.procgen_tex {:name "ceiling" - :seed 22222 - :width 64 - :height 64 - :base_color 0}) - wall-tex (pxl8.procgen_tex {:name "wall" - :seed 12345 - :width 64 - :height 64 - :base_color 4})] + (let [floor-tex (pxl8.procgen_tex {:name "floor" + :seed 11111 + :width 64 + :height 64 + :base_color 19}) + ceiling-tex (pxl8.procgen_tex {:name "ceiling" + :seed 22222 + :width 64 + :height 64 + :base_color 1}) + wall-tex (pxl8.procgen_tex {:name "wall" + :seed 12345 + :width 64 + :height 64 + :base_color 4})] - (pxl8.upload_atlas) + (pxl8.upload_atlas) - (let [result (pxl8.world_apply_textures world [ - {:name "floor" - :texture_id floor-tex - :rule (fn [normal] (> normal.y 0.7))} - {:name "ceiling" - :texture_id ceiling-tex - :rule (fn [normal] (< normal.y -0.7))} - {:name "wall" - :texture_id wall-tex - :rule (fn [normal] (and (<= normal.y 0.7) (>= normal.y -0.7)))}])] - (when (< result 0) - (pxl8.error (.. "Failed to apply textures - result: " result))))))))) + (let [result (pxl8.world_apply_textures world [ + {:name "floor" + :texture_id floor-tex + :rule (fn [normal] (> normal.y 0.7))} + {:name "ceiling" + :texture_id ceiling-tex + :rule (fn [normal] (< normal.y -0.7))} + {:name "wall" + :texture_id wall-tex + :rule (fn [normal] (and (<= normal.y 0.7) (>= normal.y -0.7)))}])] + (when (< result 0) + (pxl8.error (.. "Failed to apply textures - result: " result)))))))) (fn update [dt] - (set fps-accumulator (+ fps-accumulator dt)) - (set fps-frame-count (+ fps-frame-count 1)) - - (when (>= fps-accumulator 0.25) - (set fps (/ fps-frame-count fps-accumulator)) - (set fps-accumulator 0) - (set fps-frame-count 0)) - - (when (pxl8.key_pressed "F8") - (set show-debug-ui (not show-debug-ui)) - (pxl8.ui_window_set_open "Debug Menu (F8)" show-debug-ui)) - (when (pxl8.world_is_loaded world) (let [forward-x (- (math.sin cam-yaw)) forward-z (- (math.cos cam-yaw)) @@ -166,22 +147,12 @@ (pxl8.set_model (pxl8.mat4_identity)) - (pxl8.set_affine_textures affine) (pxl8.world_render world [cam-x eye-y cam-z]) (pxl8.text (.. "Pos: " (string.format "%.0f" cam-x) "," (string.format "%.0f" cam-y) "," (string.format "%.0f" cam-z)) 10 25 12) - - (let [new-state (debug-ui.render {:show-debug-ui show-debug-ui - :fps fps - :wireframe false - :auto-rotate false - :orthographic false - :use-texture true - :affine affine})] - (when (not= new-state.show-debug-ui nil) (set show-debug-ui new-state.show-debug-ui)) - (when (not= new-state.affine nil) (set affine new-state.affine)))))) + (pxl8.text (.. "FPS: " (string.format "%.1f" (pxl8.get_fps))) 10 40 12)))) {:init init :update update diff --git a/src/lua/pxl8.lua b/src/lua/pxl8.lua index a44d90c..7b6d540 100644 --- a/src/lua/pxl8.lua +++ b/src/lua/pxl8.lua @@ -1,5 +1,6 @@ local ffi = require("ffi") local C = ffi.C +local game = _pxl8_game local gfx = _pxl8_gfx local input = _pxl8_input local ui = _pxl8_ui @@ -46,6 +47,10 @@ function pxl8.sprite(id, x, y, w, h, flip_x, flip_y) C.pxl8_sprite(gfx, id or 0, x or 0, y or 0, w or 16, h or 16, flip_x or false, flip_y or false) end +function pxl8.get_fps() + return C.pxl8_game_get_fps(game) +end + function pxl8.get_width() return C.pxl8_gfx_get_width(gfx) end diff --git a/src/pxl8.c b/src/pxl8.c index 6f7e5ca..5907bbb 100644 --- a/src/pxl8.c +++ b/src/pxl8.c @@ -119,6 +119,7 @@ pxl8_game_result pxl8_init(pxl8_game* game, i32 argc, char* argv[]) { pxl8_script_set_gfx(game->script, game->gfx); pxl8_script_set_input(game->script, &game->input); pxl8_script_set_ui(game->script, game->ui); + pxl8_script_set_game(game->script, game); if (game->script_path[0] != '\0') { pxl8_result result = pxl8_script_load_main(game->script, game->script_path); @@ -307,3 +308,7 @@ void pxl8_quit(pxl8_game* game) { pxl8_script_destroy(game->script); if (game->ui) pxl8_ui_destroy(game->ui); } + +f32 pxl8_game_get_fps(const pxl8_game* game) { + return game ? game->fps : 0.0f; +} diff --git a/src/pxl8_game.h b/src/pxl8_game.h index 0077915..9557806 100644 --- a/src/pxl8_game.h +++ b/src/pxl8_game.h @@ -52,3 +52,4 @@ pxl8_game_result pxl8_init(pxl8_game* game, i32 argc, char* argv[]); pxl8_game_result pxl8_update(pxl8_game* game); pxl8_game_result pxl8_frame(pxl8_game* game); void pxl8_quit(pxl8_game* game); +f32 pxl8_game_get_fps(const pxl8_game* game); diff --git a/src/pxl8_script.c b/src/pxl8_script.c index a391f8e..c97e18d 100644 --- a/src/pxl8_script.c +++ b/src/pxl8_script.c @@ -79,9 +79,12 @@ static const char* pxl8_ffi_cdefs = "typedef float f32;\n" "typedef double f64;\n" "typedef struct pxl8_gfx pxl8_gfx;\n" +"typedef struct pxl8_game pxl8_game;\n" "typedef struct { int x, y, w, h; } pxl8_bounds;\n" "typedef struct { int x, y; } pxl8_point;\n" "\n" +"f32 pxl8_game_get_fps(const pxl8_game* game);\n" +"\n" "i32 pxl8_gfx_get_height(pxl8_gfx* ctx);\n" "i32 pxl8_gfx_get_width(pxl8_gfx* ctx);\n" "void pxl8_circle(pxl8_gfx* ctx, i32 x, i32 y, i32 r, u32 color);\n" @@ -408,6 +411,14 @@ void pxl8_script_set_ui(pxl8_script* script, pxl8_ui* ui) { } } +void pxl8_script_set_game(pxl8_script* script, void* game) { + if (!script) return; + if (script->L && game) { + lua_pushlightuserdata(script->L, game); + lua_setglobal(script->L, "_pxl8_game"); + } +} + static pxl8_result pxl8_script_prepare_path(pxl8_script* script, const char* filename, char* out_basename, size_t basename_size) { char filename_copy[PATH_MAX]; strncpy(filename_copy, filename, sizeof(filename_copy) - 1); diff --git a/src/pxl8_script.h b/src/pxl8_script.h index 8f41fe4..4c7a188 100644 --- a/src/pxl8_script.h +++ b/src/pxl8_script.h @@ -20,6 +20,7 @@ void pxl8_script_set_cart_path(pxl8_script* script, const char* cart_path, const void pxl8_script_set_gfx(pxl8_script* script, pxl8_gfx* gfx); void pxl8_script_set_input(pxl8_script* script, pxl8_input_state* input); void pxl8_script_set_ui(pxl8_script* script, pxl8_ui* ui); +void pxl8_script_set_game(pxl8_script* script, void* game); pxl8_result pxl8_script_call_function(pxl8_script* script, const char* name); pxl8_result pxl8_script_call_function_f32(pxl8_script* script, const char* name, f32 arg); diff --git a/src/pxl8_sdl3.c b/src/pxl8_sdl3.c index a64c184..78ab630 100644 --- a/src/pxl8_sdl3.c +++ b/src/pxl8_sdl3.c @@ -61,9 +61,6 @@ static void* sdl3_create(pxl8_color_mode mode, pxl8_resolution resolution, pxl8_error("Failed to set vsync: %s", SDL_GetError()); } - SDL_SetRenderLogicalPresentation(ctx->renderer, fb_w, fb_h, - SDL_LOGICAL_PRESENTATION_INTEGER_SCALE); - ctx->framebuffer_texture = SDL_CreateTexture(ctx->renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING, diff --git a/tools/aseprite/tile-props/main.lua b/tools/aseprite/tile-props/main.lua index d9634cb..46b6428 100644 --- a/tools/aseprite/tile-props/main.lua +++ b/tools/aseprite/tile-props/main.lua @@ -1,5 +1,5 @@ --- pxl8 tile properties editor --- provides a ui for editing custom properties of tilemap tiles +-- pxl8 tile properties dialog menu +-- provides a ui for editing custom properties on tilemap tiles local DEBUG = false @@ -140,13 +140,11 @@ local function showPropertyEditor(existingProps) option = prop.type, options = { "boolean", "number", "string" }, onchange = function() - -- Save all current field values and apply type conversions for j = 1, #properties do properties[j].key = dlg.data["key_" .. j] or properties[j].key local newType = dlg.data["type_" .. j] or properties[j].type local oldType = properties[j].type - -- Apply default values when type changes if newType ~= oldType then if newType == "boolean" then properties[j].value = false @@ -191,7 +189,6 @@ local function showPropertyEditor(existingProps) id = "delete_" .. i, text = "Delete", onclick = function() - -- Save current field values before deleting for j = 1, #properties do properties[j].key = dlg.data["key_" .. j] or properties[j].key properties[j].type = dlg.data["type_" .. j] or properties[j].type @@ -208,7 +205,6 @@ local function showPropertyEditor(existingProps) dlg:button{ text = "Add Property", onclick = function() - -- Save current field values before adding new property for i = 1, #properties do properties[i].key = dlg.data["key_" .. i] or properties[i].key properties[i].type = dlg.data["type_" .. i] or properties[i].type @@ -254,14 +250,12 @@ local function showPropertyEditor(existingProps) end function init(plugin) - log("=== PLUGIN INIT START ===") - if not plugin then print("[tile-properties] ERROR: plugin is nil!") return end - -- Register in Sprite menu + -- register in sprite menu plugin:newCommand{ id = "TilePropertiesEditor", title = "Tile Properties", @@ -272,12 +266,7 @@ function init(plugin) end, onclick = showPropertyEditor } - - log("Command registered in Sprite menu") - - log("=== PLUGIN INIT COMPLETE ===") end function exit(plugin) - log("=== PLUGIN EXIT ===") end