#include "room.h" #include #include #include // Constructor Room::Room(std::string file, SDL_Renderer *renderer, Screen *screen, Asset *asset, options_t *options, ItemTracker *itemTracker, int *items, Debug *debug) { // Copia los punteros a objetos this->renderer = renderer; this->asset = asset; this->screen = screen; this->itemTracker = itemTracker; this->itemsPicked = items; this->debug = debug; this->options = options; // Inicializa variables tileSize = 8; mapWidth = 32; mapHeight = 16; paused = false; itemColor1 = "magenta"; itemColor2 = "yellow"; autoSurfaceDirection = 1; counter = 0; // Crea los objetos loadMapFile(file); texture = new Texture(renderer, asset->get(tileset)); tilesetWidth = texture->getWidth() / tileSize; itemSound = JA_LoadSound(asset->get("item.wav").c_str()); loadMapTileFile(asset->get(tileMapFile)); // Calcula las superficies setBottomSurfaces(); setTopSurfaces(); setLeftSurfaces(); setRightSurfaces(); setLeftSlopes(); setRightSlopes(); setAutoSurfaces(); // Busca los tiles animados setAnimatedTiles(); // 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 == nullptr) { printf("Error: mapTexture could not be created!\nSDL Error: %s\n", SDL_GetError()); } SDL_SetTextureBlendMode(mapTexture, SDL_BLENDMODE_BLEND); // Pinta el mapa de la habitación en la textura fillMapTexture(); // Establece el color del borde screen->setBorderColor(stringToColor(options->palette, borderColor)); } // 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; } for (auto a : aTile) { delete a.sprite; } } // Carga las variables desde un fichero de mapa bool Room::loadMapFile(std::string file_path) { const 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\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; enemy.flip = false; 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()); } } while (line != "[/enemy]"); // Añade el enemigo al vector de enemigos enemies.push_back(new Enemy(enemy)); } // 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; item.color1 = stringToColor(options->palette, itemColor1); item.color2 = stringToColor(options->palette, itemColor2); 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()); } } 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()); } } } // Cierra el fichero printf("Closing file %s\n\n", filename.c_str()); file.close(); } // El fichero no se puede abrir else { printf("Warning: Unable to open %s file\n", filename.c_str()); return false; } return true; } // Carga las variables y texturas desde un fichero de mapa de tiles bool Room::loadMapTileFile(std::string file_path) { const 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)) { // Lee el fichero linea a linea if (line.find("data encoding") != std::string::npos) { // Lee la primera linea std::getline(file, line); while (line != "") { // Procesa lineas mientras haya std::stringstream ss(line); std::string tmp; while (getline(ss, tmp, ',')) { tilemap.push_back(std::stoi(tmp) - 1); } // Lee la siguiente linea std::getline(file, line); } } } // Cierra el fichero printf("Closing file %s\n\n", filename.c_str()); file.close(); } else { // El fichero no se puede abrir printf("Warning: Unable to open %s file\n", filename.c_str()); return false; } return true; } // 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 == "tilemap") { tileMapFile = value; } else if (var == "name") { name = value; } else if (var == "bgColor") { bgColor = value; } else if (var == "border") { borderColor = value; } else if (var == "itemColor1") { itemColor1 = value; } else if (var == "itemColor2") { itemColor2 = value; } else if (var == "tileset") { tileset = value; if (options->palette == p_zxspectrum) { tileset = "standard.png"; } else if (options->palette == p_zxarne) { tileset = "standard_zxarne.png"; } } 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 == "autoSurface") { if (value == "right") { autoSurfaceDirection = 1; } else { autoSurfaceDirection = -1; } } 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 == "flip") { enemy->flip = stringToBool(value); } else if (var == "color") { enemy->color = stringToColor(options->palette, 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 stringToColor(options->palette, bgColor); } // Devuelve el color del borde color_t Room::getBorderColor() { return stringToColor(options->palette, borderColor); } // Crea la textura con el mapeado de la habitación void Room::fillMapTexture() { SDL_SetRenderTarget(renderer, mapTexture); SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x00); SDL_RenderClear(renderer); // Los tilesets son de 20x20 tiles. El primer tile es el 0. Cuentan hacia la derecha y hacia abajo SDL_Rect clip = {0, 0, tileSize, tileSize}; for (int y = 0; y < mapHeight; ++y) for (int x = 0; x < mapWidth; ++x) { // Tiled pone los tiles vacios del mapa como cero y empieza a contar de 1 a n. // Al cargar el mapa en memoria, se resta uno, por tanto los tiles vacios son -1 // Tampoco hay que dibujar los tiles animados que estan en la fila 19 (indices) const int index = (y * mapWidth) + x; const bool a = (tilemap[index] >= 18 * tilesetWidth) && (tilemap[index] < 19 * tilesetWidth); const bool b = tilemap[index] > -1; if (b && !a) { clip.x = (tilemap[index] % tilesetWidth) * tileSize; clip.y = (tilemap[index] / tilesetWidth) * tileSize; texture->render(renderer, x * tileSize, y * tileSize, &clip); // **** if (debug->getEnabled()) { if (clip.x != -tileSize) { clip.x = x * tileSize; clip.y = y * tileSize; SDL_SetRenderDrawColor(renderer, 64, 64, 64, 224); SDL_RenderFillRect(renderer, &clip); } } // **** } } // **** if (debug->getEnabled()) { // BottomSurfaces if (true) { for (auto l : bottomSurfaces) { SDL_SetRenderDrawColor(renderer, (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF); SDL_SetRenderDrawColor(renderer, 255, 0, 0, 0xFF); SDL_RenderDrawLine(renderer, l.x1, l.y, l.x2, l.y); } } // TopSurfaces if (true) { for (auto l : topSurfaces) { SDL_SetRenderDrawColor(renderer, (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF); SDL_SetRenderDrawColor(renderer, 0, 255, 0, 0xFF); SDL_RenderDrawLine(renderer, l.x1, l.y, l.x2, l.y); } } // LeftSurfaces if (true) { for (auto l : leftSurfaces) { SDL_SetRenderDrawColor(renderer, (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF); SDL_SetRenderDrawColor(renderer, 0, 0, 255, 0xFF); SDL_RenderDrawLine(renderer, l.x, l.y1, l.x, l.y2); } } // RightSurfaces if (true) { for (auto l : rightSurfaces) { SDL_SetRenderDrawColor(renderer, (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF); SDL_SetRenderDrawColor(renderer, 255, 255, 0, 0xFF); SDL_RenderDrawLine(renderer, l.x, l.y1, l.x, l.y2); } } // LeftSlopes if (true) { for (auto l : leftSlopes) { SDL_SetRenderDrawColor(renderer, (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF); SDL_SetRenderDrawColor(renderer, 0, 255, 255, 0xFF); SDL_RenderDrawLine(renderer, l.x1, l.y1, l.x2, l.y2); } } // RightSlopes if (true) { for (auto l : rightSlopes) { SDL_SetRenderDrawColor(renderer, (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF); SDL_SetRenderDrawColor(renderer, 255, 0, 255, 0xFF); SDL_RenderDrawLine(renderer, l.x1, l.y1, l.x2, l.y2); } } // AutoSurfaces if (true) { for (auto l : autoSurfaces) { SDL_SetRenderDrawColor(renderer, (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF); SDL_RenderDrawLine(renderer, l.x1, l.y, l.x2, l.y); } } } // **** SDL_SetRenderTarget(renderer, nullptr); } // Dibuja el mapa en pantalla void Room::renderMap() { // Dibuja la textura con el mapa en pantalla SDL_RenderCopy(renderer, mapTexture, nullptr, nullptr); // Dibuja los tiles animados if (!debug->getEnabled()) { renderAnimatedTiles(); } } // 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() { if (paused) { // Si está en modo pausa no se actualiza nada return; } // Actualiza el contador counter++; // Actualiza los tiles animados updateAnimatedTiles(); for (auto enemy : enemies) { // Actualiza los enemigos enemy->update(); } for (auto item : items) { // Actualiza los 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 tile_e Room::getTile(SDL_Point point) { const int pos = ((point.y / tileSize) * mapWidth) + (point.x / tileSize); return getTile(pos); } // Devuelve el tipo de tile que hay en ese indice tile_e Room::getTile(int index) { const int maxTile = mapWidth * mapHeight; if (index < maxTile) { // Las filas 0-8 son de tiles t_wall if ((tilemap[index] >= 0) && (tilemap[index] < 9 * tilesetWidth)) { return t_wall; } // Las filas 9-17 son de tiles t_passable else if ((tilemap[index] >= 9 * tilesetWidth) && (tilemap[index] < 18 * tilesetWidth)) { return t_passable; } // Las filas 18-20 es de tiles t_animated else if ((tilemap[index] >= 18 * tilesetWidth) && (tilemap[index] < 21 * tilesetWidth)) { return t_animated; } // La fila 21 es de tiles t_slope_r else if ((tilemap[index] >= 21 * tilesetWidth) && (tilemap[index] < 22 * tilesetWidth)) { return t_slope_r; } // La fila 22 es de tiles t_slope_l else if ((tilemap[index] >= 22 * tilesetWidth) && (tilemap[index] < 23 * tilesetWidth)) { return t_slope_l; } // La fila 23 es de tiles t_kill else if ((tilemap[index] >= 23 * tilesetWidth) && (tilemap[index] < 24 * tilesetWidth)) { return t_kill; } } return t_empty; } // 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) { for (int i = 0; i < (int)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; return true; } } return false; } // Recarga la textura void Room::reLoadTexture() { if (options->palette == p_zxspectrum) { texture->loadFromFile(asset->get("standard.png"), renderer); } else if (options->palette == p_zxarne) { texture->loadFromFile(asset->get("standard_zxarne.png"), renderer); } // texture->reLoad(); fillMapTexture(); for (auto enemy : enemies) { enemy->reLoadTexture(); } for (auto item : items) { item->reLoadTexture(); } } // Recarga la paleta void Room::reLoadPalette() { // Cambia el color de los items for (auto item:items) { item->setColors(stringToColor(options->palette, itemColor1), stringToColor(options->palette, itemColor2)); } // Establece el color del borde screen->setBorderColor(stringToColor(options->palette, borderColor)); } // Obten el tamaño del tile int Room::getTileSize() { return tileSize; } // Obten la coordenada de la cuesta a partir de un punto perteneciente a ese tile int Room::getSlopeHeight(SDL_Point p, tile_e slope) { // Calcula la base del tile int base = ((p.y / tileSize) * tileSize) + tileSize; debug->add("BASE = " + std::to_string(base)); // Calcula cuanto se ha entrado en el tile horizontalmente const int pos = (p.x % tileSize); // Esto da un valor entre 0 y 7 debug->add("POS = " + std::to_string(pos)); // Se resta a la base la cantidad de pixeles pos en funcion de la rampa if (slope == t_slope_r) { base -= pos + 1; debug->add("BASE_R = " + std::to_string(base)); } else { base -= (tileSize - pos); debug->add("BASE_L = " + std::to_string(base)); } return base; } // Calcula las superficies inferiores void Room::setBottomSurfaces() { std::vector tile; // Busca todos los tiles de tipo muro que no tengan debajo otro muro // Hay que recorrer la habitación por filas (excepto los de la última fila) for (int i = 0; i < (int)tilemap.size() - mapWidth; ++i) { if (getTile(i) == t_wall && getTile(i + mapWidth) != t_wall) { tile.push_back(i); // Si llega al final de la fila, introduce un separador if (i % mapWidth == mapWidth - 1) { tile.push_back(-1); } } } // Recorre el vector de tiles buscando tiles consecutivos para localizar las superficies int i = 0; int lastOne = 0; while (i < (int)tile.size()) { h_line_t line; line.x1 = (tile[i] % mapWidth) * tileSize; line.y = ((tile[i] / mapWidth) * tileSize) + tileSize - 1; lastOne = i; i++; while (tile[i] == tile[i - 1] + 1) { lastOne = i; i++; } line.x2 = ((tile[lastOne] % mapWidth) * tileSize) + tileSize - 1; bottomSurfaces.push_back(line); if (tile[i] == -1) { // Si el siguiente elemento es un separador, hay que saltarlo i++; } } } // Calcula las superficies superiores void Room::setTopSurfaces() { std::vector tile; // Busca todos los tiles de tipo muro o pasable que no tengan encima un muro // Hay que recorrer la habitación por filas (excepto los de la primera fila) for (int i = mapWidth; i < (int)tilemap.size(); ++i) { if ((getTile(i) == t_wall || getTile(i) == t_passable) && getTile(i - mapWidth) != t_wall) { tile.push_back(i); // Si llega al final de la fila, introduce un separador if (i % mapWidth == mapWidth - 1) { tile.push_back(-1); } } } // Recorre el vector de tiles buscando tiles consecutivos para localizar las superficies int i = 0; int lastOne = 0; while (i < (int)tile.size()) { h_line_t line; line.x1 = (tile[i] % mapWidth) * tileSize; line.y = (tile[i] / mapWidth) * tileSize; lastOne = i; i++; while (tile[i] == tile[i - 1] + 1) { lastOne = i; i++; } line.x2 = ((tile[lastOne] % mapWidth) * tileSize) + tileSize - 1; topSurfaces.push_back(line); if (tile[i] == -1) { // Si el siguiente elemento es un separador, hay que saltarlo i++; } } } // Calcula las superficies laterales izquierdas void Room::setLeftSurfaces() { std::vector tile; // Busca todos los tiles de tipo muro que no tienen a su izquierda un tile de tipo muro // Hay que recorrer la habitación por columnas (excepto los de la primera columna) for (int i = 1; i < mapWidth; ++i) { for (int j = 0; j < mapHeight; ++j) { const int pos = (j * mapWidth + i); if (getTile(pos) == t_wall && getTile(pos - 1) != t_wall) { tile.push_back(pos); } } } // Recorre el vector de tiles buscando tiles consecutivos // (Los tiles de la misma columna, la diferencia entre ellos es de mapWidth) // para localizar las superficies int i = 0; while (i < (int)tile.size()) { v_line_t line; line.x = (tile[i] % mapWidth) * tileSize; line.y1 = ((tile[i] / mapWidth) * tileSize); while (tile[i] + mapWidth == tile[i + 1]) { i++; } line.y2 = ((tile[i] / mapWidth) * tileSize) + tileSize - 1; leftSurfaces.push_back(line); i++; } } // Calcula las superficies laterales derechas void Room::setRightSurfaces() { std::vector tile; // Busca todos los tiles de tipo muro que no tienen a su derecha un tile de tipo muro // Hay que recorrer la habitación por columnas (excepto los de la última columna) for (int i = 0; i < mapWidth - 1; ++i) { for (int j = 0; j < mapHeight; ++j) { const int pos = (j * mapWidth + i); if (getTile(pos) == t_wall && getTile(pos + 1) != t_wall) { tile.push_back(pos); } } } // Recorre el vector de tiles buscando tiles consecutivos // (Los tiles de la misma columna, la diferencia entre ellos es de mapWidth) // para localizar las superficies int i = 0; while (i < (int)tile.size()) { v_line_t line; line.x = ((tile[i] % mapWidth) * tileSize) + tileSize - 1; line.y1 = ((tile[i] / mapWidth) * tileSize); while (tile[i] + mapWidth == tile[i + 1]) { i++; } line.y2 = ((tile[i] / mapWidth) * tileSize) + tileSize - 1; rightSurfaces.push_back(line); i++; } } // Encuentra todas las rampas que suben hacia la izquierda void Room::setLeftSlopes() { // Recorre la habitación entera por filas buscando tiles de tipo t_slope_l std::vector found; for (int i = 0; i < (int)tilemap.size(); ++i) { if (getTile(i) == t_slope_l) { found.push_back(i); } } // El primer elemento es el inicio de una rampa. Se añade ese elemento y se buscan los siguientes, // que seran i + mapWidth + 1. Conforme se añaden se eliminan y se vuelve a escudriñar el vector de // tiles encontrados hasta que esté vacío while (found.size() > 0) { d_line_t line; line.x1 = (found[0] % mapWidth) * tileSize; line.y1 = (found[0] / mapWidth) * tileSize; int lookingFor = found[0] + mapWidth + 1; int lastOneFound = found[0]; found.erase(found.begin()); for (int i = 0; i < (int)found.size(); ++i) { if (found[i] == lookingFor) { lastOneFound = lookingFor; lookingFor += mapWidth + 1; found.erase(found.begin() + i); i--; } } line.x2 = ((lastOneFound % mapWidth) * tileSize) + tileSize - 1; line.y2 = ((lastOneFound / mapWidth) * tileSize) + tileSize - 1; leftSlopes.push_back(line); } } // Encuentra todas las rampas que suben hacia la derecha void Room::setRightSlopes() { // Recorre la habitación entera por filas buscando tiles de tipo t_slope_r std::vector found; for (int i = 0; i < (int)tilemap.size(); ++i) { if (getTile(i) == t_slope_r) { found.push_back(i); } } // El primer elemento es el inicio de una rampa. Se añade ese elemento y se buscan los siguientes, // que seran i + mapWidth - 1. Conforme se añaden se eliminan y se vuelve a escudriñar el vector de // tiles encontrados hasta que esté vacío while (found.size() > 0) { d_line_t line; line.x1 = ((found[0] % mapWidth) * tileSize) + tileSize - 1; line.y1 = (found[0] / mapWidth) * tileSize; int lookingFor = found[0] + mapWidth - 1; int lastOneFound = found[0]; found.erase(found.begin()); for (int i = 0; i < (int)found.size(); ++i) { if (found[i] == lookingFor) { lastOneFound = lookingFor; lookingFor += mapWidth - 1; found.erase(found.begin() + i); i--; } } line.x2 = (lastOneFound % mapWidth) * tileSize; line.y2 = ((lastOneFound / mapWidth) * tileSize) + tileSize - 1; rightSlopes.push_back(line); } } // Calcula las superficies automaticas void Room::setAutoSurfaces() { std::vector tile; // Busca todos los tiles de tipo animado // Hay que recorrer la habitación por filas (excepto los de la primera fila) for (int i = mapWidth; i < (int)tilemap.size(); ++i) { if (getTile(i) == t_animated) { tile.push_back(i); // Si llega al final de la fila, introduce un separador if (i % mapWidth == mapWidth - 1) { tile.push_back(-1); } } } // Recorre el vector de tiles buscando tiles consecutivos para localizar las superficies int i = 0; int lastOne = 0; while (i < (int)tile.size()) { h_line_t line; line.x1 = (tile[i] % mapWidth) * tileSize; line.y = (tile[i] / mapWidth) * tileSize; lastOne = i; i++; while (tile[i] == tile[i - 1] + 1) { lastOne = i; i++; } line.x2 = ((tile[lastOne] % mapWidth) * tileSize) + tileSize - 1; autoSurfaces.push_back(line); if (tile[i] == -1) { // Si el siguiente elemento es un separador, hay que saltarlo i++; } } } // Localiza todos los tiles animados de la habitación void Room::setAnimatedTiles() { // Recorre la habitación entera por filas buscando tiles de tipo t_animated for (int i = 0; i < (int)tilemap.size(); ++i) { if (getTile(i) == t_animated) { // la i me da la ubicación const int x = (i % mapWidth) * tileSize; const int y = (i / mapWidth) * tileSize; // tilemap[i] me da el tile a poner const int xc = (tilemap[i] % tilesetWidth) * tileSize; const int yc = (tilemap[i] / tilesetWidth) * tileSize; aTile_t at; at.sprite = new Sprite(x, y, 8, 8, texture, renderer); at.sprite->setSpriteClip(xc, yc, 8, 8); at.xcOrig = xc; aTile.push_back(at); } } } // Actualiza los tiles animados void Room::updateAnimatedTiles() { const int numFrames = 4; int offset = 0; if (autoSurfaceDirection == -1) { offset = ((counter / 3) % numFrames * tileSize); } else { offset = ((numFrames - 1 - ((counter / 3) % numFrames)) * tileSize); } for (auto &a : aTile) { SDL_Rect rect = a.sprite->getSpriteClip(); rect.x = a.xcOrig + offset; a.sprite->setSpriteClip(rect); } } // Pinta los tiles animados en pantalla void Room::renderAnimatedTiles() { for (auto a : aTile) { a.sprite->render(); } } // Comprueba las colisiones int Room::checkRightSurfaces(SDL_Rect *rect) { for (auto s : rightSurfaces) { if (checkCollision(s, *rect)) { return s.x; } } return -1; } // Comprueba las colisiones int Room::checkLeftSurfaces(SDL_Rect *rect) { for (auto s : leftSurfaces) { if (checkCollision(s, *rect)) { return s.x; } } return -1; } // Comprueba las colisiones int Room::checkTopSurfaces(SDL_Rect *rect) { for (auto s : topSurfaces) { if (checkCollision(s, *rect)) { return s.y; } } return -1; } // Comprueba las colisiones int Room::checkBottomSurfaces(SDL_Rect *rect) { for (auto s : bottomSurfaces) { if (checkCollision(s, *rect)) { return s.y; } } return -1; } // Comprueba las colisiones int Room::checkAutoSurfaces(SDL_Rect *rect) { for (auto s : autoSurfaces) { if (checkCollision(s, *rect)) { return s.y; } } return -1; } // Comprueba las colisiones bool Room::checkTopSurfaces(SDL_Point *p) { for (auto s : topSurfaces) { if (checkCollision(s, *p)) { return true; } } return false; } // Comprueba las colisiones bool Room::checkAutoSurfaces(SDL_Point *p) { for (auto s : autoSurfaces) { if (checkCollision(s, *p)) { return true; } } return false; } // Comprueba las colisiones int Room::checkLeftSlopes(v_line_t *line) { for (auto s : leftSlopes) { const SDL_Point p = checkCollision(s, *line); if (p.x != -1) { return p.y; } } return -1; } // Comprueba las colisiones bool Room::checkLeftSlopes(SDL_Point *p) { for (auto s : leftSlopes) { if (checkCollision(*p, s)) { return true; } } return false; } // Comprueba las colisiones int Room::checkRightSlopes(v_line_t *line) { for (auto s : rightSlopes) { const SDL_Point p = checkCollision(s, *line); if (p.x != -1) { return p.y; } } return -1; } // Comprueba las colisiones bool Room::checkRightSlopes(SDL_Point *p) { for (auto s : rightSlopes) { if (checkCollision(*p, s)) { return true; } } return false; } // Pone el mapa en modo pausa void Room::pause() { paused = true; } // Quita el modo pausa del mapa void Room::resume() { paused = false; } // Obten la direccion de las superficies automaticas int Room::getAutoSurfaceDirection() { return autoSurfaceDirection; }