diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Api.h | 71 | ||||
-rw-r--r-- | src/Level.cpp | 108 | ||||
-rw-r--r-- | src/Level.h | 45 | ||||
-rw-r--r-- | src/main.cpp | 83 |
4 files changed, 307 insertions, 0 deletions
diff --git a/src/Api.h b/src/Api.h new file mode 100644 index 0000000..da763c2 --- /dev/null +++ b/src/Api.h @@ -0,0 +1,71 @@ +#ifndef DNG_API_H +#define DNG_API_H + +#include "Level.h" +#include <lua.hpp> +#include <memory> + +extern std::shared_ptr<Level> lvl; + +static int +c_update_player_pos(lua_State* L) +{ + // stack ordering + int dy = static_cast<int>(lua_tonumber(L, -1)); + int dx = static_cast<int>(lua_tonumber(L, -2)); + + bool res = false; + + if (lvl->canStep(dx, dy)) { + lvl->player.x += dx; + lvl->player.y += dy; + res = true; + } + + lua_pushboolean(L, res); + + return 1; +} + +static int +c_player_can_move(lua_State* L) +{ + // stack ordering + int dy = static_cast<int>(lua_tonumber(L, -1)); + int dx = static_cast<int>(lua_tonumber(L, -2)); + + bool res = lvl->canStep(dx, dy); + lua_pushboolean(L, res); + + return 1; +} + +static int +c_enemy_can_move(lua_State* L) +{ + return 1; +} + +static int +c_spawn_enemy(lua_State* L) +{ + return 1; +} + +static int +c_destroy_enemy(lua_State* L) +{ + return 1; +} + +static void +init_c_api(lua_State* L) +{ + lua_register(L, "c_update_player_pos", c_update_player_pos); + lua_register(L, "c_player_can_move", c_player_can_move); + lua_register(L, "c_enemy_can_move", c_enemy_can_move); + lua_register(L, "c_spawn_enemy", c_spawn_enemy); + lua_register(L, "c_destroy_enemy", c_destroy_enemy); +} + +#endif // DNG_API_H
\ No newline at end of file diff --git a/src/Level.cpp b/src/Level.cpp new file mode 100644 index 0000000..013c2a1 --- /dev/null +++ b/src/Level.cpp @@ -0,0 +1,108 @@ +#include "Level.h" +#include <fstream> +#include <iostream> +#include <string> + +void +Level::loadLevelFromFile(const char* filePath) +{ + std::ifstream mapFile(filePath); + if (mapFile.is_open()) { + + // each element in the map has a unique ID + // some magic but player is always 0 + const int playerId = 0; + // from 1 -> N each enemy and treasure has its own unique ID + // IDs are unique entirely, not just per enemy or treasure + + + std::string line; + int y = 0; + while (std::getline(mapFile, line)) { + this->map.emplace_back(); + int x = 0; + for (char c : line) { + if (c == WALL_TKN) { + this->map[y].push_back(WALL_SPACE); + } else if (c == EMPTY_TKN) { + this->map[y].push_back(BLANK_SPACE); + } else if (c == ENEMY_TKN) { + this->enemyPositions.push_back( + { .id = this->nextId(), .x = x, .y = y }); + this->map[y].push_back(BLANK_SPACE); + } else if (c == PLAYER_TKN) { + this->player = { .id = playerId, .x = x, .y = y }; + this->map[y].push_back(BLANK_SPACE); + } else if (c == TREASURE_TKN) { + this->treasurePositions.push_back( + { .id = this->nextId(), .x = x, .y = y }); + this->map[y].push_back(BLANK_SPACE); + } else { + continue; + } + ++x; + } + ++y; + } + } + mapFile.close(); +} + +bool +Level::isEmpty(int x, int y) +{ + return map[y][x] == BLANK_SPACE; +} + +bool +Level::canStep(int dx, int dy) +{ + bool res = map[player.y + dy][player.x + dx] != WALL_SPACE; + return res; +} + +void +Level::print() +{ + int x = 0; + int y = 0; + for (auto& row : map) { + for (auto& tile : row) { + bool printed = false; + if (player.x == x && player.y == y) { + std::cout << "p"; + printed = true; + } + for (auto pos : enemyPositions) { + if (pos.x == x && pos.y == y) { + std::cout << "e"; + printed = true; + } + } + for (auto pos : treasurePositions) { + if (pos.x == x && pos.y == y) { + std::cout << "t"; + printed = true; + } + } + if (tile == WALL_SPACE) { + std::cout << tile; + printed = true; + } + if (!printed) { + std::cout << " "; + } + std::cout << " "; + ++x; + } + std::cout << "\n"; + ++y; + x = 0; + } +} + +int +Level::nextId() +{ + return idCounter++; +}
\ No newline at end of file diff --git a/src/Level.h b/src/Level.h new file mode 100644 index 0000000..1607f0c --- /dev/null +++ b/src/Level.h @@ -0,0 +1,45 @@ +#ifndef DNG_LEVEL_H +#define DNG_LEVEL_H + +static const char PLAYER_TKN = 'p'; +static const char WALL_TKN = 'w'; +static const char EMPTY_TKN = '0'; +static const char TREASURE_TKN = 't'; +static const char ENEMY_TKN = 'e'; +static const char BLANK_SPACE = '\0'; +static const char WALL_SPACE = '#'; + +#include <memory> +#include <vector> + +struct Pos +{ + int id; + int x; + int y; +} typedef Coord; + +class Level +{ + +public: + void loadLevelFromFile(const char* filePath); + + bool isEmpty(int x, int y); + + bool canStep(int dx, int dy); + + void print(); + + int nextId(); + + std::vector<std::vector<char>> map; + Pos player; + std::vector<Pos> enemyPositions; + std::vector<Pos> treasurePositions; + +private: + int idCounter = 1; // defaults at 1 (player always 0) +}; + +#endif // DNG_LEVEL_H diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..fb61369 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,83 @@ +#include "Api.h" +#include "Level.h" +#include <SFML/Graphics.hpp> +#include <filesystem> +#include <iostream> +#include <lua.hpp> +#include <memory> + +const char* DEFAULT_PROC = "include/default_proc.lua"; +std::shared_ptr<Level> lvl = std::make_shared<Level>(); + +bool +call_onkeypress(lua_State* L, char pressedKey); + +int +main(int argc, char** argv) +{ + + if (argc <= 1) { + return -1; + } + + std::string lvl_pfx = argv[1]; + + std::filesystem::path mapFile{ lvl_pfx + "/dng.map" }; + std::filesystem::path luaFile{ lvl_pfx + "/proc.lua" }; + + lvl->loadLevelFromFile(mapFile.c_str()); + + lua_State* L_lvl = luaL_newstate(); + luaL_openlibs(L_lvl); + init_c_api(L_lvl); + + lua_State* L_default = luaL_newstate(); + luaL_openlibs(L_default); + init_c_api(L_default); + + if (std::filesystem::exists(luaFile) && + luaL_dofile(L_default, DEFAULT_PROC) != LUA_OK) { + std::cout << "Failed to load default proc" << std::endl; + luaL_error(L_default, "Error: %s", lua_tostring(L_default, -1)); + return EXIT_FAILURE; + } + + if (std::filesystem::exists(luaFile) && + luaL_dofile(L_lvl, luaFile.c_str()) != LUA_OK) { + std::cout << "[C] No Good" << std::endl; + luaL_error(L_lvl, "Error: %s\n", lua_tostring(L_lvl, -1)); + return EXIT_FAILURE; + } + + bool quit = false; + + char in; + + do { + lvl->print(); + std::cin >> in; + if (!call_onkeypress(L_default, in)) { + quit = true; + } + if (!quit && in == 'q') { + quit = true; + } + } while (!quit); + + std::cout << "[C] Quit" << std::endl; + + 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; +}
\ No newline at end of file |