#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 actor : actors) { delete actor; } actors.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 [actor] se realiza el proceso de carga de los actores else if (line == "[actors]") { do { std::getline(file, line); if (line == "[moving platform]") { actor_t actor; actor.asset = asset; actor.renderer = renderer; actor.name = a_moving_platform; SDL_Point p1, p2; do { std::getline(file, line); // Encuentra la posición del caracter '=' int pos = line.find("="); // Procesa las dos subcadenas if (!setActor(&actor, &p1, &p2, 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 != "[/moving platform]"); printf("** actor moving platform loaded\n"); actors.push_back(new ActorMovingPlatform(actor, p1, p2)); } if (line == "[diamond]") { actor_t actor; actor.asset = asset; actor.renderer = renderer; actor.name = a_diamond; actor.vx = 0.0f; actor.vy = 0.0f; SDL_Point p1, p2; do { std::getline(file, line); // Encuentra la posición del caracter '=' int pos = line.find("="); // Procesa las dos subcadenas if (!setActor(&actor, &p1, &p2, 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 != "[/diamond]"); printf("** actor diamond loaded\n"); actors.push_back(new ActorDiamond(actor)); } } while (line != "[/actors]"); /*actor_t actor; actor.asset = asset; actor.renderer = renderer; do { std::getline(file, line); // Encuentra la posición del caracter '=' int pos = line.find("="); // Procesa las dos subcadenas if (!setActor(&actor, 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 != "[/actor]"); // Añade el enemigo al vector de enemigos actors.push_back(new ActorMovingPlatform(actor));*/ } // 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::setActor(actor_t *actor, SDL_Point *p1, SDL_Point *p2, std::string var, std::string value) { // Indicador de éxito en la asignación bool success = true; if (var == "tileset") { actor->tileset = value; } else if (var == "animation") { actor->animation = value; } else if (var == "width") { actor->w = std::stoi(value); } else if (var == "height") { actor->h = std::stoi(value); } else if (var == "x") { actor->x = std::stof(value) * tile_size; } else if (var == "y") { actor->y = std::stof(value) * tile_size; } else if (var == "vx") { actor->vx = std::stof(value); } else if (var == "vy") { actor->vy = std::stof(value); } else if (var == "x1") { p1->x = std::stoi(value) * tile_size; } else if (var == "x2") { p2->x = std::stoi(value) * tile_size; } else if (var == "y1") { p1->y = std::stoi(value) * tile_size; } else if (var == "y2") { p2->y = std::stoi(value) * tile_size; } else if ((var == "[/moving platform]") || (var == "[/diamond]")) { } 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 actor : actors) { actor->render(); } } // Actualiza todas las variables void Map::update() { for (auto actor : actors) { actor->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 ""; } // Indica si hay colision con un actor a partir de un rectangulo int Map::actorCollision(SDL_Rect &rect) { int index = 0; for (auto actor : actors) { if (checkCollision(rect, actor->getCollider())) { return index; } index++; } return -1; } // Indica si hay colision con un actor a partir de un rectangulo int Map::actorCollision(SDL_Point &p) { int index = 0; for (auto actor : actors) { if (checkCollision(p, actor->getCollider())) { return index; } index++; } return -1; } // Devuelve el nombre del actor a pàrtir de un índice int Map::getActorName(int index) { if (index != -1) { return actors[index]->getName(); } return -1; } // Devuelve el rectangulo de colisión SDL_Rect Map::getActorCollider(int index) { SDL_Rect rect = {0, 0, 0, 0}; if (index != -1) { rect = actors[index]->getCollider(); } return rect; } // Devuelve el desplazamiento relativo del actor int Map::getActorIncX(int index) { int shift = 0; if (index != -1) { shift = actors[index]->getIncX(); } return shift; } // Elimina un actor bool Map::deleteActor(int index) { bool success = false; if (actors[index] != nullptr) { delete actors[index]; success = true; } actors.erase(actors.begin() + index); return success; }