From 3ed64a471aacd555f60ff91e529dc4f586d630a2 Mon Sep 17 00:00:00 2001 From: Raimon Zamora Date: Mon, 17 Nov 2025 14:24:03 +0100 Subject: [PATCH] - No se, molts canvis i coses --- lagueirtofile | 2 +- source/enemies.cpp | 137 --------- source/enemies.h | 26 -- source/images.cpp | 59 ---- source/images.h | 9 - source/japi/draw.cpp | 626 +++++------------------------------------- source/japi/draw.h | 158 ++--------- source/japi/font.cpp | 73 +++++ source/japi/font.h | 8 + source/japi/game.cpp | 24 +- source/japi/input.cpp | 10 +- source/japi/input.h | 2 + source/main.cpp | 46 ++-- source/menu.cpp | 68 +++++ source/menu.h | 14 + source/rooms.cpp | 387 -------------------------- source/rooms.h | 73 ----- 17 files changed, 295 insertions(+), 1427 deletions(-) delete mode 100644 source/enemies.cpp delete mode 100644 source/enemies.h delete mode 100644 source/images.cpp delete mode 100644 source/images.h create mode 100644 source/japi/font.cpp create mode 100644 source/japi/font.h create mode 100644 source/menu.cpp create mode 100644 source/menu.h delete mode 100644 source/rooms.cpp delete mode 100644 source/rooms.h diff --git a/lagueirtofile b/lagueirtofile index 4d7a2e9..00e071b 100644 --- a/lagueirtofile +++ b/lagueirtofile @@ -1,4 +1,4 @@ -libs = -lSDL3 -lGL +libs = -lSDL3 cppflags = -g executable = dilemmaker sourcepath = source source/japi diff --git a/source/enemies.cpp b/source/enemies.cpp deleted file mode 100644 index 5d9e917..0000000 --- a/source/enemies.cpp +++ /dev/null @@ -1,137 +0,0 @@ -#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 deleted file mode 100644 index d760d93..0000000 --- a/source/enemies.h +++ /dev/null @@ -1,26 +0,0 @@ -#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/images.cpp b/source/images.cpp deleted file mode 100644 index 2031721..0000000 --- a/source/images.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "images.h" -#include -#include -#include -#include -#include - -namespace images -{ - std::map images; - - draw::surface *getImage(std::string filename) - { - auto item = images.find(filename); - if (item != images.end()) return item->second; - - draw::surface *image = draw::loadSurface(filename.c_str()); - images[filename] = image; - return image; - } - - int loadPalette(std::string filename) - { - uint32_t palette[16]; - - FILE *file = fopen(filename.c_str(), "r"); - if (!file) return -1; - - char header[32]; - int version, count; - - // Read and validate header - if (!fgets(header, sizeof(header), file) || strncmp(header, "JASC-PAL", 8) != 0) { - fclose(file); - return -2; - } - - if (fscanf(file, "%d\n%d\n", &version, &count) != 2 || count != 16) { - fclose(file); - return -3; - } - - // Read 16 RGB triplets - for (int i = 0; i < 16; ++i) { - int r, g, b; - if (fscanf(file, "%d %d %d\n", &r, &g, &b) != 3) { - fclose(file); - return -4; - } - palette[i] = (r << 16) | (g << 8) | b; - } - - fclose(file); - - draw::setPalette(palette, 16); - - return 0; - } -} diff --git a/source/images.h b/source/images.h deleted file mode 100644 index 28e0eef..0000000 --- a/source/images.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "japi/draw.h" -#include - -namespace images -{ - draw::surface *getImage(std::string filename); - int loadPalette(std::string filename); -} diff --git a/source/japi/draw.cpp b/source/japi/draw.cpp index 26b3c0b..b361e92 100644 --- a/source/japi/draw.cpp +++ b/source/japi/draw.cpp @@ -2,88 +2,16 @@ #include #include "gif.h" #include "file.h" -//#include "shader.h" namespace draw { - // La idea de esta unitat es usar "superficies", que no son mes que arrays de bytes, per a anar pintant. - // El resultat final s'ha de pintar en algun moment a la superficie "screen" (o siga, especificar nullptr en setDestination) - // Aleshores, en "render" el contingut de screen se volca a la textura SDL que crearem, - // i eixa textura se pintarà a pantalla com se sol fer amb SDL. Ho anirem veient en el codi. - SDL_Window *sdl_window {nullptr}; // La finestra de SDL SDL_Renderer *sdl_renderer {nullptr}; // El renderer de SDL - SDL_Texture *sdl_texture {nullptr}; // La textura de SDL a la que pintarem la nostra superficie "screen" i que despres volcarem a pantalla - //SDL_Texture *sdl_shadertex {nullptr}; // La textura de SDL per al shader + SDL_Texture *sdl_source {nullptr}; - static int screen_zoom = 1; - static bool screen_fullscreen = false; - static bool screen_cursor = true; - static char* screen_shader = nullptr; - static bool shader_enabled = false; - static float window_ratio = 1; - static int canvas_width; - static int canvas_height; - static int desktop_width; - static int desktop_height; - static int window_width; - static int window_height; - static int offset_x = 0; - static int offset_y = 0; - char window_title[256]; - - surface *screen {nullptr}; // La superficie screen, que representa la pantalla. Se crea i destrueix internament - surface *destination {nullptr}; // Punter a la actual superficie de destí - surface *source {nullptr}; // Punter a la actual superficie d'oritge - surface *pushed_source {nullptr}; // Punter a la superficie d'oritge que s'ha pushat - - uint32_t palette[256]; // La paleta de colors - uint32_t aux_palette[256]; // La paleta de colors, para els fadein - uint8_t color_indices[256]; // Indices dels colors per defecte - uint8_t sel_color {0}; // Color seleccionat per defecte - uint8_t transparent {0}; // El color transparent - - //surface *textsurf = nullptr; // Surface on guardar el gif amb la font - - SDL_Rect viewport; - - bool fading_out = false; - bool fading_in = false; - - void createDisplay() + void init(const char *titol, const uint16_t width, const uint16_t height) { - // Ajustem el zoom i el ratio, per si tenen valors locs - if (screen_zoom <= 0) screen_zoom = 1; - if (window_ratio <= 0) window_ratio = 1; - - // Ajustem el tamany de la finestra, segons el zoom i el ratio - window_width = canvas_width*screen_zoom; - window_height = window_ratio != 1 ? int(float(canvas_width)*window_ratio*float(screen_zoom)) : canvas_height*screen_zoom; - - // Mentres no càpiga en la pantalla, reduïm el zoom - while (window_width > desktop_width || window_height > desktop_height) { - screen_zoom--; - window_width = canvas_width*screen_zoom; - window_height = window_ratio != 1 ? int(float(canvas_width)*window_ratio*float(screen_zoom)) : canvas_height*screen_zoom; - } - - if (screen_fullscreen) { - if (desktop_width * window_ratio > desktop_height) { - offset_y = 0; - window_height = desktop_height; - window_width = desktop_height/window_ratio; - offset_x = (desktop_width - window_width)/2; - } else { - offset_x = 0; - window_width = desktop_width; - window_height = desktop_width*window_ratio; - offset_y = (desktop_height - window_height)/2; - } - } else { - offset_x = offset_y = 0; - } - - sdl_window = SDL_CreateWindow(window_title, window_width, window_height, SDL_WINDOW_OPENGL|(screen_fullscreen?SDL_WINDOW_FULLSCREEN:0)); + sdl_window = SDL_CreateWindow(titol, width, height, SDL_WINDOW_RESIZABLE); if (!sdl_window) { SDL_LogCritical(SDL_LOG_CATEGORY_VIDEO, "ERROR (draw::init): Failed to initialize window!\n"); exit(1); @@ -94,432 +22,123 @@ namespace draw SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "ERROR (draw::init): Failed to initialize renderer!\n"); exit(1); } - - if (screen_cursor) SDL_ShowCursor(); else SDL_HideCursor(); - - sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, canvas_width, canvas_height); - SDL_SetTextureScaleMode(sdl_texture, SDL_SCALEMODE_NEAREST); - if (!sdl_texture) { - SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "ERROR (draw::init): Failed to initialize texture!\n"); - exit(1); - } - -// sdl_shadertex = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, window_width, window_height); -// SDL_SetTextureScaleMode(sdl_shadertex, SDL_SCALEMODE_NEAREST); - -// loadShader(); + //SDL_SetRenderDrawBlendMode(sdl_renderer, SDL_BLENDMODE_BLEND); } - void destroyDisplay() - { - SDL_DestroyTexture(sdl_texture); - SDL_DestroyRenderer(sdl_renderer); - SDL_DestroyWindow(sdl_window); - } - - // Inicialització de tot el que fa falta per a carregar gràfics i pintar en pantalla - void init(const char *titol, const uint16_t width, const uint16_t height, const int zoom, const bool fullscreen, const float ratio) - { - screen_zoom = file::getConfigValueInteger("zoom", zoom); - screen_fullscreen = file::getConfigValueBool("fullscreen", fullscreen); - window_ratio = ratio; - canvas_width = width; - canvas_height = height; - strcpy(window_title, titol); - - const SDL_DisplayMode *dm = SDL_GetDesktopDisplayMode(SDL_GetPrimaryDisplay()); - if (!dm) - { - SDL_Log("SDL_GetDesktopDisplayMode failed: %s", SDL_GetError()); - exit(1); - } - desktop_width = dm->w; - desktop_height = dm->h; - - createDisplay(); - // Inicialització de les estructures de SDL - /* - sdl_window = SDL_CreateWindow(titol, width * zoom, height * zoom, 0); - if (!sdl_window) { - SDL_LogCritical(SDL_LOG_CATEGORY_VIDEO, "ERROR (draw::init): Failed to initialize window!\n"); - exit(1); - } - sdl_renderer = SDL_CreateRenderer(sdl_window, NULL); - if (!sdl_renderer) { - SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "ERROR (draw::init): Failed to initialize renderer!\n"); - exit(1); - } - sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height); - SDL_SetTextureScaleMode(sdl_texture, SDL_SCALEMODE_NEAREST); - if (!sdl_texture) { - SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "ERROR (draw::init): Failed to initialize texture!\n"); - exit(1); - } - */ - - // Creem la superficie "screen" i la establim com a superficie destinació - screen = createSurface(width, height); - destination = screen; - viewport.x = viewport.y = 0; - viewport.w = width; - viewport.h = height; - sel_color = transparent = 0; - for (int i=0;i<256;++i) color_indices[i] = i; - - //SDL_HideCursor(); - //textsurf = loadSurface("font.gif"); - } - - // Finalització del sistema void quit() { - //if (textsurf) freeSurface(textsurf); + SDL_DestroyRenderer(sdl_renderer); + SDL_DestroyWindow(sdl_window); - // Si la superficie "screen" existia, alliberem la seua memòria - if (screen != nullptr) - { - freeSurface(screen); - } - - // Destruim tot el relacionat amb SDL - destroyDisplay(); - - // Fiquem tots els punters a nullptr, per si de cas no estem eixint del programa - // i anem a tornar a inicialitzar el sistema sdl_window = nullptr; sdl_renderer = nullptr; - sdl_texture = nullptr; - screen = destination = source = nullptr; } - void setZoom(const int value) { - screen_zoom = value; - destroyDisplay(); - createDisplay(); - file::setConfigValueInteger("zoom", screen_zoom); - } - - const int getZoom() + SDL_Texture *createSurface(const uint16_t w, const uint16_t h) { - return screen_zoom; + return SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, w, h); } - const float getScaleX() + SDL_Texture *loadSurface(const char *filename, const int transparent) { - return float(window_width) / float(canvas_width); - } + int size; + uint8_t *buffer = (uint8_t *)file::getFileBuffer(filename, size); + if (buffer == nullptr) return nullptr; - const float getScaleY() - { - return float(window_height) / float(canvas_height); - } + uint16_t w, h; + uint8_t *pixels = LoadGif(buffer, &w, &h); - const int getOffsetX() - { - return offset_x; - } + int paletteSize; + uint32_t *pal = LoadPalette(buffer, &paletteSize); - const int getOffsetY() - { - return offset_y; - } + SDL_Texture *surf = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, w, h); + SDL_SetTextureBlendMode(surf, SDL_BLENDMODE_BLEND); - bool getFullscreen() { - return screen_fullscreen; - } + Uint32 *sdl_pixels; + int sdl_pitch; - void setFullscreen(const bool value) { - screen_fullscreen=value; - destroyDisplay(); - createDisplay(); - file::setConfigValueBool("fullscreen", screen_fullscreen); - } + SDL_LockTexture(surf, NULL, (void **)&sdl_pixels, &sdl_pitch); + for (uint32_t i = 0; i < w*h; ++i) sdl_pixels[i] = transparent==pixels[i] ? 0x00000000 : pal[pixels[i]] | 0xff000000; + SDL_UnlockTexture(surf); - void hideCursor() - { - screen_cursor = false; - SDL_HideCursor(); - } + free(pal); + free(pixels); + free(buffer); - void showCursor() - { - screen_cursor = true; - SDL_ShowCursor(); - } - - // Crea una superficie i torna un punter a ella - surface *createSurface(const uint16_t w, const uint16_t h) - { - // Primer reservem memòria per a la estructura "surface" - surface *surf = (surface *)malloc(sizeof(surface)); - - // Després reservem memòria per als pixels - surf->pixels = (uint8_t *)malloc(w * h); - - // I apuntem el ample i alt de la superficie - surf->w = w; - surf->h = h; - - // ...i tornem la superficie creada, clar return surf; } - // Carrega un gràfic d'un arxiu (en format GIF) a una nova superficie, i torna un punter a ella - surface *loadSurface(const char *filename, const bool loadPalette) + void freeSurface(SDL_Texture *surf) { - // Agafem un buffer de bytes de l'arxiu especificat - // getFileBuffer() simplement ens torna el arxiu sencer dins de un array de char - int size; - uint8_t *buffer = (uint8_t *)file::getFileBuffer(filename, size); - - // Si ens ha tornat nullptr, es que no l'ha trobat, tornem nosaltres també nullptr ja que no s'ha pogut crear la superficie - if (buffer == nullptr) - { - return nullptr; - } - - // Primer reservem memòria per a la estructura "surface" - surface *surf = (surface *)malloc(sizeof(surface)); - - // Després li passem el buffer de bytes a la funció de carregar un GIF. - // El resultat es un array de bytes, els pixels en sí. Ja havem reservat - // la memòria necessaria en "LoadGif", així que no tenim que fer-ho ara, - // però, ojo, sí que tindrem que alliberar-la. - surf->pixels = LoadGif(buffer, &surf->w, &surf->h); - - // Si li havem dit que carregue també la paleta... - if (loadPalette) - { - // Li passem el array del arxiu a LoadPalette. Ell ens torna un array de uint32_t amb la paleta - // Van a ser com a molt 256 entrades de 32 bits (pero no sempre), cada entrada es un color, amb el format 0xAARRGGBB - int paletteSize; - uint32_t *pal = LoadPalette(buffer, &paletteSize); - - // Copiem eixe array al nostre array de la paleta de sistema. Ara ja tenim la paleta carregada. - for (int i=0;i<256;++i) { - palette[i] = ipixels != nullptr) - { - free(surf->pixels); - } - - // ... alliberem la superficie - free(surf); - } + SDL_SetRenderTarget(sdl_renderer, surf); } - // Estableix una superficie com a superficie que rebrà les funcions de pintat (especificar nullptr per a pintar a pantalla) - void setDestination(surface *surf) + void setSource(SDL_Texture *surf) { - // Si han especificat nullptr, fiquem "screen" com a destinació - destination = surf == nullptr ? screen : surf; - resetViewport(); + sdl_source = surf; } - // Estableix una superficie com a superficie de la que s'agafaràn els gràfics per a pintar - void setSource(surface *surf) + + void setClip(const int x, const int y, const int w, const int h) { - // Si han especificat nullptr, fiquem "screen" com a font - source = surf == nullptr ? screen : surf; + SDL_Rect rect {x, y, w, h}; + SDL_SetRenderClipRect(sdl_renderer, &rect); } - void pushSource() + void resetClip() { - pushed_source = source; + SDL_SetRenderClipRect(sdl_renderer, nullptr); } - void popSource() + SDL_Point getWindowSize() { - source = pushed_source; - } - - void setViewport(const int x, const int y, const int w, const int h) - { - viewport.x = x>0?x:0; - viewport.y = y>0?y:0; - viewport.w = w+xw?w:destination->w; - viewport.h = h+yh?h:destination->h; - } - - void resetViewport() - { - viewport.x = viewport.y = 0; - viewport.w = destination->w; - viewport.h = destination->h; - } - - const int getLocalX(const int x) - { - return x - viewport.x; - } - - const int getLocalY(const int y) - { - return y - viewport.y; - } - - // Carrega la paleta d'un GIF i la torna en un array de uint32_t - uint32_t *loadPalette(const char *filename, int *paletteSize) - { - // Agafem un buffer de bytes de l'arxiu especificat - // getFileBuffer() simplement ens torna el arxiu sencer dins de un array de char - int size; - uint8_t *buffer = (uint8_t *)file::getFileBuffer(filename, size); - - // Li passem el array del arxiu a LoadPalette. Ell ens torna un array de uint32_t amb la paleta - // Van a ser 256 entrades de 32 bits, cada entrada es un color, amb el format 0xAARRGGBB - uint32_t *pal = LoadPalette(buffer); - - // I també el buffer del arxiu - free(buffer); - - if (paletteSize) *paletteSize = size; - return pal; - } - - // Estableix la paleta del sistema, o part de ella, des d'un array especificat - void setPalette(const uint32_t *pal, const int len, const int pos) - { - for (int i=0; i>16)&0xff, (col>>8)&0xff, (col)&0xff, (col>>24)&0xff); } - // Esborra la superficie "destination" amb el color especificat - void cls(const uint8_t color) + void cls(const uint32_t color) { - // El tamany es width x height bytes - const int size = destination->w * destination->h; - - // Omplim la memòria dels pixels de la superficie de destinació amb "color" - memset(destination->pixels, color, size); + setColor(color); + SDL_RenderClear(sdl_renderer); } - //Estableix el color especificat com a transparent - void setTrans(const uint8_t color) + void line(const int x1, const int y1, const int x2, const int y2) { - transparent = color; + SDL_RenderLine(sdl_renderer, x1, y1, x2, y2); } - // Funció interna per a pintar un pixel d'una superficie sense eixir-se'n de la memòria i petar el mame - void pset(surface *surface, const int x, const int y, const uint8_t color) + void fillrect(const int x, const int y, const int w, const int h) { - // Si el color es transparent, eixim, ni ens molestem en mirar res més - if (color == transparent) return; - - // Si pintem a "destination", mirem que estiga dins del "viewport" i sinó fora - if (surface == destination) { - if (x+viewport.x >= 0 && y+viewport.y >= 0 && x < viewport.w && y < viewport.h) - surface->pixels[(viewport.x+x) + (y+viewport.y) * surface->w] = color_indices[color]; - } else { - // Si no es destinations, mirem que estiga dins de la surface, i sinó fora! - if (x >= 0 && y >= 0 && x < surface->w && y < surface->h) - surface->pixels[x + y * surface->w] = color_indices[color]; - } + SDL_FRect rect {float(x), float(y), float(w),float(h)}; + SDL_RenderFillRect(sdl_renderer, &rect); } - // Funció interna per a llegir un pixel d'una superficie eixir-se'n de la memòria i petar el mame - const uint8_t pget(surface *surface, const int x, const int y) + void rect(const int x, const int y, const int w, const int h) { - // Si estem llegint de "destination", mirar que estigam llegint dins del viewport - if (surface == destination) { - if (x+viewport.x >= 0 && y+viewport.y >= 0 && x < viewport.w && y < viewport.h) - return surface->pixels[(viewport.x + x) + (viewport.y + y) * surface->w]; - } else { - // Si no es "destination", si la coordenada està dins del rang que abarca la superficie, - if (x >= 0 && y >= 0 && x < surface->w && y < surface->h) - return surface->pixels[x + y * surface->w]; - } - - return 0; + SDL_FRect rect {float(x), float(y), float(w),float(h)}; + SDL_RenderRect(sdl_renderer, &rect); } - void putPixel(const int x, const int y, const uint8_t color) + void draw(const SDL_Rect source, const SDL_Rect dest, const SDL_FlipMode flip) { - pset(screen, x, y, color); - } - - // Pinta un troç de la superficie "source" en la superficie "destination". - void draw(const int dx, const int dy, const int w, const int h, const int sx, const int sy, const draw::flip flip) - { - // Si no hi ha superficie d'oritge especificada, no fem res, o petarà el mame - if (source == nullptr) - { - return; - } - - // En principi, el quadrat de l'oritge començarà en (sx,sy) i avançarem 1 pixel en positiu tant en x com en y - int sdx = 1, sdy = 1, ssx = sx, ssy = sy; - - // Però si s'ha especificat que fem flip en horitzontal... - if (flip & draw::flip::horizontal) - { - sdx = -1; // Avançarem 1 pixel en negatiu - ssx = sx + w - 1; // I començarem al final, o siga, sumarem a sx el ample - } - - // De igual forma per al flip en vertical, per a la y - if (flip & draw::flip::vertical) - { - sdy = -1; - ssy = sy + h - 1; - } - - // guardem la coordenada d'oritge en x per a restablir-la a cada linea - int csx = ssx; - - // Anem linea per linea. Les variables dels dos bucles for controlen les coordenades en la destinació, que sempre van avant. - for (int y = dy; y < dy + h; ++y) - { - ssx = csx; // fiquem la coordenada de l'oritge al principi - - // en cada linea, anem pixel a pixel - for (int x = dx; x < dx + w; ++x) - { - pset(destination, x, y, pget(source, ssx, ssy)); // Agafem pixel de l'oritge i el fiquem en la destinació - ssx += sdx; // avancem (o retrocedim) la coordenada x de l'oritge - } - ssy += sdy; // avancem (o retrocedim) la coordenada y de l'oritge - } + if (!sdl_source) return; + SDL_FRect src {float(source.x), float(source.y), float(source.w),float(source.h)}; + SDL_FRect dst {float(dest.x), float(dest.y), float(dest.w),float(dest.h)}; + SDL_RenderTextureRotated(sdl_renderer, sdl_source, &src, &dst, 0.0, nullptr, flip); } +/* void draw(const int dx, const int dy, const int w, const int h, const int sx, const int sy, const int zoom) { // Si no hi ha superficie d'oritge especificada, no fem res, o petarà el mame @@ -549,137 +168,16 @@ namespace draw } // Carrega la superficie especificada en "source" i la pinta tota en la superficie "destination", posició (0,0). - void draw(draw::surface* surf) + void draw(SDL_Texture* surf) { setSource(surf); draw(); } - - void swapcol(const Uint8 c1, const Uint8 c2) - { - color_indices[c1] = c2; - } - - void restorecol(const Uint8 c) - { - color_indices[c] = c; - } - - void color(const Uint8 col) - { - sel_color = col; - } - - void hline(const int x, const int y, const int w) - { - for (int i=x;i> 16) & 0xff; - uint8_t g = (entry >> 8) & 0xff; - uint8_t b = entry & 0xff; - - r = r>=val ? r-val : 0; - g = g>=val ? g-val : 0; - b = b>=val ? b-val : 0; - palette[index] = (r << 16) + (g << 8) + b; - - return palette[index] != 0; - } - - bool incPalEntry(const uint8_t index, const uint8_t val) - { - const uint32_t entry = palette[index]; - uint8_t r = (entry >> 16) & 0xff; - uint8_t g = (entry >> 8) & 0xff; - uint8_t b = entry & 0xff; - - const uint32_t dest_entry = aux_palette[index]; - const uint8_t dr = (dest_entry >> 16) & 0xff; - const uint8_t dg = (dest_entry >> 8) & 0xff; - const uint8_t db = dest_entry & 0xff; - - r = (r+val > dr) ? dr : r+val; - g = (g+val > dg) ? dg : g+val; - b = (b+val > db) ? db : b+val; - palette[index] = (r << 16) + (g << 8) + b; - - return palette[index] != aux_palette[index]; - } - - void fadein() - { - if (!fading_in) { - for (int i=0;i<256;++i) { - aux_palette[i] = palette[i]; - palette[i] = 0; - } - } - fading_in = false; - for (int i=0; i<256; ++i) if (incPalEntry(i, 8)) fading_in = true; - } - - void fadeout() - { - fading_out = false; - for (int i=0; i<256; ++i) if (decPalEntry(i, 8)) fading_out = true; - } - - bool isfading() - { - return fading_in || fading_out; - } +*/ // Refresca la pantalla void render() { - Uint32 *sdl_pixels; // Punter al array de pixels que enstornarà SDL_LockTexture - int sdl_pitch; // Ací estarà guardat el pitch de la textura, com es de 32 bits, no m'afecta - const uint32_t size = screen->w * screen->h; // tamany de la superficie - - if (fading_in) fadein(); - if (fading_out) fadeout(); - - // Bloquejem la textura SDL i agafem els seus pixels (son enters de 32 bits amb format 0xAARRGGBB) - SDL_LockTexture(sdl_texture, NULL, (void **)&sdl_pixels, &sdl_pitch); - - // Cada pixel de la superficie "screen" es un enter de 8 bits que representa un index en la paleta de colors - // Per tant, per a pintar en la textura SDL, pillem el color de la paleta que correspon al index en "screen" - // i el enviem a la textura SDL - for (uint32_t i = 0; i < size; ++i) - { - sdl_pixels[i] = palette[screen->pixels[i]] | 0xff000000; - } - - // Desbloquejem la textura - SDL_UnlockTexture(sdl_texture); - - SDL_SetRenderTarget(sdl_renderer, nullptr); - // Pintem la textura a pantalla - SDL_RenderTexture(sdl_renderer, sdl_texture, NULL, NULL); - - // I ho presentem SDL_RenderPresent(sdl_renderer); } diff --git a/source/japi/draw.h b/source/japi/draw.h index 4496451..5f8bdde 100644 --- a/source/japi/draw.h +++ b/source/japi/draw.h @@ -1,158 +1,36 @@ #pragma once #include +#include -//#define DRAW_FLIP_NONE 0 -//#define DRAW_FLIP_HORIZONTAL 1 -//#define DRAW_FLIP_VERTICAL 2 -//#define DRAW_FLIP_BOTH 3 - -// Unitat per a la gestió dels recursos gràfics i dibuixat en pantalla namespace draw { enum flip { none, horizontal, vertical, both }; - // Estructura per a mantindre una superficie de pintat, la "pantalla virtual" de tota la vida - struct surface - { - uint16_t w; // Ample de la superficie - uint16_t h; // Alt de la superficie - uint8_t *pixels; // pixels de la superficie - }; - - /// @brief Inicialització de tot el que fa falta per a carregar gràfics i pintar en pantalla. - /// @brief La finestra serà width*zoom x height*zoom de gran. - /// @param titol es el text que apareixerà en la finestra - /// @param width es el ample de la finestra "virtual" - /// @param height es el alt de la finestra "virtual" - /// @param zoom es com de grans son els pixels. - void init(const char *titol, const uint16_t width, const uint16_t height, const int zoom, const bool fullscreen=false, const float ratio=1.0); - - /// @brief Finalització del sistema (tancar coses de SDL, superficies fixes, etc...) + void init(const char *titol, const uint16_t width, const uint16_t height); void quit(); - void setZoom(const int value); - const int getZoom(); - const float getScaleX(); - const float getScaleY(); - const int getOffsetX(); - const int getOffsetY(); + SDL_Texture *createSurface(const uint16_t w, const uint16_t h); + SDL_Texture *loadSurface(const char* filename, const int transparent = -1); + void freeSurface(SDL_Texture *surf); + void setDestination(SDL_Texture *surf); + void setSource(SDL_Texture *surf); - bool getFullscreen(); - void setFullscreen(const bool value); + void setClip(const int x, const int y, const int w, const int h); + void resetClip(); - void hideCursor(); - void showCursor(); + SDL_Point getWindowSize(); - /// @brief Crea una superficie i torna un punter a ella - /// @param w ample de la superficie - /// @param h alt de la superficie - /// @return un punter a una nova superficie - surface *createSurface(const uint16_t w, const uint16_t h); - - /// @brief Carrega un gràfic d'un arxiu (en format GIF) a una nova superficie, i torna un punter a ella - /// @param filename nom de l'arxiu GIF d'on carregar la superficie - /// @param loadPalette si es true també se carrega la paleta del GIF - /// @return un punter a una nova superficie - surface *loadSurface(const char* filename, const bool loadPalette = false); - - /// @brief Allibera la memòria d'una superficie, els seus pixels inclosos - /// @param surf punter a la superficie a alliberar - void freeSurface(surface *surf); - - /// @brief Estableix una superficie com a superficie que rebrà les funcions de pintat (especificar nullptr per a pintar a pantalla) - /// @param surf punter a la superficie a establir com a destinació - void setDestination(surface *surf); - - /// @brief Estableix una superficie com a superficie de la que s'agafaràn els gràfics per a pintar - /// @param surf punter a la superficie a establir com a oritge - void setSource(surface *surf); - - void pushSource(); - void popSource(); - - void setViewport(const int x, const int y, const int w, const int h); - void resetViewport(); - - const int getLocalX(const int x); - const int getLocalY(const int y); - - /// @brief Carrega la paleta d'un GIF i la torna en un array de uint32_t - /// @param filename nom de l'arxiu GIF d'on carregar la paleta - /// @param paletteSize si no es NULL ens torna el tamany de la paleta carregada - uint32_t *loadPalette(const char *filename, int *paletteSize = nullptr); - - /// @brief Estableix la paleta del sistema, o part de ella, des d'un array especificat - /// @param pal un array de uint32_t - /// @param len quantes entrades volem trasladar a la paleta de sistema (no superar el tamany de 'pal'!) - /// @param pos des de quina posició de la paleta de sistema comencem a copiar - void setPalette(const uint32_t *pal, const int len, const int pos=0); - - /// @brief Recupera la paleta del sistema, o part de ella, a un array - /// @return un array de uint32_t - uint32_t *getPalette(); - - /// @brief Estableix una entrada de la paleta del sistema - /// @param index l'index de l'entrada de la paleta - /// @param r la component roja de l'entrada de la paleta - /// @param g la component verda de l'entrada de la paleta - /// @param b la component blava de l'entrada de la paleta - void setPaletteEntry(const uint8_t index, const uint8_t r, const uint8_t g, const uint8_t b); - - /// @brief Esborra la superficie "destination" amb el color especificat - /// @param color color a usar per a borrar la superficie de destinació - void cls(const uint8_t color); - - /// @brief Estableix el color especificat com a transparent - /// @param color color a usar com a transparent - void setTrans(const uint8_t color); - - void putPixel(const int x, const int y, const uint8_t color); - - /// @brief Pinta un troç de la superficie "source" en la superficie "destination". - /// @param dx coordenada x de la destinació - /// @param dy coordenada y de la destinació - /// @param w ample del quadrat a pintar - /// @param h alt del quadrat a pintar - /// @param sx coordenada x de l'oritge - /// @param sy coordenada y de l'oritge - /// @param flip si s'ha de fer flip en hortizontal o vertical (o ambdos) - void draw(const int dx, const int dy, const int w, const int h, const int sx, const int sy, const draw::flip flip = draw::flip::none); - - /// @brief Pinta un troç de la superficie "source" en la superficie "destination", amb zoom. - /// @param dx coordenada x de la destinació - /// @param dy coordenada y de la destinació - /// @param w ample del quadrat d'oritge a pintar - /// @param h alt del quadrat d'oritge a pintar - /// @param sx coordenada x de l'oritge - /// @param sy coordenada y de l'oritge - /// @param zoom zoom a aplicar al pintar - void draw(const int dx, const int dy, const int w, const int h, const int sx, const int sy, const int zoom); - - /// @brief Pinta tota la superficie "source" en la superficie "destination", posició (x,y). - /// @param x coordenada x de la destinació - /// @param y coordenada y de la destinació - void draw(const int x, const int y); - - /// @brief Pinta tota la superficie "source" en la superficie "destination", posició (0,0). - void draw(); - - /// @brief Carrega la superficie especificada en "source" i la pinta tota en la superficie "destination", posició (0,0). - void draw(draw::surface* surf); - - void swapcol(const uint8_t c1, const uint8_t c2); - void restorecol(const uint8_t c); - void color(const uint8_t col); - void hline(const int x, const int y, const int w); - void vline(const int x, const int y, const int h); + void setColor(const uint32_t col); + void cls(const uint32_t color); + void line(const int x1, const int y1, const int x2, const int y2); void fillrect(const int x, const int y, const int w, const int h); void rect(const int x, const int y, const int w, const int h); - void fadein(); - void fadeout(); - bool isfading(); + void draw(const SDL_Rect source, const SDL_Rect dest, const SDL_FlipMode flip = SDL_FLIP_NONE); + //void draw(const int x, const int y); + //void draw(); + //void draw(SDL_Texture* surf); + - //void print(const char* text, const int x, const int y, const uint8_t color, const uint8_t borde); - - /// @brief Refresca la pantalla void render(); } diff --git a/source/japi/font.cpp b/source/japi/font.cpp new file mode 100644 index 0000000..d51eae7 --- /dev/null +++ b/source/japi/font.cpp @@ -0,0 +1,73 @@ +#include "font.h" +#include "draw.h" +#include "file.h" +#include + +namespace font +{ + SDL_Texture *surf {nullptr}; + char spaces[127]; + int pos = 30; + int chars_per_line = 0; + + void load(const char* filename) + { + char font_filename[256]; + strcpy(font_filename, filename); + strcat(font_filename, ".txt"); + + int filesize; + char *buffer = file::getFileBuffer(font_filename, filesize, true); + char *p = buffer; + + pos = 30; + bool eof = false; + while (true) { + if (*p=='#') while (*p!=0 && *p!=10) p++; + if (*p==0) break; + p++; + spaces[pos++] = (*p)-48; + if (pos==127) break; + p++; + if (*p==0) break; + p++; + } + free(buffer); + + char gif_filename[256]; + strcpy(gif_filename, filename); + strcat(gif_filename, ".gif"); + surf = draw::loadSurface(gif_filename, 0); + } + + void printChar(const char c, int x, int y) + { + const int w = spaces[30]; + const int h = spaces[31]; + const int chars_per_line = (surf->w/w); + const int sx = ((c-32) % chars_per_line)*8; + const int sy = ((c-32) / chars_per_line)*8; + //printf("char %i, sx:%i, sy:%i\n", c, sx, sy); + draw::draw({sx, sy, spaces[c], h}, {x, y, spaces[c], h}); + } + + void print(const char* text, int x, int y) + { + draw::setSource(surf); + while(*text) { + printChar(*text, x, y); + x += spaces[*text]+1; + text++; + } + } + + const int len(const char *text) + { + int l = 0; + while (*text) { + l += spaces[*text]+1; + text++; + } + return l-1; + } +} diff --git a/source/japi/font.h b/source/japi/font.h new file mode 100644 index 0000000..2721246 --- /dev/null +++ b/source/japi/font.h @@ -0,0 +1,8 @@ +#pragma once + +namespace font +{ + void load(const char* filename); + void print(const char* text, int x, int y); + const int len(const char *text); +} diff --git a/source/japi/game.cpp b/source/japi/game.cpp index 88e0365..1c2613b 100644 --- a/source/japi/game.cpp +++ b/source/japi/game.cpp @@ -84,19 +84,19 @@ int main(int argc, char *argv[]) } if (e.type==SDL_EVENT_KEY_UP) { - switch (e.key.scancode) { - case SDL_SCANCODE_F1: - draw::setZoom(draw::getZoom()-1); - break; - case SDL_SCANCODE_F2: - draw::setZoom(draw::getZoom()+1); - break; - case SDL_SCANCODE_F3: - draw::setFullscreen(!draw::getFullscreen()); - break; - default: +// switch (e.key.scancode) { +// case SDL_SCANCODE_F1: +// draw::setZoom(draw::getZoom()-1); +// break; +// case SDL_SCANCODE_F2: +// draw::setZoom(draw::getZoom()+1); +// break; +// case SDL_SCANCODE_F3: +// draw::setFullscreen(!draw::getFullscreen()); +// break; +// default: input::updateKeypressed(e.key.scancode); - } +// } } if (e.type==SDL_EVENT_MOUSE_BUTTON_UP) { diff --git a/source/japi/input.cpp b/source/japi/input.cpp index 7e78cba..74f3ea4 100644 --- a/source/japi/input.cpp +++ b/source/japi/input.cpp @@ -1,6 +1,5 @@ #include "input.h" #include -#include "draw.h" namespace input { @@ -79,7 +78,7 @@ namespace input { float x; SDL_GetMouseState(&x, NULL); - return (x-draw::getOffsetX())/draw::getScaleX(); + return x; } // Torna la posició Y actual del ratolí @@ -87,7 +86,7 @@ namespace input { float y; SDL_GetMouseState(NULL, &y); - return (y-draw::getOffsetY())/draw::getScaleY(); + return y; } // Determina si el botó del ratolí especificat està sent polsada ara mateix @@ -103,6 +102,11 @@ namespace input return btnClicked == btn; } + void mouseDiscard() + { + btnClicked = 0; + } + // Obté el valor actual de la rodeta del ratolí const int mouseWheel() { diff --git a/source/japi/input.h b/source/japi/input.h index 8fc7241..32792b7 100644 --- a/source/japi/input.h +++ b/source/japi/input.h @@ -80,6 +80,8 @@ namespace input /// @return true si està polsat, false si no const bool mouseClk(const int btn); + void mouseDiscard(); + /// @brief Obté el valor actual de la rodeta del ratolí /// @return 0 si no es mou, positiu si roda cap amunt, negatiu si roda cap avall const int mouseWheel(); diff --git a/source/main.cpp b/source/main.cpp index 9ec3dec..96776b9 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,31 +1,45 @@ -#include "rooms.h" -#include "enemies.h" #include "japi/draw.h" #include "japi/game.h" -#include "images.h" +#include "japi/font.h" +#include "menu.h" bool loop(); void game::init() { - draw::init("DILEMMAKER v0.1", 320, 240, 2, false); + draw::init("DILEMMAKER v0.1", 800, 600); game::setState(loop); - enemies::load(); - rooms::load(); - images::loadPalette("./data/palette/zx-spectrum.pal"); + font::load("font/8bithud"); } bool loop() { - draw::cls(4); - draw::setTrans(255); - //rooms::drawFullMap(); - - rooms::draw(); - draw::color(COLOR_BRIGHT_BLACK); - /*for (int i=0; i<=32; ++i) draw::vline(64+i*16, 48, 256); - for (int i=0; i<=16; ++i) draw::hline(64, 48+i*16, 512); - */ + draw::cls(0x00000000); + + menu::start(); + if (menu::option("FILE")) { + menu::popup::start(); + menu::popup::end(); + } + if (menu::option("EDIT")) { + menu::popup::start(); + menu::popup::end(); + } + if (menu::option("SELECTION")) { + menu::popup::start(); + menu::popup::end(); + } + if (menu::option("VIEW")) { + menu::popup::start(); + menu::popup::end(); + } + + /*x1 += 6; x2 = x1 + font::len("FILE")+6; + font::print("FILE", x1, 5); x1=x2; + + font::print("EDIT", x, 5); x+= font::len("EDIT")+12; + font::print("SELECTION", x, 5); x+= font::len("SELECTION")+12; + font::print("VIEW", x, 5); x+= font::len("VIEW")+12;*/ draw::render(); return true; } diff --git a/source/menu.cpp b/source/menu.cpp new file mode 100644 index 0000000..56332a8 --- /dev/null +++ b/source/menu.cpp @@ -0,0 +1,68 @@ +#include "menu.h" +#include "japi/input.h" +#include "japi/draw.h" +#include "japi/font.h" + +namespace menu +{ + int x1, x2, m; + int menu_shown = -1; + + void start() + { + draw::setColor(0xff3c3c3c); + draw::fillrect(0,0,draw::getWindowSize().x,24); + x1=0; x2=0; m=-1; + } + + bool option(const char* label) + { + m++; + x1 = x2 + 8; x2 = x1 + font::len(label)+8; + int mx = input::mouseX(); + int my = input::mouseY(); + if (mx>=x1 && my>=0 && mx=x1-8 && my>=24 && mx -#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; - draw::surface *map_surface {nullptr}; - - 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!=0 ? room.bgColor : 1; - } - } - } - } - - 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++; - - if (map_surface) draw::freeSurface(map_surface); - map_surface = draw::createSurface(256,128); - - /*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; - } - }*/ - /*room_t &room = rooms["01"]; - 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["01"]; - - draw::setTrans(16); - draw::setDestination(map_surface); - draw::resetViewport(); - draw::setSource(room.tileSetFile); - draw::cls(room.bgColor); - - 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); - } - } - } - - draw::setTrans(0); - 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::setTrans(16); - draw::setDestination(nullptr); - draw::setSource(map_surface); - draw::cls(COLOR_BRIGHT_BLACK); - //draw::color(room.border); - //draw::fillrect(48, 32, 512+32, 256+32); - //draw::setViewport(64, 48, 512, 256); - draw::setViewport(32, 24, 256, 128); - draw::draw(0, 0); - draw::resetViewport(); - - //draw::setSource(room.thumbnail); - //draw::draw(); - } - - uint8_t blinking = 0; - void drawFullMap() - { - blinking = (blinking+1)%16; - 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(); - - if (item.first == "01") { - draw::color(blinking); - draw::rect(x-1, y-1, 36, 20); - draw::color(COLOR_BLACK); - draw::rect(x, y, 34, 18); - } else { - draw::color(COLOR_WHITE); - draw::rect(x+1, y+1, 34, 18); - draw::color(COLOR_BLACK); - 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.roomLeft != "0") draw::fillrect(x-4, y+7, 4, 4); - } - } - -} diff --git a/source/rooms.h b/source/rooms.h deleted file mode 100644 index f233d7b..0000000 --- a/source/rooms.h +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once -#include -#include -#include -#include "japi/draw.h" - -#define COLOR_BLACK 0 -#define COLOR_BRIGHT_BLACK 1 -#define COLOR_BLUE 2 -#define COLOR_BRIGHT_BLUE 3 -#define COLOR_RED 4 -#define COLOR_BRIGHT_RED 5 -#define COLOR_MAGENTA 6 -#define COLOR_BRIGHT_MAGENTA 7 -#define COLOR_GREEN 8 -#define COLOR_BRIGHT_GREEN 9 -#define COLOR_CYAN 10 -#define COLOR_BRIGHT_CYAN 11 -#define COLOR_YELLOW 12 -#define COLOR_BRIGHT_YELLOW 13 -#define COLOR_WHITE 14 -#define COLOR_BRIGHT_WHITE 15 - -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]; - draw::surface *thumbnail {nullptr}; - int map_x {0}; - int map_y {0}; - }; - - void load(); - void draw(); - void drawFullMap(); -}