#include "rooms.h" #include #include #include #include #include #include #include #include #include "images.h" #include "enemies.h" namespace fs = std::filesystem; namespace rooms { int num_total_rooms = 0; std::string current_room = ""; std::map rooms; int full_map_x = 0, full_map_y = 0; static const char *paletteMap[] = { "black", "bright_black", "blue", "bright_blue", "red", "bright_red", "magenta", "bright_magenta", "green", "bright_green", "cyan", "bright_cyan", "yellow", "bright_yellow", "white", "bright_white" }; const uint8_t colorToNum(std::string value) { for (int i=0; i<16; ++i) if (value == paletteMap[i]) return i; return 0; } 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& room_name, const std::string& section, const std::string& key, const std::string& value) { room_t& room = rooms[room_name]; if (section == "global") { if (key == "name") { room.name = value; } else if (key == "bgColor") { room.bgColor = colorToNum(value); } else if (key == "border") { room.border = colorToNum(value); //} else if (key == "tileMapFile") { // room.tileMapFile = value; } else if (key == "tileSetFile") { room.tileSetFile = images::getImage("tilesets/"+value); } else if (key == "roomUp") { room.roomUp = value.substr(0, value.find_last_of('.'));; } else if (key == "roomDown") { room.roomDown = value.substr(0, value.find_last_of('.'));; } else if (key == "roomLeft") { room.roomLeft = value.substr(0, value.find_last_of('.'));; } else if (key == "roomRight") { room.roomRight = value.substr(0, value.find_last_of('.'));; } else if (key == "itemColor1") { room.itemColor1 = colorToNum(value); } else if (key == "itemColor2") { room.itemColor2 = colorToNum(value); } } else if (section == "enemy") { if (key == "animation") { room.enemies.back().animation = value.substr(0, value.find_last_of('.')); } else if (key == "x") { room.enemies.back().x = std::stoi(value); } else if (key == "y") { room.enemies.back().y = std::stoi(value); } else if (key == "vx") { room.enemies.back().vx = std::stof(value); } else if (key == "vy") { room.enemies.back().vy = std::stof(value); } else if (key == "x1") { room.enemies.back().x1 = std::stoi(value); } else if (key == "y1") { room.enemies.back().y1 = std::stoi(value); } else if (key == "x2") { room.enemies.back().x2 = std::stoi(value); } else if (key == "y2") { room.enemies.back().y2 = std::stoi(value); } else if (key == "color") { room.enemies.back().color = colorToNum(value); } else if (key == "flip") { room.enemies.back().flip = value=="true" ? true : false; } else if (key == "mirror") { room.enemies.back().mirror = value=="true" ? true : false; } } else if (section == "item") { if (key == "tile") { room.items.back().tile = std::stoi(value); } else if (key == "x") { room.items.back().x = std::stoi(value); } else if (key == "y") { room.items.back().y = std::stoi(value); } else if (key == "counter") { room.items.back().counter = std::stof(value); } } } void loadRoom(fs::path filename) { std::string room_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 == "enemy") rooms[room_name].enemies.emplace_back(); else if (section == "item") rooms[room_name] .items.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(room_name, current_section, key, value); } } } void loadTiles(fs::path filename) { filename.replace_extension(".tmx"); std::string room_name = filename.stem().string(); std::string line; bool inData = false; int row = 0, col = 0; std::ifstream file(filename); if (!file) { std::cerr << "Failed to open file.\n"; return; } room_t& room = rooms[room_name]; while (std::getline(file, line)) { if (!inData) { if (line.find("") != std::string::npos) inData = true; continue; } if (line.find("") != std::string::npos) break; std::stringstream ss(line); std::string value; while (std::getline(ss, value, ',')) { if (!value.empty()) { room.tiles[col][row] = std::stoi(value); ++col; if (col == 32) { col = 0; ++row; } } } } } void generateThumbnail(fs::path filename) { std::string room_name = filename.stem().string(); room_t &room = rooms[room_name]; // Primer generem un pixel per a cada tile del gif de tiles draw::surface *tiles = room.tileSetFile; uint8_t pixels[tiles->w/8][tiles->h/8]; for (int ty=0; tyh/8; ty++) { for (int tx=0; txw/8; tx++) { uint8_t count[16] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; for (int y=0;y<8;++y) for (int x=0;x<8;x++) { count[tiles->pixels[(x+tx*8)+(y+ty*8)*tiles->w]]++; } uint8_t max_count=0; uint8_t max_index=0; for (int i=0; i<16; ++i) if (count[i] > max_count) {max_count=count[i]; max_index=i;} pixels[tx][ty] = max_index; } } room.thumbnail = draw::createSurface(32,16); for (int y=0; y<16; ++y) { for (int x=0; x<32; ++x) { uint16_t tile = room.tiles[x][y]; if (tile>0) { tile--; room.thumbnail->pixels[x+y*32] = pixels[tile%24][tile/24]; } else { room.thumbnail->pixels[x+y*32] = room.bgColor; } } } } std::map visited; void detectFullMapOffset(std::string room_name, int x, int y) { if (visited.find(room_name)!= visited.end()) return; printf("Visiting '%s'...\n", room_name.c_str()); visited[room_name] = true; if (full_map_x < x) full_map_x = x; if (full_map_y < y) full_map_y = y; room_t &room = rooms[room_name]; room.map_x = x; room.map_y = y; if (room.roomUp != "0") detectFullMapOffset(room.roomUp, x, y+1); if (room.roomLeft != "0") detectFullMapOffset(room.roomLeft, x+1, y); if (room.roomDown != "0") detectFullMapOffset(room.roomDown, x, y-1); if (room.roomRight != "0") detectFullMapOffset(room.roomRight, x-1, y); } void load() { // Get all room files fs::path target_dir = "./data/room"; std::vector room_files; try { for (const auto& entry : fs::directory_iterator(target_dir)) { if (entry.is_regular_file() && entry.path().extension() == ".room") { room_files.push_back(entry.path()); } } std::sort(room_files.begin(), room_files.end()); for (const auto& path : room_files) { std::cout << "Processing " << path.filename() << '\n'; loadRoom(path); loadTiles(path); generateThumbnail(path); } } catch (const fs::filesystem_error& e) { std::cerr << "Filesystem error: " << e.what() << '\n'; } visited.clear(); detectFullMapOffset("01", 0, 0); full_map_x++; full_map_y++; /*for (auto &item : rooms) { room_t &room = item.second; std::cout << room.name << std::endl; for (int y=0; y<16; ++y) { for (int x=0; x<32; ++x) std::cout << std::to_string(room.tiles[x][y]) << ","; std::cout << std::endl; } }*/ } void draw() { room_t &room = rooms["02"]; draw::cls(room.border); draw::setViewport(32, 24, 256, 128); draw::cls(room.bgColor); draw::setSource(room.tileSetFile); for (int y=0; y<16; ++y) { for (int x=0; x<32; ++x) { uint16_t tile = room.tiles[x][y]; if (tile>0) { tile--; draw::draw(x*8, y*8, 8, 8, (tile%24)*8, (tile/24)*8); } } } 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); } draw::resetViewport(); draw::setSource(room.thumbnail); draw::draw(); } void drawFullMap() { for (auto &item : rooms) { auto room = item.second; int x = ((full_map_x-room.map_x)*38)-1; int y = ((full_map_y-room.map_y)*22)-1; draw::resetViewport(); draw::color(COLOR_WHITE); draw::rect(x, y, 34, 18); draw::setSource(room.thumbnail); draw::draw(x+1, y+1, 32, 16, 0, 0); if (room.roomUp != "0") draw::fillrect(x+15, y-4, 4, 4); //if (room.roomDown != "0") draw::fillrect(x+15, y+16, 4, 4); if (room.roomLeft != "0") draw::fillrect(x-4, y+7, 4, 4); } } }