- [NEW] Càrrega i pintat d'enemics en l'habitació
This commit is contained in:
137
source/enemies.cpp
Normal file
137
source/enemies.cpp
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
#include "enemies.h"
|
||||||
|
#include <filesystem>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
namespace enemies
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, enemy_t> 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<fs::path> 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];
|
||||||
|
}
|
||||||
|
}
|
||||||
26
source/enemies.h
Normal file
26
source/enemies.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "images.h"
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace enemies
|
||||||
|
{
|
||||||
|
struct animation_t
|
||||||
|
{
|
||||||
|
std::string name {""};
|
||||||
|
float speed {0.0f};
|
||||||
|
uint8_t loop {0};
|
||||||
|
std::vector<uint8_t> frames;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct enemy_t
|
||||||
|
{
|
||||||
|
draw::surface *tileSetFile {nullptr};
|
||||||
|
uint8_t frame_width {0};
|
||||||
|
uint8_t frame_height {0};
|
||||||
|
std::vector<animation_t> animations;
|
||||||
|
};
|
||||||
|
|
||||||
|
void load();
|
||||||
|
enemy_t &get(std::string name);
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "rooms.h"
|
#include "rooms.h"
|
||||||
|
#include "enemies.h"
|
||||||
#include "japi/draw.h"
|
#include "japi/draw.h"
|
||||||
#include "japi/game.h"
|
#include "japi/game.h"
|
||||||
#include "images.h"
|
#include "images.h"
|
||||||
@@ -9,6 +10,7 @@ void game::init()
|
|||||||
{
|
{
|
||||||
draw::init("DILEMMAKER v0.1", 320, 240, 3, false);
|
draw::init("DILEMMAKER v0.1", 320, 240, 3, false);
|
||||||
game::setState(loop);
|
game::setState(loop);
|
||||||
|
enemies::load();
|
||||||
rooms::load();
|
rooms::load();
|
||||||
images::loadPalette("./data/palette/zx-spectrum.pal");
|
images::loadPalette("./data/palette/zx-spectrum.pal");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "images.h"
|
#include "images.h"
|
||||||
|
#include "enemies.h"
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
@@ -29,22 +30,9 @@ namespace rooms
|
|||||||
return 0;
|
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) {
|
inline void trim(std::string& s) {
|
||||||
ltrim(s);
|
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
|
||||||
rtrim(s);
|
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)
|
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") {
|
} else if (section == "enemy") {
|
||||||
if (key == "animation") {
|
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") {
|
} 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") {
|
} 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") {
|
} 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") {
|
} 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") {
|
} 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") {
|
} 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") {
|
} 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") {
|
} 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") {
|
} else if (key == "color") {
|
||||||
room.enemies[room.enemies.size()-1].color = colorToNum(value);
|
room.enemies.back().color = colorToNum(value);
|
||||||
} else if (key == "flip") {
|
} 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") {
|
} 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") {
|
} else if (section == "item") {
|
||||||
if (key == "tile") {
|
if (key == "tile") {
|
||||||
room.items[room.items.size()-1].tile = std::stoi(value);
|
room.items.back().tile = std::stoi(value);
|
||||||
} else if (key == "x") {
|
} 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") {
|
} 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") {
|
} 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;
|
if (line.empty() || line[0] == '#') continue;
|
||||||
|
|
||||||
// Remove inline comments
|
// Remove inline comments
|
||||||
std::size_t comment_pos = line.find('#');
|
/*std::size_t comment_pos = line.find('#');
|
||||||
if (comment_pos != std::string::npos) {
|
if (comment_pos != std::string::npos) {
|
||||||
line = line.substr(0, comment_pos);
|
line = line.substr(0, comment_pos);
|
||||||
trim(line);
|
trim(line);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// Check if entering or exiting a section
|
// Check if entering or exiting a section
|
||||||
if (line[0] == '[')
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,10 @@
|
|||||||
#define COLOR_WHITE 14
|
#define COLOR_WHITE 14
|
||||||
#define COLOR_BRIGHT_WHITE 15
|
#define COLOR_BRIGHT_WHITE 15
|
||||||
|
|
||||||
struct enemy_t
|
namespace rooms
|
||||||
{
|
{
|
||||||
|
struct enemy_t
|
||||||
|
{
|
||||||
std::string animation {""};
|
std::string animation {""};
|
||||||
uint8_t x {0};
|
uint8_t x {0};
|
||||||
uint8_t y {0};
|
uint8_t y {0};
|
||||||
@@ -35,18 +37,18 @@ struct enemy_t
|
|||||||
uint8_t color {COLOR_WHITE};
|
uint8_t color {COLOR_WHITE};
|
||||||
bool flip {false};
|
bool flip {false};
|
||||||
bool mirror {false};
|
bool mirror {false};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct item_t
|
struct item_t
|
||||||
{
|
{
|
||||||
uint8_t tile {0};
|
uint8_t tile {0};
|
||||||
uint8_t x {0};
|
uint8_t x {0};
|
||||||
uint8_t y {0};
|
uint8_t y {0};
|
||||||
float counter {0.0f};
|
float counter {0.0f};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct room_t
|
struct room_t
|
||||||
{
|
{
|
||||||
std::string name {""};
|
std::string name {""};
|
||||||
uint8_t bgColor {COLOR_BLACK};
|
uint8_t bgColor {COLOR_BLACK};
|
||||||
uint8_t border {COLOR_BLACK};
|
uint8_t border {COLOR_BLACK};
|
||||||
@@ -60,10 +62,8 @@ struct room_t
|
|||||||
std::vector<enemy_t> enemies;
|
std::vector<enemy_t> enemies;
|
||||||
std::vector<item_t> items;
|
std::vector<item_t> items;
|
||||||
uint16_t tiles[32][16];
|
uint16_t tiles[32][16];
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace rooms
|
|
||||||
{
|
|
||||||
void load();
|
void load();
|
||||||
void draw();
|
void draw();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user