#include "room.h" #include #include #include // Constructor Room::Room(std::string file_path, SDL_Renderer *renderer, Asset *asset, ItemTracker *itemTracker, int *items) { // Copia los punteros a objetos this->asset = asset; this->renderer = renderer; this->itemTracker = itemTracker; this->itemsPicked = items; // Crea los objetos load(file_path); texture = new LTexture(renderer, asset->get(tileset)); itemSound = JA_LoadSound(asset->get("item.wav").c_str()); // Crea la textura para el mapa de tiles de la habitación mapTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT); if (mapTexture == NULL) printf("Error: mapTexture could not be created!\nSDL Error: %s\n", SDL_GetError()); // Pinta el mapa de la habitación en la textura fillMapTexture(); } // Destructor Room::~Room() { // Reclama la memoria utilizada por los objetos delete texture; JA_DeleteSound(itemSound); SDL_DestroyTexture(mapTexture); for (auto enemy : enemies) { delete enemy; } for (auto item : items) { delete item; } } // Carga las variables desde un fichero bool Room::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 [enemy] se realiza el proceso de carga de un enemigo 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 enemies.push_back(new Enemy(enemy)); } // Si la linea contiene el texto [tilemap] se realiza el proceso de carga del fichero tmx else if (line == "[tilemap]") { // printf("Loading tilemap...\n"); do { std::getline(file, line); if (line.find(".tmx") != std::string::npos) { // printf("Reading file %s\n", asset->get(line).c_str()); 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); // printf("parsing: %s\n", line.c_str()); pos = line.find("data encoding"); // printf("pos: %i\n", pos); } 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 != "") { // printf("data: %s\n", line.c_str()); std::stringstream ss(line); std::string tmp; while (getline(ss, tmp, ',')) { // printf("tile: %s\n", tmp.c_str()); tilemap.push_back(std::stoi(tmp)); } } } while (line != ""); } } } } } while (line != "[/tilemap]"); } // Si la linea contiene el texto [item] se realiza el proceso de carga de un item else if (line == "[item]") { item_t item; item.asset = asset; item.renderer = renderer; item.counter = 0; do { std::getline(file, line); // Encuentra la posición del caracter '=' int pos = line.find("="); // Procesa las dos subcadenas if (!setItem(&item, 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 != "[/item]"); // Añade el item al vector de items const SDL_Point itemPos = {item.x, item.y}; if (!itemTracker->hasBeenPicked(name, itemPos)) { items.push_back(new Item(item)); } } // 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 Room::setVars(std::string var, std::string value) { // Indicador de éxito en la asignación bool success = true; if (var == "name") { name = value; } else if (var == "bgColor") { bgColor = stringToColor(value); } else if (var == "tileset") { tileset = value; } else if (var == "roomUp") { roomUp = value; } else if (var == "roomDown") { roomDown = value; } else if (var == "roomLeft") { roomLeft = value; } else if (var == "roomRight") { roomRight = 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; } // Asigna variables a una estructura enemy_t bool Room::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) * BLOCK; } else if (var == "y") { enemy->y = std::stof(value) * BLOCK; } else if (var == "vx") { enemy->vx = std::stof(value); } else if (var == "vy") { enemy->vy = std::stof(value); } else if (var == "x1") { enemy->x1 = std::stoi(value) * BLOCK; } else if (var == "x2") { enemy->x2 = std::stoi(value) * BLOCK; } else if (var == "y1") { enemy->y1 = std::stoi(value) * BLOCK; } else if (var == "y2") { enemy->y2 = std::stoi(value) * BLOCK; } else if (var == "color") { enemy->color = stringToColor(value); } else if (var == "[/enemy]") { } else { success = false; } return success; } // Asigna variables a una estructura item_t bool Room::setItem(item_t *item, std::string var, std::string value) { // Indicador de éxito en la asignación bool success = true; if (var == "tileset") { item->tileset = value; } else if (var == "counter") { item->counter = std::stoi(value); } else if (var == "x") { item->x = std::stof(value) * BLOCK; } else if (var == "y") { item->y = std::stof(value) * BLOCK; } else if (var == "tile") { item->tile = std::stof(value); } else if (var == "[/item]") { } else { success = false; } return success; } // Devuelve el nombre de la habitación std::string Room::getName() { return name; } // Devuelve el color de la habitación color_t Room::getBGColor() { return bgColor; } // Crea la textura con el mapeado de la habitación void Room::fillMapTexture() { SDL_SetRenderTarget(renderer, mapTexture); SDL_SetTextureBlendMode(mapTexture, SDL_BLENDMODE_BLEND); SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00); SDL_RenderClear(renderer); // Los tilesets son de 20x20 tiles. El primer tile es el 1. Cuentan hacia la derecha y hacia abajo SDL_Rect clip = {0, 0, 8, 8}; for (int y = 0; y < 16; y++) for (int x = 0; x < 32; x++) { clip.x = ((tilemap[(y * 32) + x] - 1) % 20) * 8; clip.y = ((tilemap[(y * 32) + x] - 1) / 20) * 8; texture->render(renderer, x * 8, y * 8, &clip); } SDL_SetRenderTarget(renderer, nullptr); } // Dibuja el mapa en pantalla void Room::renderMap() { SDL_Rect rect = {0, 0, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT}; // Dibuja la textura con el mapa en pantalla SDL_RenderCopy(renderer, mapTexture, &rect, NULL); } // Dibuja los enemigos en pantalla void Room::renderEnemies() { for (auto enemy : enemies) { enemy->render(); } } // Dibuja los objetos en pantalla void Room::renderItems() { for (auto item : items) { item->render(); } } // Actualiza las variables y objetos de la habitación void Room::update() { for (auto enemy : enemies) { enemy->update(); } for (auto item : items) { item->update(); } } // Devuelve la cadena del fichero de la habitación contigua segun el borde std::string Room::getRoom(int border) { switch (border) { case BORDER_TOP: return roomUp; break; case BORDER_BOTTOM: return roomDown; break; case BORDER_RIGHT: return roomRight; break; case BORDER_LEFT: return roomLeft; break; default: break; } return ""; } // Devuelve el tipo de tile que hay en ese pixel int Room::getTile(SDL_Point point) { int pos = ((point.y / 8) * 32) + (point.x / 8); int tile = TILE_EMPTY; if (pos < 512) { // Los tiles entre el 1 y el 80 son solidos if ((tilemap[pos] > 0) && (tilemap[pos] < 201)) { return TILE_SOLID; } // Los tiles mayores de 80 son atravesables if ((tilemap[pos] > 200) && (tilemap[pos] < 381)) { return TILE_TRAVESSABLE; } // Los tiles mayores de 80 son atravesables if ((tilemap[pos] > 380) && (tilemap[pos] < 400)) { return TILE_KILL; } } return tile; } // Indica si hay colision con un enemigo a partir de un rectangulo bool Room::enemyCollision(SDL_Rect &rect) { bool collision = false; for (auto enemy : enemies) { collision |= checkCollision(rect, enemy->getCollider()); } return collision; } // Indica si hay colision con un objeto a partir de un rectangulo bool Room::itemCollision(SDL_Rect &rect) { bool collision = false; for (int i = 0; i < items.size(); i++) { if (checkCollision(rect, items[i]->getCollider())) { itemTracker->addItem(name, items[i]->getPos()); delete items[i]; items.erase(items.begin() + i); JA_PlaySound(itemSound); *itemsPicked = *itemsPicked + 1; collision = true; } } return collision; } // Recarga la textura void Room::reLoadTexture() { texture->reLoad(); fillMapTexture(); for (auto enemy : enemies) { enemy->reLoadTexture(); } for (auto item : items) { item->reLoadTexture(); } } // Obten el tamaño del tile int Room::getTileSize() { return 8; }