feature/rla-11_AlgorithmsP1 #12
@@ -23,5 +23,6 @@ Necessary:
|
||||
init_function(map_w, map_h)
|
||||
Should initialize the function fresh with a given width and height.
|
||||
|
||||
update(map)
|
||||
update()
|
||||
Called updates_per_second times per second. Should calculate new map state and draw on the map as needed. The map will have the previous state retained.
|
||||
Returns true if finished, else false
|
||||
|
||||
34
scripts/algorithms/drunk_walk.lua
Normal file
34
scripts/algorithms/drunk_walk.lua
Normal file
@@ -0,0 +1,34 @@
|
||||
require "math"
|
||||
DrunkenWalk = {
|
||||
curr_x = 0,
|
||||
curr_y = 0,
|
||||
map_w = 0,
|
||||
map_h = 0,
|
||||
iterations = 30
|
||||
}
|
||||
|
||||
function DrunkenWalk:initialize(w, h)
|
||||
math.randomseed(os.time())
|
||||
self.map_w = w
|
||||
self.map_h = h
|
||||
visualizer.map:fill(true)
|
||||
self.curr_x = math.random(0, w-1)
|
||||
self.curr_y = math.random(0, h-1);
|
||||
end
|
||||
|
||||
function DrunkenWalk:update()
|
||||
self.curr_x = self.curr_x + math.random(-1, 1)
|
||||
self.curr_y = self.curr_y + math.random(-1, 1)
|
||||
while self.curr_x >= self.map_w or self.curr_x < 0 or self.curr_y >= self.map_h or self.curr_y < 0 do
|
||||
self.curr_x = self.curr_x + math.random(-1, 1)
|
||||
self.curr_y = self.curr_y + math.random(-1, 1)
|
||||
end
|
||||
visualizer.map:draw_floor(self.curr_x, self.curr_y)
|
||||
self.iterations = self.iterations - 1
|
||||
if self.iterations == 0 then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
visualizer.algorithm_manager:register_algorithm("Drunken Walk", function (w, h) DrunkenWalk:initialize(w, h) end, function () return DrunkenWalk:update() end, 5)
|
||||
18
scripts/algorithms/test.lua
Normal file
18
scripts/algorithms/test.lua
Normal file
@@ -0,0 +1,18 @@
|
||||
Test = {}
|
||||
|
||||
function Test.initialize(w, h)
|
||||
visualizer.map:fill(false)
|
||||
for mx = 0, w-1 do
|
||||
for my = 0, h-1 do
|
||||
if mx == 0 or mx == w-1 or my == 0 or my == h-1 then
|
||||
visualizer.map:draw_wall(mx, my)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Test.update()
|
||||
|
||||
end
|
||||
|
||||
visualizer.algorithm_manager:register_algorithm("Test", Test.initialize, Test.update, 1)
|
||||
@@ -11,6 +11,6 @@ std::string LuaContextManager::get_key(std::string args) {
|
||||
// TODO: Switch the arg to a struct and use that to init libraries
|
||||
std::shared_ptr<sol::state> LuaContextManager::load_resource(std::string args) {
|
||||
auto lua = std::make_shared<sol::state>();
|
||||
lua->open_libraries(sol::lib::base, sol::lib::package);
|
||||
lua->open_libraries(sol::lib::base, sol::lib::package, sol::lib::math, sol::lib::os);
|
||||
return lua;
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
//
|
||||
|
||||
#include "algorithmmanager.hpp"
|
||||
#include "../engine/modules/logger.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <fmt/format.h>
|
||||
|
||||
void AlgorithmManager::register_algorithm(std::string name, sol::function initialize, sol::function update,
|
||||
unsigned int updates_per_second) {
|
||||
@@ -19,6 +21,39 @@ void AlgorithmManager::register_algorithm(std::string name, sol::function initia
|
||||
|
||||
}
|
||||
|
||||
ranges::any_view<DungeonAlgorithm> AlgorithmManager::get_algorithms() {
|
||||
return algorithms;
|
||||
ranges::any_view<DungeonAlgorithm*, ranges::category::random_access | ranges::category::sized> AlgorithmManager::get_algorithms() {
|
||||
auto view = algorithms | ranges::view::transform([](auto& algo) {
|
||||
return &algo;
|
||||
});
|
||||
return view;
|
||||
}
|
||||
|
||||
void AlgorithmManager::load_algorithm(DungeonAlgorithm *algorithm, int w, int h) {
|
||||
algorithm_done = false;
|
||||
ticks = 0;
|
||||
loaded_algorithm = algorithm;
|
||||
auto init_result = loaded_algorithm->initialize(w, h);
|
||||
if(!init_result.valid()) {
|
||||
sol::error err = init_result;
|
||||
Logger::log(LogLevel::ERROR, fmt::format("error while initializing lua: {}", err.what()));
|
||||
}
|
||||
}
|
||||
|
||||
void AlgorithmManager::tick_algorithm() {
|
||||
if(this->loaded_algorithm == nullptr || algorithm_done) {
|
||||
return;
|
||||
}
|
||||
if(ticks >= this->loaded_algorithm->frames_per_update) {
|
||||
ticks = 0;
|
||||
auto update_result = this->loaded_algorithm->update();
|
||||
if(update_result.valid()) {
|
||||
algorithm_done = update_result;
|
||||
}
|
||||
else {
|
||||
algorithm_done = true;
|
||||
sol::error err = update_result;
|
||||
Logger::log(LogLevel::ERROR, fmt::format("An error occurred while running update: {}", err.what()));
|
||||
}
|
||||
}
|
||||
ticks++;
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
#include <range/v3/view.hpp>
|
||||
struct DungeonAlgorithm {
|
||||
unsigned int frames_per_update=1;
|
||||
sol::function update;
|
||||
sol::function initialize;
|
||||
sol::protected_function update;
|
||||
sol::protected_function initialize;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
@@ -17,17 +17,15 @@ class AlgorithmManager {
|
||||
private:
|
||||
std::vector<DungeonAlgorithm> algorithms;
|
||||
unsigned int target_fps=1;
|
||||
unsigned int ticks=0;
|
||||
DungeonAlgorithm* loaded_algorithm = nullptr;
|
||||
bool algorithm_done = false;
|
||||
public:
|
||||
void register_algorithm(std::string name, sol::function initialize, sol::function update, unsigned int updates_per_second);
|
||||
|
||||
void setTargetFps(unsigned int targetFps) {
|
||||
target_fps = targetFps;
|
||||
}
|
||||
|
||||
ranges::any_view<DungeonAlgorithm> get_algorithms();
|
||||
|
||||
ranges::any_view<DungeonAlgorithm*, ranges::category::random_access | ranges::category::sized> get_algorithms();
|
||||
void load_algorithm(DungeonAlgorithm* algorithm, int w, int h);
|
||||
void tick_algorithm();
|
||||
explicit AlgorithmManager(unsigned int targetFps) : target_fps(targetFps) {}
|
||||
|
||||
AlgorithmManager() = default;
|
||||
};
|
||||
|
||||
|
||||
@@ -4,12 +4,16 @@
|
||||
|
||||
#include "tilemap.hpp"
|
||||
#include "../engine/utility/point.hpp"
|
||||
#include "../engine/modules/logger.hpp"
|
||||
#include <fmt/format.h>
|
||||
|
||||
void TileMap::draw_floor(int x, int y) {
|
||||
Logger::log(LogLevel::DEBUG, fmt::format("Drawing floor at x: {} y: {}", x, y));
|
||||
grid.insert(x, y, floor_tile);
|
||||
}
|
||||
|
||||
void TileMap::draw_wall(int x, int y) {
|
||||
Logger::log(LogLevel::DEBUG, fmt::format("Drawing wall at x: {} y: {}", x, y));
|
||||
grid.insert(x, y, wall_tile);
|
||||
}
|
||||
|
||||
@@ -18,6 +22,7 @@ char TileMap::get_tile(int x, int y) {
|
||||
}
|
||||
|
||||
void TileMap::fill(bool wall) {
|
||||
Logger::log(LogLevel::DEBUG, fmt::format("Running fill with wall: {}", wall));
|
||||
for(Point p : grid.get_range()) {
|
||||
if(wall) {
|
||||
draw_wall(p.x, p.y);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Created by m on 12/3/21.
|
||||
//
|
||||
|
||||
#include <filesystem>
|
||||
#include "visualizer.hpp"
|
||||
#include "tilemap.hpp"
|
||||
|
||||
@@ -9,6 +10,7 @@ bool Visualizer::update(InputResult input) {
|
||||
if(input.keycode == KEY_ESCAPE) {
|
||||
return true;
|
||||
}
|
||||
this->algorithm_manager.tick_algorithm();
|
||||
switch(input.keycode) {
|
||||
case KEY_RIGHT: x += 1; break;
|
||||
case KEY_LEFT: x -= 1; break;
|
||||
@@ -16,6 +18,12 @@ bool Visualizer::update(InputResult input) {
|
||||
case KEY_DOWN: y += 1; break;
|
||||
default: break;
|
||||
}
|
||||
if(input.keycode >= InputProcessorKeycode::KEY_1 && input.keycode <= InputProcessorKeycode::KEY_9) {
|
||||
if(this->keycode_to_algorithm.contains(input.keycode)) {
|
||||
auto algorithm = this->keycode_to_algorithm[input.keycode];
|
||||
this->algorithm_manager.load_algorithm(algorithm, this->map_size_w, this->map_size_h);
|
||||
}
|
||||
}
|
||||
|
||||
this->x = std::clamp(this->x, 0, (int)this->tile_map.get_width()-1);
|
||||
this->y = std::clamp(this->y, 0, (int)this->tile_map.get_height()-1);
|
||||
@@ -63,6 +71,7 @@ void Visualizer::initialize(GameInitArgs args) {
|
||||
this->camera = Camera(Point{x,y}, tilesx, tilesy, tile_map.get_width(), tile_map.get_height());
|
||||
this->algorithm_manager = AlgorithmManager(args.target_fps);
|
||||
this->initialize_context();
|
||||
this->load_algorithms();
|
||||
Logger::log(LogLevel::DEBUG, "Game initialization finished");
|
||||
}
|
||||
|
||||
@@ -86,6 +95,34 @@ void Visualizer::initialize_context() {
|
||||
|
||||
auto algo_manager_lua = lua->new_usertype<AlgorithmManager>("AlgorithmManager", sol::no_constructor);
|
||||
algo_manager_lua["register_algorithm"] = &AlgorithmManager::register_algorithm;
|
||||
|
||||
auto game_state_lua = lua->new_usertype<Visualizer>("Visualizer", sol::no_constructor);
|
||||
game_state_lua.set("algorithm_manager", sol::readonly(&Visualizer::algorithm_manager));
|
||||
game_state_lua.set("map", &Visualizer::tile_map);
|
||||
|
||||
lua->set("visualizer", this);
|
||||
}
|
||||
|
||||
void Visualizer::load_algorithms() {
|
||||
auto lua = lua_context_manager.get_default_context();
|
||||
const std::string algorithms_directory = "scripts/algorithms";
|
||||
|
||||
for(const auto& file : std::filesystem::directory_iterator(algorithms_directory)) {
|
||||
lua->script_file(file.path());
|
||||
}
|
||||
Logger::log(LogLevel::DEBUG, "finished loading lua files");
|
||||
auto algorithms = this->algorithm_manager.get_algorithms();
|
||||
auto algorithm_count = algorithms.size();
|
||||
Logger::log(LogLevel::DEBUG, fmt::format("algorithms: {}", algorithm_count));
|
||||
|
||||
for(int code = InputProcessorKeycode::KEY_1;code < InputProcessorKeycode::KEY_9;code++) {
|
||||
auto index = code-InputProcessorKeycode::KEY_1;
|
||||
if(algorithms.size() <= index) {
|
||||
break;
|
||||
}
|
||||
auto algo = algorithms[index];
|
||||
this->keycode_to_algorithm[(InputProcessorKeycode)code] = algo;
|
||||
}
|
||||
}
|
||||
|
||||
Visualizer::~Visualizer() = default;
|
||||
|
||||
@@ -38,8 +38,9 @@ private:
|
||||
int window_height = 0;
|
||||
TileMap tile_map = TileMap(0, 0, DEFAULT_WALL_CHAR[0], DEFAULT_FLOOR_CHAR[0]);
|
||||
Camera camera = Camera();
|
||||
LuaContextManager lua_context_manager = LuaContextManager();
|
||||
LuaContextManager lua_context_manager;
|
||||
AlgorithmManager algorithm_manager;
|
||||
std::unordered_map<InputProcessorKeycode, DungeonAlgorithm*> keycode_to_algorithm;
|
||||
|
||||
int x = 0;
|
||||
int y=0;
|
||||
@@ -54,6 +55,7 @@ private:
|
||||
|
||||
void initialize_map(int width, int height);
|
||||
void initialize_context();
|
||||
void load_algorithms();
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user