#include "map.h" // Constructor Map::Map(std::string file, SDL_Renderer *renderer, Asset *asset) { // Inicializa variables tile_size = 8; map_width = 40; map_height = 26; tileset_width = 32; // Copia los punteros a objetos this->asset = asset; this->renderer = renderer; // Crea los objetos texture_tile = new LTexture(); load(file); loadTextureFromFile(texture_tile, asset->get(tileset_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; SDL_DestroyTexture(map_texture); for (auto enemy : enemy_list) { delete enemy; } enemy_list.clear(); } // 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]"); } // Si la linea contiene el texto [enemy] se realiza el proceso de carga de un enemigo else if (line == "[enemy]") { enemy_t enemy; enemy.asset = asset; enemy.renderer = renderer; do { std::getline(file, line); // Encuentra la posición del caracter '=' int pos = line.find("="); // Procesa las dos subcadenas if (!setEnemy(&enemy, line.substr(0, pos), line.substr(pos + 1, line.length()))) { printf("Warning: file %s\n, unknown parameter \"%s\"\n", filename.c_str(), line.substr(0, pos).c_str()); success = false; } } while (line != "[/enemy]"); // Añade el enemigo al vector de enemigos enemy_list.push_back(new Enemy(enemy)); } // 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 == "tileset_img") { tileset_img = value; } else if (var == "bgColor1") { // Se introducen los valores separados por comas en un vector std::stringstream ss(value); std::string tmp; getline(ss, tmp, ','); bgColor1.r = std::stoi(tmp); getline(ss, tmp, ','); bgColor1.g = std::stoi(tmp); getline(ss, tmp, ','); bgColor1.b = std::stoi(tmp); } else if (var == "bgColor2") { // Se introducen los valores separados por comas en un vector std::stringstream ss(value); std::string tmp; getline(ss, tmp, ','); bgColor2.r = std::stoi(tmp); getline(ss, tmp, ','); bgColor2.g = std::stoi(tmp); getline(ss, tmp, ','); bgColor2.b = std::stoi(tmp); } 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 == "") { } else { success = false; } return success; } // Asigna variables a una estructura enemy_t bool Map::setEnemy(enemy_t *enemy, std::string var, std::string value) { // Indicador de éxito en la asignación bool success = true; if (var == "tileset") { enemy->tileset = value; } else if (var == "animation") { enemy->animation = value; } else if (var == "width") { enemy->w = std::stof(value); } else if (var == "height") { enemy->h = std::stof(value); } else if (var == "x") { enemy->x = std::stof(value) * tile_size; } else if (var == "y") { enemy->y = std::stof(value) * tile_size; } else if (var == "vx") { enemy->vx = std::stof(value); } else if (var == "vy") { enemy->vy = std::stof(value); } else if (var == "x1") { enemy->p1.x = std::stoi(value) * tile_size; } else if (var == "x2") { enemy->p2.x = std::stoi(value) * tile_size; } else if (var == "y1") { enemy->p1.y = std::stoi(value) * tile_size; } else if (var == "y2") { enemy->p2.y = std::stoi(value) * tile_size; } else if (var == "[/enemy]") { } 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, 0xFF); SDL_RenderClear(renderer); // Dibuja el degradado de fondo const int num_lines = 208; for (int i = 0; i < num_lines; i++) { float step = ((float)i / (float)num_lines); int r = bgColor1.r + ((bgColor2.r - bgColor1.r) * step); int g = bgColor1.g + ((bgColor2.g - bgColor1.g) * step); int b = bgColor1.b + ((bgColor2.b - bgColor1.b) * step); SDL_SetRenderDrawColor(renderer, r, g, b, 0xFF); SDL_RenderDrawLine(renderer, 0, i, 319, i); } // Dibuja el mapeado de tiles SDL_Rect clip = {0, 0, tile_size, tile_size}; for (int y = 0; y < map_height; y++) for (int x = 0; x < map_width; x++) { clip.x = ((tilemap[(y * map_width) + x] - 1) % tileset_width) * tile_size; clip.y = ((tilemap[(y * map_width) + x] - 1) / tileset_width) * tile_size; texture_tile->render(renderer, x * tile_size, y * tile_size, &clip); } // Dibuja el degradado del marcador int color = 105; for (int i = 208; i < 240; i++) { SDL_SetRenderDrawColor(renderer, 0x69, color, 0x69, 0xFF); SDL_RenderDrawLine(renderer, 0, i, 320, i); color--; } // Dibuja el marco del marcador // SDL_SetRenderDrawColor(renderer, 85, 50, 85, 0xFF); // SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xFF); // SDL_Rect rect = {0, 208, 320, 32}; // SDL_RenderDrawRect(renderer, &rect); // rect = {1, 209, 318, 30}; // SDL_RenderDrawRect(renderer, &rect); // Vuelve a colocar el renderizador SDL_SetRenderTarget(renderer, nullptr); } // Dibuja el mapa en pantalla void Map::render() { // Dibuja la textura con el mapa en pantalla SDL_Rect rect = {0, 0, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT}; SDL_RenderCopy(renderer, map_texture, &rect, NULL); for (auto enemy : enemy_list) { enemy->render(); } } // Actualiza todas las variables void Map::update() { for (auto enemy : enemy_list) { enemy->update(); } } // Devuelve el tipo de tile que hay en un punto e_tile_map Map::getTile(SDL_Point p) { // Normalizamos los puntos para que no busque fuera del mapa const int x = std::max(getPlayArea(b_left), (std::min(p.x, getPlayArea(b_right) - 1))); const int y = std::max(getPlayArea(b_top), (std::min(p.y, getPlayArea(b_bottom) - 1))); // Calcula el tile const int tile = tilemap[((y / tile_size) * map_width) + (x / tile_size)]; const int png_width = 32; // Las 8 primeras filas son tiles de fondo if (tile >= 0 && tile < 8 * png_width) { return nothing; } // De la fila 8 a la 15 hay tiles de muro else if (tile >= (8 * png_width) && tile < 16 * png_width) { return wall; } // A partir de la fila 16 son tiles atravesables else { return passable; } return nothing; } // Devuelve el valor de la variable int Map::getTileSize() { return tile_size; } // Devuelve el indice del tile correspondiente a un punto del mapa int Map::getTileIndex(SDL_Point p) { return tilemap[((p.y / tile_size) * map_width) + (p.x / tile_size)]; } // Devuelve el valor de los bordes de la zona de juego int Map::getPlayArea(e_border border) { switch (border) { case b_top: return 0; break; case b_left: return 0; break; case b_right: return tile_size * map_width; break; case b_bottom: return tile_size * map_height; break; default: break; } return -1; } // Devuelve el nombre del fichero de la habitación en funcion del borde std::string Map::getRoomFileName(e_border border) { switch (border) { case b_top: return room_up; break; case b_left: return room_left; break; case b_right: return room_right; break; case b_bottom: return room_down; break; default: break; } return ""; }