From 87a53f2a09a204ca9bcdde9c73db414c79075326 Mon Sep 17 00:00:00 2001 From: Steph Enders Date: Fri, 17 Jun 2022 11:19:51 -0400 Subject: Add scene controls and win/loss scenarios Setup ability to check collisions and transition game scene --- src/Api.h | 114 --------------------------------- src/CApi.h | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/LuaApi.h | 89 ++++++++++++++++++++++++++ src/Scene.h | 5 ++ src/main.cpp | 80 +++++++++++------------ 5 files changed, 332 insertions(+), 159 deletions(-) delete mode 100644 src/Api.h create mode 100644 src/CApi.h create mode 100644 src/LuaApi.h create mode 100644 src/Scene.h (limited to 'src') diff --git a/src/Api.h b/src/Api.h deleted file mode 100644 index f9e7e8d..0000000 --- a/src/Api.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef DNG_API_H -#define DNG_API_H - -#include "Level.h" -#include -#include - -extern std::shared_ptr lvl; - -static int c_get_player_position(lua_State *L) { - lua_createtable(L, 0, 2); - lua_pushnumber(L, lvl->player.y + 1); - lua_setfield(L, -2, "y"); - lua_pushnumber(L, lvl->player.x + 1); - lua_setfield(L, -2, "x"); - - return 1; -} - -static int c_move_player(lua_State *L) { - // stack ordering - int dy = static_cast(lua_tonumber(L, -1)); - int dx = static_cast(lua_tonumber(L, -2)); - - bool res = false; - - if (lvl->playerCanStep(dx, dy)) { - lvl->player.x += dx; - lvl->player.y += dy; - res = true; - } - - lua_pushboolean(L, res); - - return 1; -} - -static int c_move_enemy(lua_State *L) { - // stack ordering - int dy = static_cast(lua_tonumber(L, -1)); - int dx = static_cast(lua_tonumber(L, -2)); - int id = static_cast(lua_tonumber(L, -3)); - - int i = lvl->getEnemyIndex(id); - // guard against enemy not found - if (i == -1) { - lua_pushboolean(L, false); - return 1; - } - - bool res = false; - if (lvl->enemyCanStep(lvl->enemyPositions[i], dx, dy)) { - lvl->enemyPositions[i].x += dx; - lvl->enemyPositions[i].y += dy; - res = true; - } - - lua_pushboolean(L, res); - - return 1; -} - -static int c_get_enemies(lua_State *L) { - lua_createtable(L, int(lvl->enemyPositions.size()), 0); - - int idx = 0; - - for (auto &pos : lvl->enemyPositions) { - lua_pushnumber(L, ++idx); - lua_createtable(L, 0, 3); - lua_pushnumber(L, pos.id); - lua_setfield(L, -2, "id"); - lua_pushnumber(L, pos.x + 1); - lua_setfield(L, -2, "x"); - lua_pushnumber(L, pos.y + 1); - lua_setfield(L, -2, "y"); - lua_settable(L, -3); - } - - return 1; -} - -static int c_spawn_enemy(lua_State *L) { return 1; } - -static int c_destroy_enemy(lua_State *L) { return 1; } - -static int c_get_map(lua_State *L) { - lua_createtable(L, int(lvl->map.size()), 0); - int idx = 0; - for (auto &vec : lvl->map) { - lua_pushnumber(L, ++idx); - lua_createtable(L, int(vec.size()), 0); - int inner_idx = 0; - for (auto &c : vec) { - lua_pushnumber(L, ++inner_idx); - lua_pushnumber(L, c == WALL_SPACE ? 1 : 0); - lua_rawset(L, -3); - } - lua_rawset(L, -3); - } - return 1; -} - -static void init_c_api(lua_State *L) { - lua_register(L, "c_move_player", c_move_player); - lua_register(L, "c_move_enemy", c_move_enemy); - lua_register(L, "c_spawn_enemy", c_spawn_enemy); - lua_register(L, "c_destroy_enemy", c_destroy_enemy); - lua_register(L, "c_get_enemies", c_get_enemies); - lua_register(L, "c_get_player_position", c_get_player_position); - lua_register(L, "c_get_map", c_get_map); -} - -#endif // DNG_API_H \ No newline at end of file diff --git a/src/CApi.h b/src/CApi.h new file mode 100644 index 0000000..651cc13 --- /dev/null +++ b/src/CApi.h @@ -0,0 +1,203 @@ +#ifndef DNG_CAPI_H +#define DNG_CAPI_H + +#include "Level.h" +#include "Scene.h" +#include +#include + +extern std::shared_ptr lvl; +extern Scene scene; + +/* + * c_get_player_position(int x, int y) + */ +static int c_get_player_position(lua_State *L) { + lua_createtable(L, 0, 2); + lua_pushnumber(L, lvl->player.y + 1); + lua_setfield(L, -2, "y"); + lua_pushnumber(L, lvl->player.x + 1); + lua_setfield(L, -2, "x"); + + return 1; +} + +/* + * c_move_player(int dx, int dy) + */ +static int c_move_player(lua_State *L) { + // stack ordering + int dy = static_cast(lua_tonumber(L, -1)); + int dx = static_cast(lua_tonumber(L, -2)); + + if (lvl->playerCanStep(dx, dy)) { + lvl->player.x += dx; + lvl->player.y += dy; + } + + lua_createtable(L, 0, 2); + lua_pushnumber(L, lvl->player.y + 1); + lua_setfield(L, -2, "y"); + lua_pushnumber(L, lvl->player.x + 1); + lua_setfield(L, -2, "x"); + + return 1; +} + +/* + * c_move_enemy(int id, int dx, int dy) + */ +static int c_move_enemy(lua_State *L) { + // stack ordering + int dy = static_cast(lua_tonumber(L, -1)); + int dx = static_cast(lua_tonumber(L, -2)); + int id = static_cast(lua_tonumber(L, -3)); + + int i = lvl->getEnemyIndex(id); + // guard against enemy not found + if (i == -1) { + return 1; + } + + if (lvl->enemyCanStep(lvl->enemyPositions[i], dx, dy)) { + lvl->enemyPositions[i].x += dx; + lvl->enemyPositions[i].y += dy; + } + lua_createtable(L, 0, 3); + lua_pushnumber(L, lvl->enemyPositions[i].y + 1); + lua_setfield(L, -2, "y"); + lua_pushnumber(L, lvl->enemyPositions[i].x + 1); + lua_setfield(L, -2, "x"); + lua_pushnumber(L, lvl->enemyPositions[i].id); + lua_setfield(L, -2, "id"); + + return 1; +} + +/* + * c_get_enemies() + */ +static int c_get_enemies(lua_State *L) { + lua_createtable(L, int(lvl->enemyPositions.size()), 0); + + int idx = 0; + + for (auto &pos : lvl->enemyPositions) { + lua_pushnumber(L, ++idx); + lua_createtable(L, 0, 3); + lua_pushnumber(L, pos.id); + lua_setfield(L, -2, "id"); + lua_pushnumber(L, pos.x + 1); + lua_setfield(L, -2, "x"); + lua_pushnumber(L, pos.y + 1); + lua_setfield(L, -2, "y"); + lua_settable(L, -3); + } + + return 1; +} + +/* + * c_spawn_enemy(int x, int y) + */ +static int c_spawn_enemy(lua_State *L) { return 1; } + +/* + * c_destroy_enemy(int id) + */ +static int c_destroy_enemy(lua_State *L) { return 1; } + +/* + * c_get_map() + */ +static int c_get_map(lua_State *L) { + lua_createtable(L, int(lvl->map.size()), 0); + int idx = 0; + for (auto &vec : lvl->map) { + lua_pushnumber(L, ++idx); + lua_createtable(L, int(vec.size()), 0); + int inner_idx = 0; + for (auto &c : vec) { + lua_pushnumber(L, ++inner_idx); + lua_pushnumber(L, c == WALL_SPACE ? 1 : 0); + lua_rawset(L, -3); + } + lua_rawset(L, -3); + } + return 1; +} + +/* + * c_trigger_level_start() + */ +static int c_trigger_level_start(lua_State *L) { + scene = Scene::LEVEL; + lua_pushboolean(L, true); + return 1; +} +/* + * c_trigger_win() + */ +static int c_trigger_win(lua_State *L) { + scene = Scene::WIN; + lua_pushboolean(L, true); + return 1; +} + +/* + * c_trigger_loss() + */ +static int c_trigger_loss(lua_State *L) { + scene = Scene::LOSS; + lua_pushboolean(L, true); + return 1; +} + +static int c_get_scene(lua_State *L) { + lua_pushnumber(L, scene); + return 1; +} + +static int c_get_treasures(lua_State *L) { + lua_createtable(L, static_cast(lvl->treasurePositions.size()), 0); + int idx = 0; + for (auto &t : lvl->treasurePositions) { + lua_pushnumber(L, ++idx); + lua_createtable(L, 0, 3); + lua_pushnumber(L, t.y + 1); + lua_setfield(L, -2, "y"); + lua_pushnumber(L, t.x + 1); + lua_setfield(L, -2, "x"); + lua_pushnumber(L, t.id); + lua_setfield(L, -2, "id"); + lua_settable(L, -3); + } + return 1; +} + +static int c_score_treasure(lua_State *L) { + int id = static_cast(lua_tonumber(L, -1)); + + erase_if(lvl->treasurePositions, [id](Pos t) { return t.id == id; }); + + return 1; +} + +// not for lua use +void init_c_api(lua_State *L) { + lua_register(L, "c_move_player", c_move_player); + lua_register(L, "c_move_enemy", c_move_enemy); + lua_register(L, "c_spawn_enemy", c_spawn_enemy); + lua_register(L, "c_destroy_enemy", c_destroy_enemy); + lua_register(L, "c_get_enemies", c_get_enemies); + lua_register(L, "c_get_player_position", c_get_player_position); + lua_register(L, "c_get_map", c_get_map); + lua_register(L, "c_trigger_level_start", c_trigger_level_start); + lua_register(L, "c_trigger_win", c_trigger_win); + lua_register(L, "c_trigger_loss", c_trigger_loss); + lua_register(L, "c_get_scene", c_get_scene); + lua_register(L, "c_score_treasure", c_score_treasure); + lua_register(L, "c_get_treasures", c_get_treasures); +} + +#endif // DNG_CAPI_H \ No newline at end of file diff --git a/src/LuaApi.h b/src/LuaApi.h new file mode 100644 index 0000000..cb68e36 --- /dev/null +++ b/src/LuaApi.h @@ -0,0 +1,89 @@ +#ifndef DNG_LUA_API_H +#define DNG_LUA_API_H + +#include +#include + +struct LState { + lua_State *onkeypress; + lua_State *onupdate; + lua_State *onintro; + lua_State *onwin; + lua_State *onloss; +} typedef LState; + +const char *ON_KEYPRESS = "onKeypress"; +const char *ON_UPDATE = "onUpdate"; +const char *ON_INTRO = "onIntro"; +const char *ON_WIN = "onWin"; +const char *ON_LOSS = "onLoss"; + +LState *init_default(lua_State *L) { + auto *state = static_cast(malloc(sizeof(LState))); + + state->onkeypress = L; + state->onupdate = L; + state->onintro = L; + state->onwin = L; + state->onloss = L; + + return state; +} + +bool check_fn(lua_State *L, const char *fn) { + lua_getglobal(L, fn); + return lua_isfunction(L, -1); +} + +void override_file_fns(lua_State *L, LState *state) { + if (check_fn(L, ON_KEYPRESS)) { + state->onkeypress = L; + } + if (check_fn(L, ON_UPDATE)) { + state->onupdate = L; + } + if (check_fn(L, ON_INTRO)) { + state->onintro = L; + } + if (check_fn(L, ON_WIN)) { + state->onwin = L; + } + if (check_fn(L, ON_LOSS)) { + state->onloss = L; + } +} + +bool lua_dofn(lua_State *L, const char *fn) { + lua_getglobal(L, fn); + if (!lua_isfunction(L, -1)) { + std::cout << "[C] Error " << fn << " not function | not found" << std::endl; + return false; + } + lua_pcall(L, 0, 1, 0); + return true; +} + +bool lua_dofn_with_key(lua_State *L, const char *fn, char pressedKey) { + lua_getglobal(L, fn); + if (!lua_isfunction(L, -1)) { + std::cout << "[C] Error " << fn << " not function | not found" << std::endl; + return false; + } + lua_pushinteger(L, pressedKey); + lua_pcall(L, 1, 1, 0); + return true; +} + +bool lua_onkeypress(lua_State *L, char pressedKey) { + return lua_dofn_with_key(L, "onKeyPress", pressedKey); +} + +bool lua_onupdate(lua_State *L) { return lua_dofn(L, "onUpdate"); } + +bool lua_onintro(lua_State *L) { return lua_dofn(L, "onIntro"); } + +bool lua_onwin(lua_State *L) { return lua_dofn(L, "onWin"); } + +bool lua_onloss(lua_State *L) { return lua_dofn(L, "onLoss"); } + +#endif // DNG_LUA_API_H \ No newline at end of file diff --git a/src/Scene.h b/src/Scene.h new file mode 100644 index 0000000..dab51c5 --- /dev/null +++ b/src/Scene.h @@ -0,0 +1,5 @@ +#ifndef DNG_SCENE_H +#define DNG_SCENE_H +/* sync with constants.lua */ +enum Scene { INTRO, LEVEL, WIN, LOSS }; +#endif // DNG_SCENE_H diff --git a/src/main.cpp b/src/main.cpp index eef9777..a9b5d3b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,20 +1,16 @@ -#include "Api.h" +#include "CApi.h" #include "Level.h" +#include "LuaApi.h" #include #include #include #include const char *DEFAULT_PROC = "include/defaults.lua"; -std::shared_ptr lvl; -struct LState { - lua_State *onkeypress; - lua_State *onupdate; -} typedef LState; +std::shared_ptr lvl; -bool call_onkeypress(lua_State *L, char pressedKey); -bool call_onupdate(lua_State *L); +Scene scene; int main(int argc, char **argv) { @@ -28,6 +24,7 @@ int main(int argc, char **argv) { std::filesystem::path luaFile{lvl_pfx + "/proc.lua"}; lvl = std::make_shared(); + scene = Scene::INTRO; lvl->loadLevelFromFile(mapFile.c_str()); @@ -47,20 +44,11 @@ int main(int argc, char **argv) { } // Initialize to default - LState l_state = {.onkeypress = L_default, .onupdate = L_default}; + LState *l_state = init_default(L_default); if (std::filesystem::exists(luaFile) && luaL_dofile(L_lvl, luaFile.c_str()) == LUA_OK) { - - // overwrite defaults - lua_getglobal(L_lvl, "onKeyPress"); - if (lua_isfunction(L_lvl, -1)) { - l_state.onkeypress = L_lvl; - } - lua_getglobal(L_lvl, "onUpdate"); - if (lua_isfunction(L_lvl, -1)) { - l_state.onupdate = L_lvl; - } + override_file_fns(L_lvl, l_state); } else if (std::filesystem::exists(luaFile)) { std::cout << "[C] No Good" << std::endl; luaL_error(L_lvl, "Error: %s\n", lua_tostring(L_lvl, -1)); @@ -72,12 +60,35 @@ int main(int argc, char **argv) { char in; do { - lvl->print(); - std::cin >> in; - if (!call_onkeypress(l_state.onkeypress, in)) { + if (scene == Scene::INTRO) { + if (!lua_onintro(l_state->onintro)) { + quit = true; + } + std::cin >> in; + if (!lua_onkeypress(l_state->onkeypress, in)) { + quit = true; + } + } else if (scene == Scene::LEVEL) { + lvl->print(); + + std::cin >> in; + if (!lua_onkeypress(l_state->onkeypress, in)) { + quit = true; + } + if (!lua_onupdate(l_state->onupdate)) { + quit = true; + } + } else if (scene == Scene::WIN) { + lvl->player.x = -1; // hide + lvl->player.y = -1; // hide + lvl->print(); + lua_onwin(l_state->onwin); quit = true; - } - if (!call_onupdate(l_state.onupdate)) { + } else if (scene == Scene::LOSS) { + lvl->player.x = -1; // hide + lvl->player.y = -1; // hide + lvl->print(); + lua_onloss(l_state->onloss); quit = true; } if (!quit && in == 'q') { @@ -89,24 +100,3 @@ int main(int argc, char **argv) { return EXIT_SUCCESS; } - -bool call_onkeypress(lua_State *L, char pressedKey) { - lua_getglobal(L, "onKeyPress"); - if (!lua_isfunction(L, -1)) { - std::cout << "[C] Error onKeyPress not function | not found" << std::endl; - return false; - } - lua_pushinteger(L, pressedKey); - lua_pcall(L, 1, 1, 0); - return true; -} - -bool call_onupdate(lua_State *L) { - lua_getglobal(L, "onUpdate"); - if (!lua_isfunction(L, -1)) { - std::cout << "[C] Error onUpdate not function | not found" << std::endl; - return false; - } - lua_pcall(L, 0, 1, 0); - return true; -} \ No newline at end of file -- cgit v1.2.3-54-g00ecf