diff --git a/source/enemies.cpp b/source/enemies.cpp new file mode 100644 index 0000000..5d9e917 --- /dev/null +++ b/source/enemies.cpp @@ -0,0 +1,137 @@ +#include "enemies.h" +#include +#include +#include +#include +#include + +namespace fs = std::filesystem; + +namespace enemies +{ + std::unordered_map enemies; + + inline void trim(std::string& s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end()); + } + + void processKeyValue(const std::string& enemy_name, const std::string& section, const std::string& key, const std::string& value) + { + enemy_t& enemy = enemies[enemy_name]; + + if (section == "global") { + if (key == "tileSetFile") { + enemy.tileSetFile = images::getImage("enemies/"+value); + } else if (key == "frame_width") { + enemy.frame_width = std::stoi(value); + } else if (key == "frame_height") { + enemy.frame_height = std::stoi(value); + } + } else if (section == "animation") { + if (key == "name") { + enemy.animations.back().name = value; + printf("animacio '%s' frames: ", value.c_str()); + } else if (key == "loop") { + enemy.animations.back().loop = std::stoi(value); + } else if (key == "speed") { + enemy.animations.back().speed = std::stof(value); + } else if (key == "frames") { + std::stringstream ss(value); + std::string frame; + while (std::getline(ss, frame, ',')) { + if (!frame.empty()) { + enemy.animations.back().frames.emplace_back(std::stoi(frame)); + printf("%s,", frame.c_str()); + } + } + printf("\n"); + } + } + + } + + void loadEnemy(fs::path filename) + { + std::string enemy_name = filename.stem().string(); + + std::ifstream file(filename); + if (!file) { + std::cerr << "Failed to open file.\n"; + return; + } + + std::string current_section = "global"; + + std::string line; + while (std::getline(file, line)) + { + //std::cout << "'" << line << "'\n"; + // Trim and clean line, ignore empty lines and comments + trim(line); + if (line.empty() || line[0] == '#') continue; + + // Remove inline comments + /*std::size_t comment_pos = line.find('#'); + if (comment_pos != std::string::npos) { + line = line.substr(0, comment_pos); + trim(line); + }*/ + + // Check if entering or exiting a section + if (line[0] == '[') + { + std::size_t closing_pos = line.find(']'); + if (closing_pos != std::string::npos && closing_pos > 1) + { + std::string section = line.substr(1,closing_pos-1); + if (section[0] == '/') { + current_section = "global"; + } else { + current_section = section; + if (section == "animation") enemies[enemy_name].animations.emplace_back(); + } + } + } + + // Get and process key/value + std::size_t eq_pos = line.find('='); + if (eq_pos != std::string::npos) { + std::string key = line.substr(0, eq_pos); + std::string value = line.substr(eq_pos + 1); + trim(key); + trim(value); + processKeyValue(enemy_name, current_section, key, value); + } + } + } + + void load() + { + // Get all enemies + fs::path target_dir = "./data/enemies"; + std::vector enemy_files; + + try { + for (const auto& entry : fs::directory_iterator(target_dir)) { + if (entry.is_regular_file() && entry.path().extension() == ".ani") { + enemy_files.push_back(entry.path()); + } + } + + for (const auto& path : enemy_files) { + std::cout << "Processing " << path.filename() << '\n'; + loadEnemy(path); + } + + } catch (const fs::filesystem_error& e) { + std::cerr << "Filesystem error: " << e.what() << '\n'; + } + + } + + enemy_t &get(std::string name) + { + return enemies[name]; + } +} diff --git a/source/enemies.h b/source/enemies.h new file mode 100644 index 0000000..d760d93 --- /dev/null +++ b/source/enemies.h @@ -0,0 +1,26 @@ +#pragma once +#include "images.h" +#include +#include + +namespace enemies +{ + struct animation_t + { + std::string name {""}; + float speed {0.0f}; + uint8_t loop {0}; + std::vector frames; + }; + + struct enemy_t + { + draw::surface *tileSetFile {nullptr}; + uint8_t frame_width {0}; + uint8_t frame_height {0}; + std::vector animations; + }; + + void load(); + enemy_t &get(std::string name); +} diff --git a/source/main.cpp b/source/main.cpp index 55a74bb..a1e770e 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,4 +1,5 @@ #include "rooms.h" +#include "enemies.h" #include "japi/draw.h" #include "japi/game.h" #include "images.h" @@ -9,6 +10,7 @@ void game::init() { draw::init("DILEMMAKER v0.1", 320, 240, 3, false); game::setState(loop); + enemies::load(); rooms::load(); images::loadPalette("./data/palette/zx-spectrum.pal"); } diff --git a/source/rooms.cpp b/source/rooms.cpp index 2bd60b4..33da6eb 100644 --- a/source/rooms.cpp +++ b/source/rooms.cpp @@ -8,6 +8,7 @@ #include #include #include "images.h" +#include "enemies.h" namespace fs = std::filesystem; @@ -29,22 +30,9 @@ namespace rooms return 0; } - // Trim from start (in-place) - inline void ltrim(std::string& s) { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), - [](unsigned char ch) { return !std::isspace(ch); })); - } - - // Trim from end (in-place) - inline void rtrim(std::string& s) { - s.erase(std::find_if(s.rbegin(), s.rend(), - [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end()); - } - - // Trim both ends (in-place) inline void trim(std::string& s) { - ltrim(s); - rtrim(s); + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end()); } void processKeyValue(const std::string& room_name, const std::string& section, const std::string& key, const std::string& value) @@ -77,39 +65,39 @@ namespace rooms } } else if (section == "enemy") { if (key == "animation") { - room.enemies[room.enemies.size()-1].animation = value; + room.enemies.back().animation = value.substr(0, value.find_last_of('.'));; } else if (key == "x") { - room.enemies[room.enemies.size()-1].x = std::stoi(value); + room.enemies.back().x = std::stoi(value); } else if (key == "y") { - room.enemies[room.enemies.size()-1].y = std::stoi(value); + room.enemies.back().y = std::stoi(value); } else if (key == "vx") { - room.enemies[room.enemies.size()-1].vx = std::stof(value); + room.enemies.back().vx = std::stof(value); } else if (key == "vy") { - room.enemies[room.enemies.size()-1].vy = std::stof(value); + room.enemies.back().vy = std::stof(value); } else if (key == "x1") { - room.enemies[room.enemies.size()-1].x1 = std::stoi(value); + room.enemies.back().x1 = std::stoi(value); } else if (key == "y1") { - room.enemies[room.enemies.size()-1].y1 = std::stoi(value); + room.enemies.back().y1 = std::stoi(value); } else if (key == "x2") { - room.enemies[room.enemies.size()-1].x2 = std::stoi(value); + room.enemies.back().x2 = std::stoi(value); } else if (key == "y2") { - room.enemies[room.enemies.size()-1].y2 = std::stoi(value); + room.enemies.back().y2 = std::stoi(value); } else if (key == "color") { - room.enemies[room.enemies.size()-1].color = colorToNum(value); + room.enemies.back().color = colorToNum(value); } else if (key == "flip") { - room.enemies[room.enemies.size()-1].flip = value=="true" ? true : false; + room.enemies.back().flip = value=="true" ? true : false; } else if (key == "mirror") { - room.enemies[room.enemies.size()-1].mirror = value=="true" ? true : false; + room.enemies.back().mirror = value=="true" ? true : false; } } else if (section == "item") { if (key == "tile") { - room.items[room.items.size()-1].tile = std::stoi(value); + room.items.back().tile = std::stoi(value); } else if (key == "x") { - room.items[room.items.size()-1].x = std::stoi(value); + room.items.back().x = std::stoi(value); } else if (key == "y") { - room.items[room.items.size()-1].y = std::stoi(value); + room.items.back().y = std::stoi(value); } else if (key == "counter") { - room.items[room.items.size()-1].counter = std::stof(value); + room.items.back().counter = std::stof(value); } } } @@ -135,11 +123,11 @@ namespace rooms if (line.empty() || line[0] == '#') continue; // Remove inline comments - std::size_t comment_pos = line.find('#'); + /*std::size_t comment_pos = line.find('#'); if (comment_pos != std::string::npos) { line = line.substr(0, comment_pos); trim(line); - } + }*/ // Check if entering or exiting a section if (line[0] == '[') @@ -261,5 +249,15 @@ namespace rooms } } } + + for (auto enemy : room.enemies) + { + enemies::enemy_t &anim = enemies::get(enemy.animation); + draw::setSource(anim.tileSetFile); + const int tile = anim.animations[0].frames[0]; + draw::swapcol(1, enemy.color); + draw::draw(enemy.x*8, enemy.y*8, anim.frame_width, anim.frame_height, tile*anim.frame_width, 0); + draw::restorecol(1); + } } } diff --git a/source/rooms.h b/source/rooms.h index 6019b83..234eee8 100644 --- a/source/rooms.h +++ b/source/rooms.h @@ -21,49 +21,49 @@ #define COLOR_WHITE 14 #define COLOR_BRIGHT_WHITE 15 -struct enemy_t -{ - std::string animation {""}; - uint8_t x {0}; - uint8_t y {0}; - float vx {0.0f}; - float vy {0.0f}; - uint8_t x1 {0}; - uint8_t y1 {0}; - uint8_t x2 {0}; - uint8_t y2 {0}; - uint8_t color {COLOR_WHITE}; - bool flip {false}; - bool mirror {false}; -}; - -struct item_t -{ - uint8_t tile {0}; - uint8_t x {0}; - uint8_t y {0}; - float counter {0.0f}; -}; - -struct room_t -{ - std::string name {""}; - uint8_t bgColor {COLOR_BLACK}; - uint8_t border {COLOR_BLACK}; - draw::surface *tileSetFile {nullptr}; - std::string roomUp {0}; - std::string roomDown {0}; - std::string roomLeft {0}; - std::string roomRight {0}; - uint8_t itemColor1 {0}; - uint8_t itemColor2 {0}; - std::vector enemies; - std::vector items; - uint16_t tiles[32][16]; -}; - namespace rooms { + struct enemy_t + { + std::string animation {""}; + uint8_t x {0}; + uint8_t y {0}; + float vx {0.0f}; + float vy {0.0f}; + uint8_t x1 {0}; + uint8_t y1 {0}; + uint8_t x2 {0}; + uint8_t y2 {0}; + uint8_t color {COLOR_WHITE}; + bool flip {false}; + bool mirror {false}; + }; + + struct item_t + { + uint8_t tile {0}; + uint8_t x {0}; + uint8_t y {0}; + float counter {0.0f}; + }; + + struct room_t + { + std::string name {""}; + uint8_t bgColor {COLOR_BLACK}; + uint8_t border {COLOR_BLACK}; + draw::surface *tileSetFile {nullptr}; + std::string roomUp {0}; + std::string roomDown {0}; + std::string roomLeft {0}; + std::string roomRight {0}; + uint8_t itemColor1 {0}; + uint8_t itemColor2 {0}; + std::vector enemies; + std::vector items; + uint16_t tiles[32][16]; + }; + void load(); void draw(); }