diff --git a/data/map/01 - copia.tmx b/data/map/01 - copia.tmx new file mode 100644 index 0000000..c8bd17e --- /dev/null +++ b/data/map/01 - copia.tmx @@ -0,0 +1,38 @@ + + + + + +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,225,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + + + + +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,68,68,0,0,0,0,0,0,0,0,74,74,74,0,0,0,0, +74,74,74,75,75,74,74,68,68,68,68,68,74,74,78,74,68,74,68,68 + + + diff --git a/data/map/01.map b/data/map/01.map new file mode 100644 index 0000000..fb09aba --- /dev/null +++ b/data/map/01.map @@ -0,0 +1,11 @@ +tileset_img=tiles_surface.png +bg_img=bg_surface.png + +room_up=0 +room_down=0 +room_left=0 +room_right=0 + +[tilemap] +01.tmx +[tilemap-end] \ No newline at end of file diff --git a/data/map/01.tmx b/data/map/01.tmx new file mode 100644 index 0000000..698e5b5 --- /dev/null +++ b/data/map/01.tmx @@ -0,0 +1,21 @@ + + + + + +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,68,68,0,0,0,0,0,0,0,0,74,74,74,0,0,0,0, +74,74,74,75,75,74,74,68,68,68,68,68,74,74,78,74,68,74,68,68 + + + diff --git a/data/volcano.map b/data/volcano.map deleted file mode 100644 index fc53dab..0000000 Binary files a/data/volcano.map and /dev/null differ diff --git a/source/const.h b/source/const.h index b318fe5..aea615f 100644 --- a/source/const.h +++ b/source/const.h @@ -3,12 +3,9 @@ #ifndef CONST_H #define CONST_H -// Textos -#define WINDOW_CAPTION "Volcano (©2016,2022 JailDesigner v0.6)" - // Tamaño de bloque -#define BLOCK 8 -#define HALF_BLOCK 4 +#define BLOCK 16 +#define HALF_BLOCK 8 // Tamaño de la pantalla real #define SCREEN_WIDTH 320 diff --git a/source/game.cpp b/source/game.cpp index 0d3af22..8df6571 100644 --- a/source/game.cpp +++ b/source/game.cpp @@ -3,19 +3,21 @@ // Constructor Game::Game(SDL_Renderer *renderer, Asset *asset, Screen *screen, Input *input) { - + this->renderer = renderer; this->asset = asset; this->screen = screen; this->input = input; eventHandler = new SDL_Event(); + map = new Map(asset->get("01.map"), renderer, asset); } // Destructor Game::~Game() { delete eventHandler; + delete map; } // Bucle para el juego @@ -78,6 +80,9 @@ void Game::render() screen->start(); screen->clean(); + // Dibuja el mapa + map->render(); + // Actualiza la pantalla screen->blit(); } \ No newline at end of file diff --git a/source/game.h b/source/game.h index fd7577e..9953857 100644 --- a/source/game.h +++ b/source/game.h @@ -4,6 +4,7 @@ #include "asset.h" #include "screen.h" #include "input.h" +#include "map.h" #ifndef GAME_H #define GAME_H @@ -19,6 +20,7 @@ private: section_t section; // Seccion actual dentro del programa int ticks; // Contador de ticks para ajustar la velocidad del programa int ticksSpeed; // Velocidad a la que se repiten los bucles del programa + Map *map; // Objeto encargado de gestionar el mapeado del juego // Actualiza el juego, las variables, comprueba la entrada, etc. void update(); diff --git a/source/map.cpp b/source/map.cpp index 0b0148b..7d9596a 100644 --- a/source/map.cpp +++ b/source/map.cpp @@ -1,12 +1,212 @@ #include "map.h" // Constructor -Map::Map() +Map::Map(std::string file, SDL_Renderer *renderer, Asset *asset) { + // Copia los punteros a objetos + this->asset = asset; + this->renderer = renderer; + // Crea los objetos + texture_tile = new LTexture(); + texture_bg = new LTexture(); + load(file); + loadTextureFromFile(texture_tile, asset->get(tileset_img), renderer); + loadTextureFromFile(texture_bg, asset->get(bg_img), renderer); + + // Crea la textura para el mapa de tiles de la habitación + map_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT); + if (map_texture == NULL) + printf("Error: map_texture could not be created!\nSDL Error: %s\n", SDL_GetError()); + + // Pinta el mapa de la habitación en la textura + fillMapTexture(); } // Destructor Map::~Map() { + // Reclama la memoria utilizada por los objetos + texture_tile->unload(); + delete texture_tile; + + texture_bg->unload(); + delete texture_bg; + + SDL_DestroyTexture(map_texture); } + +// Carga las variables desde un fichero +bool Map::load(std::string file_path) +{ + // Indicador de éxito en la carga + bool success = true; + + std::string filename = file_path.substr(file_path.find_last_of("\\/") + 1); + std::string line; + std::ifstream file(file_path); + + // El fichero se puede abrir + if (file.good()) + { + // Procesa el fichero linea a linea + printf("Reading file %s\n", filename.c_str()); + while (std::getline(file, line)) + { + // Si la linea contiene el texto [tilemap] se realiza el proceso de carga del fichero tmx + if (line == "[tilemap]") + { + do + { + std::getline(file, line); + if (line.find(".tmx") != std::string::npos) + { + std::ifstream file2(asset->get(line)); // Abre el fichero tmx + if (file2.good()) + { + bool data_read = false; + while (std::getline(file2, line)) // Lee el fichero linea a linea + { + if (!data_read) + { // Lee lineas hasta que encuentre donde empiezan los datos del mapa + int pos = 0; + do + { + std::getline(file2, line); + pos = line.find("data encoding"); + } while (pos == std::string::npos); + + do + { // Se introducen los valores separados por comas en un vector + data_read = true; + std::getline(file2, line); + if (line != "") + { + std::stringstream ss(line); + std::string tmp; + while (getline(ss, tmp, ',')) + { + tilemap.push_back(std::stoi(tmp)); + } + } + } while (line != ""); + } + } + } + } + } while (line != "[tilemap-end]"); + } + + // En caso contrario se parsea el fichero para buscar las variables y los valores + else + { + // Encuentra la posición del caracter '=' + int pos = line.find("="); + // Procesa las dos subcadenas + if (!setVars(line.substr(0, pos), line.substr(pos + 1, line.length()))) + { + printf("Warning: file %s, unknown parameter \"%s\"\n", filename.c_str(), line.substr(0, pos).c_str()); + success = false; + } + } + } + + // Cierra el fichero + printf("Closing file %s\n", filename.c_str()); + file.close(); + } + // El fichero no se puede abrir + else + { + printf("Warning: Unable to open %s file\n", filename.c_str()); + success = false; + } + + return success; +} + +// Asigna variables a partir de dos cadenas +bool Map::setVars(std::string var, std::string value) +{ + // Indicador de éxito en la asignación + bool success = true; + + if (var == "bg_img") + { + bg_img = value; + } + else if (var == "tileset_img") + { + tileset_img = value; + } + else if (var == "room_up") + { + room_up = value; + } + else if (var == "room_down") + { + room_down = value; + } + else if (var == "room_left") + { + room_left = value; + } + else if (var == "room_right") + { + room_right = value; + } + else if (var == "tilemap") + { + // Se introducen los valores separados por comas en un vector + std::stringstream ss(value); + std::string tmp; + while (getline(ss, tmp, ',')) + { + tilemap.push_back(std::stoi(tmp)); + } + } + else if (var == "") + { + } + else + { + success = false; + } + + return success; +} + +// Crea la textura con el mapeado de la habitación +void Map::fillMapTexture() +{ + SDL_SetRenderTarget(renderer, map_texture); + SDL_SetTextureBlendMode(map_texture, SDL_BLENDMODE_BLEND); + SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00); + SDL_RenderClear(renderer); + + const int tile_size = 16; + const int map_width_in_tiles = 20; + const int map_height_in_tiles = 13; + + SDL_Rect clip = {0, 0, tile_size, tile_size}; + + for (int y = 0; y < map_height_in_tiles; y++) + for (int x = 0; x < map_width_in_tiles; x++) + { + clip.x = ((tilemap[(y * map_width_in_tiles) + x] - 1) % 16) * tile_size; + clip.y = ((tilemap[(y * map_width_in_tiles) + x] - 1) / 16) * tile_size; + texture_tile->render(renderer, x * tile_size, y * tile_size, &clip); + } + + SDL_SetRenderTarget(renderer, nullptr); +} + +// Dibuja el mapa en pantalla +void Map::render() +{ + // Dibuja el fondo + + // Dibuja la textura con el mapa en pantalla + SDL_Rect rect = {0, 0, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT}; + SDL_RenderCopy(renderer, map_texture, &rect, NULL); +} \ No newline at end of file diff --git a/source/map.h b/source/map.h index da2c0ce..485af7f 100644 --- a/source/map.h +++ b/source/map.h @@ -1,4 +1,14 @@ #pragma once + +#include +#include "utils.h" +#include "asset.h" +#include "const.h" +#include +#include +#include +#include + #ifndef MAP_H #define MAP_H @@ -6,13 +16,40 @@ class Map { private: + Asset *asset; // Objeto con la ruta a todos los ficheros de recursos + SDL_Renderer *renderer; // El renderizador de la ventana + std::string room_up; // Identificador de la habitación que se encuentra arriba + std::string room_down; // Identificador de la habitación que se encuentra abajp + std::string room_left; // Identificador de la habitación que se encuentra a la izquierda + std::string room_right; // Identificador de la habitación que se encuentra a la derecha + std::string tileset_img; // Imagen con los graficos para la habitación + std::string bg_img; // Imagen con los graficos para la habitación + std::vector tilemap; // Indice de los tiles a dibujar en la habitación + LTexture *texture_tile; // Textura con los graficos de los tiles habitación + LTexture *texture_bg; // Textura con los graficos de fondo de la habitación + SDL_Texture *map_texture; // Textura para dibujar el mapa de la habitación + + // Carga las variables desde un fichero + bool load(std::string file); + + // Asigna variables a partir de dos cadenas + bool setVars(std::string var, std::string value); + + // Pinta el mapa de la habitación en la textura + void fillMapTexture(); public: // Constructor - Map(); + Map(std::string file, SDL_Renderer *renderer, Asset *asset); // Destructor ~Map(); + + // Actualiza todas las variables + void update(); + + // Dibuja el objeto + void render(); }; #endif diff --git a/source/prog.cpp b/source/prog.cpp index 09b5ecc..fe25417 100644 --- a/source/prog.cpp +++ b/source/prog.cpp @@ -29,7 +29,7 @@ Prog::Prog(std::string executablePath) section.name = SECTION_PROG_GAME; } input = new Input(asset->get("gamecontrollerdb.txt")); - screen = new Screen(window, renderer, options->screenWidth, options->screenWidth, GAME_WIDTH, GAME_HEIGHT); + screen = new Screen(window, renderer, options); } Prog::~Prog() @@ -115,7 +115,8 @@ bool Prog::initSDL() bool Prog::setFileList() { // Ficheros binarios - asset->add("/data/volcano.map", data); + asset->add("/data/map/01.map", data); + asset->add("/data/map/01.tmx", data); asset->add("/data/config.bin", data, false); asset->add("/data/gamecontrollerdb.txt", data); diff --git a/source/screen.cpp b/source/screen.cpp index e9f4a0e..4f71934 100644 --- a/source/screen.cpp +++ b/source/screen.cpp @@ -1,20 +1,25 @@ #include "screen.h" +#include "const.h" +#include +#include // Constructor -Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, int scr_w, int scr_h, int gc_w, int gc_h) +Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, options_t *options) { // Inicializa variables this->window = window; this->renderer = renderer; + this->options = options; - screenWidth = scr_w; - screenHeight = scr_h; - gameCanvasWidth = gc_w; - gameCanvasHeight = gc_h; - gameCanvasPosX = (scr_w - gc_w) / 2; - gameCanvasPosY = (scr_h - gc_h) / 2; - dest = {gameCanvasPosX, gameCanvasPosY, gameCanvasWidth, gameCanvasHeight}; + gameCanvasWidth = SCREEN_WIDTH; + gameCanvasHeight = SCREEN_HEIGHT; + + // Establece el modo de video + setVideoMode(options->fullScreenMode); + + // Define el color del borde para el modo de pantalla completa borderColor = {0x27, 0x27, 0x36}; + borderColor = {0x00, 0x00, 0x00}; // Crea la textura donde se dibujan los graficos del juego gameCanvas = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, gameCanvasWidth, gameCanvasHeight); @@ -56,4 +61,73 @@ void Screen::blit() // Muestra por pantalla el renderizador SDL_RenderPresent(renderer); +} + +// Establece el modo de video +void Screen::setVideoMode(int fullScreenMode) +{ + // Aplica el modo de video + SDL_SetWindowFullscreen(window, fullScreenMode); + + // Si está activo el modo ventana quita el borde + if (fullScreenMode == 0) + { + screenWidth = gameCanvasWidth; + screenHeight = gameCanvasHeight; + dest = {0, 0, gameCanvasWidth, gameCanvasHeight}; + + // Modifica el tamaño del renderizador y de la ventana + SDL_RenderSetLogicalSize(renderer, screenWidth, screenHeight); + SDL_SetWindowSize(window, screenWidth * options->windowSize, screenHeight * options->windowSize); + } + + // Si está activo el modo de pantalla completa añade el borde + if (fullScreenMode == SDL_WINDOW_FULLSCREEN_DESKTOP) + { + // Obten el alto y el ancho de la ventana + SDL_GetWindowSize(window, &screenWidth, &screenHeight); + + // Aplica el escalado al rectangulo donde se pinta la textura del juego + if (options->integerScale) + { + // Calcula el tamaño de la escala máxima + int scale = 0; + while (((gameCanvasWidth * (scale + 1)) <= screenWidth) && ((gameCanvasHeight * (scale + 1)) <= screenHeight)) + { + scale++; + } + + dest.w = gameCanvasWidth * scale; + dest.h = gameCanvasHeight * scale; + dest.x = (screenWidth - dest.w) / 2; + dest.y = (screenHeight - dest.h) / 2; + } + else if (options->keepAspect) + { + float ratio = (float)gameCanvasWidth / (float)gameCanvasHeight; + if ((screenWidth - gameCanvasWidth) >= (screenHeight - gameCanvasHeight)) + { + dest.h = screenHeight; + dest.w = (int)((screenHeight * ratio) + 0.5f); + dest.x = (screenWidth - dest.w) / 2; + dest.y = (screenHeight - dest.h) / 2; + } + else + { + dest.w = screenWidth; + dest.h = (int)((screenWidth / ratio) + 0.5f); + dest.x = (screenWidth - dest.w) / 2; + dest.y = (screenHeight - dest.h) / 2; + } + } + else + { + dest.w = screenWidth; + dest.h = screenHeight; + dest.x = dest.y = 0; + } + + // Modifica el tamaño del renderizador + SDL_RenderSetLogicalSize(renderer, screenWidth, screenHeight); + } } \ No newline at end of file diff --git a/source/screen.h b/source/screen.h index 014b1bc..baa7699 100644 --- a/source/screen.h +++ b/source/screen.h @@ -9,23 +9,21 @@ class Screen { private: - SDL_Window *window; // Ventana de la aplicación - SDL_Renderer *renderer; // El renderizador de la ventana + SDL_Window *window; // Ventana de la aplicación + SDL_Renderer *renderer; // El renderizador de la ventana SDL_Texture *gameCanvas; // Textura para completar la ventana de juego hasta la pantalla completa + options_t *options; // Variable con todas las opciones del programa - int screenWidth; // Ancho de la pantalla - int screenHeight; // Alto de la pantalla + int screenWidth; // Ancho de la pantalla + int screenHeight; // Alto de la pantalla int gameCanvasWidth; // Ancho de la textura donde se dibuja el juego int gameCanvasHeight; // Alto de la textura donde se dibuja el juego - int gameCanvasPosX; // Posicion en el eje X donde se dibujará la textura del juego dentro de la pantalla - int gameCanvasPosY; // Posicion en el eje Y donde se dibujará la textura del juego dentro de la pantalla - - SDL_Rect dest; // Rectangulo de destino donde se dibujarà la textura con el juego - color_t borderColor; // Color del borde añadido a la textura de juego para rellenar la pantalla + SDL_Rect dest; // Coordenadas donde se va a dibujar la textura del juego + color_t borderColor; // Color del borde añadido a la textura de juego para rellenar la pantalla public: // Constructor - Screen(SDL_Window *window, SDL_Renderer *renderer, int scr_w = 0, int scr_h = 0, int gc_w = 0, int gc_h = 0); + Screen(SDL_Window *window, SDL_Renderer *renderer, options_t *options); // Destructor ~Screen(); @@ -38,6 +36,9 @@ public: // Vuelca el contenido del renderizador en pantalla void blit(); + + // Establece el modo de video + void setVideoMode(int fullScreenMode); }; #endif