diff --git a/basic1.cpp b/basic1.cpp index 637dbb2..54ed79a 100644 --- a/basic1.cpp +++ b/basic1.cpp @@ -520,6 +520,14 @@ int main() } needs_refresh = true; } + } else if (launcher.is_game_selected()) { + // No input, but check if game wants continuous updates + current_game = launcher.get_selected_game(); + if (current_game->wants_frame_updates()) { + // Send frame tick event for animation/physics updates + InputEvent frame_tick = {INPUT_FRAME_TICK, 0, 0, 0, 0, 0, true}; + needs_refresh = current_game->update(frame_tick); + } } // 4. Redraw and queue async refresh on Core 1 diff --git a/emulator/game.h b/emulator/game.h index ab4a72c..df33ea9 100644 --- a/emulator/game.h +++ b/emulator/game.h @@ -15,6 +15,7 @@ public: virtual bool update(const InputEvent& event) = 0; virtual void draw() = 0; virtual bool wants_to_exit() const { return false; } + virtual bool wants_frame_updates() const { return false; } // Public members for Lua bindings access uint16_t width; diff --git a/emulator/lua_game_emulator.cpp b/emulator/lua_game_emulator.cpp index 62515eb..24c808e 100644 --- a/emulator/lua_game_emulator.cpp +++ b/emulator/lua_game_emulator.cpp @@ -171,7 +171,17 @@ bool LuaGame::wants_to_exit() const { return exit; } - +bool LuaGame::wants_frame_updates() const { + if (!L) return false; + + // Check registry for frame updates flag + lua_pushstring(L, "__wants_frame_updates"); + lua_gettable(L, LUA_REGISTRYINDEX); + bool wants_updates = lua_toboolean(L, -1); + lua_pop(L, 1); + + return wants_updates; +} bool LuaGame::call_lua_function(const char* func_name, int nargs, int nresults) { int result = lua_pcall(L, nargs, nresults, 0); if (result != LUA_OK) { diff --git a/emulator/main.cpp b/emulator/main.cpp index 71072cc..c33bf69 100644 --- a/emulator/main.cpp +++ b/emulator/main.cpp @@ -107,6 +107,17 @@ int main() { needs_redraw = true; } } + } else if (launcher.is_game_selected()) { + // No user input, but check if game wants frame tick updates + current_game = launcher.get_selected_game(); + if (current_game->wants_frame_updates()) { + InputEvent frame_event = {INPUT_FRAME_TICK, 0, 0, 0, 0, 0, true}; + needs_redraw = current_game->update(frame_event) || needs_redraw; + if (current_game->wants_to_exit()) { + launcher.reset(); + needs_redraw = true; + } + } } // Always redraw every frame for emulator diff --git a/games/lua_bindings.cpp b/games/lua_bindings.cpp index 84137ce..3748225 100644 --- a/games/lua_bindings.cpp +++ b/games/lua_bindings.cpp @@ -186,6 +186,21 @@ static int lua_game_exit(lua_State* L) { return 0; } +// game.set_frame_updates(enabled) - enable/disable continuous frame tick events +static int lua_game_set_frame_updates(lua_State* L) { + LuaGame* game = get_game(L); + if (!game) return 0; + + bool enabled = lua_toboolean(L, 1); + + // Set frame updates flag (will be checked in wants_frame_updates()) + lua_pushstring(L, "__wants_frame_updates"); + lua_pushboolean(L, enabled); + lua_settable(L, LUA_REGISTRYINDEX); + + return 0; +} + // ============================================================================ // INPUT TYPE CONSTANTS // ============================================================================ @@ -283,6 +298,10 @@ void lua_bindings_register(lua_State* L, LuaGame* game) { lua_pushcfunction(L, lua_game_exit); lua_settable(L, -3); + lua_pushstring(L, "set_frame_updates"); + lua_pushcfunction(L, lua_game_set_frame_updates); + lua_settable(L, -3); + // Create empty vars table for persistent state lua_pushstring(L, "vars"); lua_newtable(L); diff --git a/games/lua_examples/ball.lua b/games/lua_examples/ball.lua index eff1fc6..737c18b 100644 --- a/games/lua_examples/ball.lua +++ b/games/lua_examples/ball.lua @@ -14,6 +14,9 @@ function init() game.vars.radius = 10 game.vars.frame_count = 0 + -- Enable continuous frame updates for smooth animation + game.set_frame_updates(true) + print("Bouncing Ball initialized") end @@ -28,8 +31,8 @@ function update(event) return true end - -- Update physics if running - if game.vars.state == STATE_RUNNING then + -- Update physics if running (on any frame tick) + if event.type == INPUT.FRAME_TICK and game.vars.state == STATE_RUNNING then -- Move ball game.vars.ball_x = game.vars.ball_x + game.vars.vel_x game.vars.ball_y = game.vars.ball_y + game.vars.vel_y diff --git a/games/lua_game.cpp b/games/lua_game.cpp index a93c129..3875776 100644 --- a/games/lua_game.cpp +++ b/games/lua_game.cpp @@ -193,6 +193,18 @@ bool LuaGame::wants_to_exit() const { return exit; } +bool LuaGame::wants_frame_updates() const { + if (!L) return false; + + // Check if Lua script wants continuous frame updates + lua_pushstring(L, "__wants_frame_updates"); + lua_gettable(L, LUA_REGISTRYINDEX); + bool wants_updates = lua_toboolean(L, -1); + lua_pop(L, 1); + + return wants_updates; +} + bool LuaGame::call_lua_function(const char* func_name, int nargs, int nresults) { int result = lua_pcall(L, nargs, nresults, 0); if (result != LUA_OK) { diff --git a/games/lua_game.h b/games/lua_game.h index 6da1c8d..ae72e40 100644 --- a/games/lua_game.h +++ b/games/lua_game.h @@ -64,6 +64,12 @@ public: */ bool wants_to_exit() const override; + /** + * @brief Check if game wants continuous frame updates + * @return true if Lua script set __wants_frame_updates flag + */ + bool wants_frame_updates() const override; + /** * @brief Get Lua state for bindings access */ diff --git a/lib/game.h b/lib/game.h index 3ac4e32..fe494ef 100644 --- a/lib/game.h +++ b/lib/game.h @@ -94,6 +94,17 @@ public: */ virtual bool wants_to_exit() const { return false; } + /** + * @brief Check if game wants continuous frame updates + * + * Games that need animation or continuous updates (like physics simulations) + * can override this to return true. They will receive INPUT_FRAME_TICK events + * every frame, even without user input. + * + * @return true if game needs frame updates, false for event-driven only + */ + virtual bool wants_frame_updates() const { return false; } + /** * @brief Get the type of game for safe downcasting without RTTI */ diff --git a/lib/input_event.h b/lib/input_event.h index b24d7ef..c39ac2a 100644 --- a/lib/input_event.h +++ b/lib/input_event.h @@ -17,7 +17,8 @@ enum InputType { INPUT_TOUCH_UP, INPUT_BUTTON_0, INPUT_BUTTON_1, - INPUT_GESTURE + INPUT_GESTURE, + INPUT_FRAME_TICK // Sent every frame for animation/continuous updates }; // Unified input event structure