forked from jaildesigner-jailgames/jaildoctors_dilemma
1422 lines
40 KiB
C++
1422 lines
40 KiB
C++
#include "room.h"
|
|
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
|
|
#include <SDL2/SDL_error.h> // for SDL_GetError
|
|
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
|
|
#include <stdlib.h> // for rand
|
|
#include <exception> // for exception
|
|
#include <fstream> // for basic_ostream, operator<<, basic_ist...
|
|
#include <iostream> // for cout, cerr
|
|
#include <sstream> // for basic_stringstream
|
|
#include "debug.h" // for Debug
|
|
#include "defines.h" // for BLOCK, PLAY_AREA_HEIGHT, PLAY_AREA_W...
|
|
#include "item_tracker.h" // for ItemTracker
|
|
#include "jail_audio.h" // for JA_PlaySound
|
|
#include "options.h" // for Options, options, OptionsVideo, Opti...
|
|
#include "resource.h" // for Resource
|
|
#include "scoreboard.h" // for ScoreboardData
|
|
#include "screen.h" // for Screen
|
|
#include "sprite.h" // for Sprite
|
|
#include "texture.h" // for Texture
|
|
#include "utils.h" // for LineHorizontal, LineDiagonal, LineVe...
|
|
|
|
// Carga las variables y texturas desde un fichero de mapa de tiles
|
|
std::vector<int> loadRoomTileFile(const std::string &file_path, bool verbose)
|
|
{
|
|
std::vector<int> tileMapFile;
|
|
const std::string filename = file_path.substr(file_path.find_last_of("\\/") + 1);
|
|
std::ifstream file(file_path);
|
|
|
|
// El fichero se puede abrir
|
|
if (file.good())
|
|
{
|
|
std::string line;
|
|
// Procesa el fichero linea a linea
|
|
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 != "</data>")
|
|
{ // Procesa lineas mientras haya
|
|
std::stringstream ss(line);
|
|
std::string tmp;
|
|
while (getline(ss, tmp, ','))
|
|
{
|
|
tileMapFile.push_back(std::stoi(tmp) - 1);
|
|
}
|
|
|
|
// Lee la siguiente linea
|
|
std::getline(file, line);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Cierra el fichero
|
|
if (verbose)
|
|
{
|
|
std::cout << "TileMap loaded: " << filename.c_str() << std::endl;
|
|
}
|
|
file.close();
|
|
}
|
|
|
|
else
|
|
{ // El fichero no se puede abrir
|
|
if (verbose)
|
|
{
|
|
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << std::endl;
|
|
}
|
|
}
|
|
|
|
return tileMapFile;
|
|
}
|
|
|
|
// Carga las variables desde un fichero de mapa
|
|
RoomData loadRoomFile(const std::string &file_path, bool verbose)
|
|
{
|
|
RoomData room;
|
|
room.item_color1 = "yellow";
|
|
room.item_color2 = "magenta";
|
|
room.auto_surface_direction = 1;
|
|
|
|
const std::string fileName = file_path.substr(file_path.find_last_of("\\/") + 1);
|
|
room.number = fileName.substr(0, fileName.find_last_of("."));
|
|
|
|
std::ifstream file(file_path);
|
|
|
|
// El fichero se puede abrir
|
|
if (file.good())
|
|
{
|
|
std::string line;
|
|
// Procesa el fichero linea a linea
|
|
while (std::getline(file, line))
|
|
{
|
|
// Si la linea contiene el texto [enemy] se realiza el proceso de carga de un enemigo
|
|
if (line == "[enemy]")
|
|
{
|
|
EnemyData enemy;
|
|
enemy.flip = false;
|
|
enemy.mirror = false;
|
|
enemy.frame = -1;
|
|
|
|
do
|
|
{
|
|
std::getline(file, line);
|
|
|
|
// Encuentra la posición del caracter '='
|
|
int pos = line.find("=");
|
|
|
|
// Procesa las dos subcadenas
|
|
std::string key = line.substr(0, pos);
|
|
std::string value = line.substr(pos + 1, line.length());
|
|
if (!setEnemy(&enemy, key, value))
|
|
if (verbose)
|
|
{
|
|
std::cout << "Warning: file " << fileName.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
|
|
}
|
|
} while (line != "[/enemy]");
|
|
|
|
// Añade el enemigo al vector de enemigos
|
|
room.enemies.push_back(enemy);
|
|
}
|
|
|
|
// Si la linea contiene el texto [item] se realiza el proceso de carga de un item
|
|
else if (line == "[item]")
|
|
{
|
|
ItemData item;
|
|
item.counter = 0;
|
|
item.color1 = stringToColor(Palette::ZXSPECTRUM, "yellow");
|
|
item.color2 = stringToColor(Palette::ZXSPECTRUM, "magenta");
|
|
|
|
do
|
|
{
|
|
std::getline(file, line);
|
|
|
|
// Encuentra la posición del caracter '='
|
|
int pos = line.find("=");
|
|
|
|
// Procesa las dos subcadenas
|
|
std::string key = line.substr(0, pos);
|
|
std::string value = line.substr(pos + 1, line.length());
|
|
if (!setItem(&item, key, value))
|
|
{
|
|
if (verbose)
|
|
{
|
|
std::cout << "Warning: file " << fileName.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
|
|
}
|
|
}
|
|
|
|
} while (line != "[/item]");
|
|
|
|
room.items.push_back(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
|
|
std::string key = line.substr(0, pos);
|
|
std::string value = line.substr(pos + 1, line.length());
|
|
if (!setRoom(&room, key, value))
|
|
{
|
|
if (verbose)
|
|
{
|
|
std::cout << "Warning: file " << fileName.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Cierra el fichero
|
|
if (verbose)
|
|
{
|
|
std::cout << "Room loaded: " << fileName.c_str() << std::endl;
|
|
}
|
|
file.close();
|
|
}
|
|
// El fichero no se puede abrir
|
|
else
|
|
{
|
|
{
|
|
std::cout << "Warning: Unable to open " << fileName.c_str() << " file" << std::endl;
|
|
}
|
|
}
|
|
|
|
return room;
|
|
}
|
|
|
|
// Asigna variables a una estructura RoomData
|
|
bool setRoom(RoomData *room, const std::string &key, const std::string &value)
|
|
{
|
|
// Indicador de éxito en la asignación
|
|
bool success = true;
|
|
|
|
try
|
|
{
|
|
if (key == "tileMapFile")
|
|
{
|
|
room->tile_map_file = value;
|
|
}
|
|
else if (key == "name")
|
|
{
|
|
room->name = value;
|
|
}
|
|
else if (key == "bgColor")
|
|
{
|
|
room->bg_color = value;
|
|
}
|
|
else if (key == "border")
|
|
{
|
|
room->border_color = value;
|
|
}
|
|
else if (key == "itemColor1")
|
|
{
|
|
room->item_color1 = value;
|
|
}
|
|
else if (key == "itemColor2")
|
|
{
|
|
room->item_color2 = value;
|
|
}
|
|
else if (key == "tileSetFile")
|
|
{
|
|
room->tile_set_file = value;
|
|
}
|
|
else if (key == "roomUp")
|
|
{
|
|
room->room_top = value;
|
|
}
|
|
else if (key == "roomDown")
|
|
{
|
|
room->room_bottom = value;
|
|
}
|
|
else if (key == "roomLeft")
|
|
{
|
|
room->room_left = value;
|
|
}
|
|
else if (key == "roomRight")
|
|
{
|
|
room->room_right = value;
|
|
}
|
|
else if (key == "autoSurface")
|
|
{
|
|
room->auto_surface_direction = (value == "right") ? 1 : -1;
|
|
}
|
|
else if (key == "" || key.substr(0, 1) == "#")
|
|
{
|
|
// No se realiza ninguna acción para estas claves
|
|
}
|
|
else
|
|
{
|
|
success = false;
|
|
}
|
|
}
|
|
catch (const std::exception &e)
|
|
{
|
|
std::cerr << "Error al asignar la clave " << key << " con valor " << value << ": " << e.what() << std::endl;
|
|
success = false;
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
// Asigna variables a una estructura EnemyData
|
|
bool setEnemy(EnemyData *enemy, const std::string &key, const std::string &value)
|
|
{
|
|
// Indicador de éxito en la asignación
|
|
bool success = true;
|
|
|
|
try
|
|
{
|
|
if (key == "tileSetFile")
|
|
{
|
|
enemy->texture_path = value;
|
|
}
|
|
else if (key == "animation")
|
|
{
|
|
enemy->animation_path = value;
|
|
}
|
|
else if (key == "width")
|
|
{
|
|
enemy->w = std::stoi(value);
|
|
}
|
|
else if (key == "height")
|
|
{
|
|
enemy->h = std::stoi(value);
|
|
}
|
|
else if (key == "x")
|
|
{
|
|
enemy->x = std::stof(value) * BLOCK;
|
|
}
|
|
else if (key == "y")
|
|
{
|
|
enemy->y = std::stof(value) * BLOCK;
|
|
}
|
|
else if (key == "vx")
|
|
{
|
|
enemy->vx = std::stof(value);
|
|
}
|
|
else if (key == "vy")
|
|
{
|
|
enemy->vy = std::stof(value);
|
|
}
|
|
else if (key == "x1")
|
|
{
|
|
enemy->x1 = std::stoi(value) * BLOCK;
|
|
}
|
|
else if (key == "x2")
|
|
{
|
|
enemy->x2 = std::stoi(value) * BLOCK;
|
|
}
|
|
else if (key == "y1")
|
|
{
|
|
enemy->y1 = std::stoi(value) * BLOCK;
|
|
}
|
|
else if (key == "y2")
|
|
{
|
|
enemy->y2 = std::stoi(value) * BLOCK;
|
|
}
|
|
else if (key == "flip")
|
|
{
|
|
enemy->flip = stringToBool(value);
|
|
}
|
|
else if (key == "mirror")
|
|
{
|
|
enemy->mirror = stringToBool(value);
|
|
}
|
|
else if (key == "color")
|
|
{
|
|
enemy->color = value;
|
|
}
|
|
else if (key == "frame")
|
|
{
|
|
enemy->frame = std::stoi(value);
|
|
}
|
|
else if (key == "[/enemy]" || key == "tileSetFile" || key.substr(0, 1) == "#")
|
|
{
|
|
// No se realiza ninguna acción para estas claves
|
|
}
|
|
else
|
|
{
|
|
success = false;
|
|
}
|
|
}
|
|
catch (const std::exception &e)
|
|
{
|
|
std::cerr << "Error al asignar la clave " << key << " con valor " << value << ": " << e.what() << std::endl;
|
|
success = false;
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
// Asigna variables a una estructura ItemData
|
|
bool setItem(ItemData *item, const std::string &key, const std::string &value)
|
|
{
|
|
// Indicador de éxito en la asignación
|
|
bool success = true;
|
|
|
|
try
|
|
{
|
|
if (key == "tileSetFile")
|
|
{
|
|
item->tile_set_file = value;
|
|
}
|
|
else if (key == "counter")
|
|
{
|
|
item->counter = std::stoi(value);
|
|
}
|
|
else if (key == "x")
|
|
{
|
|
item->x = std::stof(value) * BLOCK;
|
|
}
|
|
else if (key == "y")
|
|
{
|
|
item->y = std::stof(value) * BLOCK;
|
|
}
|
|
else if (key == "tile")
|
|
{
|
|
item->tile = std::stof(value);
|
|
}
|
|
else if (key == "[/item]")
|
|
{
|
|
// No se realiza ninguna acción para esta clave
|
|
}
|
|
else
|
|
{
|
|
success = false;
|
|
}
|
|
}
|
|
catch (const std::exception &e)
|
|
{
|
|
std::cerr << "Error al asignar la clave " << key << " con valor " << value << ": " << e.what() << std::endl;
|
|
success = false;
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
// Constructor
|
|
Room::Room(const std::string &room_path, std::shared_ptr<ScoreboardData> data)
|
|
: data_(data)
|
|
{
|
|
auto room = Resource::get()->getRoom(room_path);
|
|
initializeRoom(*room);
|
|
|
|
// Abre la Jail si se da el caso
|
|
openTheJail();
|
|
|
|
// Inicializa las superficies de colision
|
|
initRoomSurfaces();
|
|
|
|
// Busca los tiles animados
|
|
setAnimatedTiles();
|
|
|
|
// Crea la textura para el mapa de tiles de la habitación
|
|
map_texture_ = createTexture(Screen::get()->getRenderer(), PLAY_AREA_WIDTH, PLAY_AREA_HEIGHT);
|
|
|
|
// Pinta el mapa de la habitación en la textura
|
|
fillMapTexture();
|
|
|
|
// Establece el color del borde
|
|
Screen::get()->setBorderColor(stringToColor(options.video.palette, border_color_));
|
|
}
|
|
|
|
// Destructor
|
|
Room::~Room() { SDL_DestroyTexture(map_texture_); }
|
|
|
|
void Room::initializeRoom(const RoomData &room)
|
|
{
|
|
// Asignar valores a las variables miembro
|
|
number_ = room.number;
|
|
name_ = room.name;
|
|
bg_color_ = room.bg_color;
|
|
border_color_ = room.border_color;
|
|
item_color1_ = room.item_color1.empty() ? "yellow" : room.item_color1;
|
|
item_color2_ = room.item_color2.empty() ? "magenta" : room.item_color2;
|
|
room_top_ = room.room_top;
|
|
room_bottom_ = room.room_bottom;
|
|
room_left_ = room.room_left;
|
|
room_right_ = room.room_right;
|
|
tile_set_file_ = room.tile_set_file;
|
|
tile_map_file_ = room.tile_map_file;
|
|
auto_surface_direction_ = room.auto_surface_direction;
|
|
tile_map_ = Resource::get()->getTileMap(room.tile_map_file);
|
|
texture_ = Resource::get()->getTexture(room.tile_set_file);
|
|
tile_set_width_ = texture_->getWidth() / TILE_SIZE_;
|
|
is_paused_ = false;
|
|
counter_ = 0;
|
|
|
|
// Crear los enemigos
|
|
for (auto &enemy_data : room.enemies)
|
|
{
|
|
enemies_.emplace_back(std::make_shared<Enemy>(enemy_data));
|
|
}
|
|
|
|
// Crear los items
|
|
for (const auto &item : room.items)
|
|
{
|
|
const SDL_Point itemPos = {item.x, item.y};
|
|
|
|
if (!ItemTracker::get()->hasBeenPicked(room.name, itemPos))
|
|
{
|
|
// Crear una copia local de los datos del item
|
|
ItemData itemCopy = item;
|
|
itemCopy.color1 = stringToColor(options.video.palette, item_color1_);
|
|
itemCopy.color2 = stringToColor(options.video.palette, item_color2_);
|
|
|
|
// Crear el objeto Item usando la copia modificada
|
|
items_.emplace_back(std::make_shared<Item>(itemCopy));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Crea la textura con el mapeado de la habitación
|
|
void Room::fillMapTexture()
|
|
{
|
|
const Color color = stringToColor(options.video.palette, bg_color_);
|
|
SDL_SetRenderTarget(Screen::get()->getRenderer(), map_texture_);
|
|
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), color.r, color.g, color.b, 0xFF);
|
|
SDL_RenderClear(Screen::get()->getRenderer());
|
|
|
|
// Los tileSetFiles son de 20x20 tiles. El primer tile es el 0. Cuentan hacia la derecha y hacia abajo
|
|
|
|
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)
|
|
{
|
|
// 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 * MAP_WIDTH_) + x;
|
|
const bool a = (tile_map_[index] >= 18 * tile_set_width_) && (tile_map_[index] < 19 * tile_set_width_);
|
|
const bool b = tile_map_[index] > -1;
|
|
|
|
if (b && !a)
|
|
{
|
|
clip.x = (tile_map_[index] % tile_set_width_) * TILE_SIZE_;
|
|
clip.y = (tile_map_[index] / tile_set_width_) * TILE_SIZE_;
|
|
texture_->render(x * TILE_SIZE_, y * TILE_SIZE_, &clip);
|
|
|
|
#ifdef DEBUG
|
|
if (Debug::get()->getEnabled())
|
|
{
|
|
if (clip.x != -TILE_SIZE_)
|
|
{
|
|
clip.x = x * TILE_SIZE_;
|
|
clip.y = y * TILE_SIZE_;
|
|
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 64, 64, 64, 224);
|
|
SDL_RenderFillRect(Screen::get()->getRenderer(), &clip);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
if (Debug::get()->getEnabled())
|
|
{
|
|
// BottomSurfaces
|
|
if (true)
|
|
{
|
|
for (auto l : bottom_surfaces_)
|
|
{
|
|
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF);
|
|
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 255, 0, 0, 0xFF);
|
|
SDL_RenderDrawLine(Screen::get()->getRenderer(), l.x1, l.y, l.x2, l.y);
|
|
}
|
|
}
|
|
|
|
// TopSurfaces
|
|
if (true)
|
|
{
|
|
for (auto l : top_surfaces_)
|
|
{
|
|
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF);
|
|
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 255, 0, 0xFF);
|
|
SDL_RenderDrawLine(Screen::get()->getRenderer(), l.x1, l.y, l.x2, l.y);
|
|
}
|
|
}
|
|
|
|
// LeftSurfaces
|
|
if (true)
|
|
{
|
|
for (auto l : left_surfaces_)
|
|
{
|
|
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF);
|
|
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 128, 128, 255, 0xFF);
|
|
SDL_RenderDrawLine(Screen::get()->getRenderer(), l.x, l.y1, l.x, l.y2);
|
|
}
|
|
}
|
|
|
|
// RightSurfaces
|
|
if (true)
|
|
{
|
|
for (auto l : right_surfaces_)
|
|
{
|
|
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF);
|
|
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 255, 255, 0, 0xFF);
|
|
SDL_RenderDrawLine(Screen::get()->getRenderer(), l.x, l.y1, l.x, l.y2);
|
|
}
|
|
}
|
|
|
|
// LeftSlopes
|
|
if (true)
|
|
{
|
|
for (auto l : left_slopes_)
|
|
{
|
|
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF);
|
|
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 255, 255, 0xFF);
|
|
SDL_RenderDrawLine(Screen::get()->getRenderer(), l.x1, l.y1, l.x2, l.y2);
|
|
}
|
|
}
|
|
|
|
// RightSlopes
|
|
if (true)
|
|
{
|
|
for (auto l : right_slopes_)
|
|
{
|
|
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF);
|
|
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 255, 0, 255, 0xFF);
|
|
SDL_RenderDrawLine(Screen::get()->getRenderer(), l.x1, l.y1, l.x2, l.y2);
|
|
}
|
|
}
|
|
|
|
// AutoSurfaces
|
|
if (true)
|
|
{
|
|
for (auto l : auto_surfaces_)
|
|
{
|
|
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 0xFF);
|
|
SDL_RenderDrawLine(Screen::get()->getRenderer(), l.x1, l.y, l.x2, l.y);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
SDL_SetRenderTarget(Screen::get()->getRenderer(), nullptr);
|
|
}
|
|
|
|
// Dibuja el mapa en pantalla
|
|
void Room::renderMap()
|
|
{
|
|
// Dibuja la textura con el mapa en pantalla
|
|
SDL_Rect dest = {0, 0, PLAY_AREA_WIDTH, PLAY_AREA_HEIGHT};
|
|
SDL_RenderCopy(Screen::get()->getRenderer(), map_texture_, nullptr, &dest);
|
|
|
|
// Dibuja los tiles animados
|
|
#ifdef DEBUG
|
|
if (!Debug::get()->getEnabled())
|
|
{
|
|
renderAnimatedTiles();
|
|
}
|
|
#else
|
|
renderAnimatedTiles();
|
|
#endif
|
|
}
|
|
|
|
// Dibuja los enemigos en pantalla
|
|
void Room::renderEnemies()
|
|
{
|
|
for (const auto &enemy : enemies_)
|
|
{
|
|
enemy->render();
|
|
}
|
|
}
|
|
|
|
// Dibuja los objetos en pantalla
|
|
void Room::renderItems()
|
|
{
|
|
for (const auto &item : items_)
|
|
{
|
|
item->render();
|
|
}
|
|
}
|
|
|
|
// Actualiza las variables y objetos de la habitación
|
|
void Room::update()
|
|
{
|
|
if (is_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 room_top_;
|
|
break;
|
|
|
|
case BORDER_BOTTOM:
|
|
return room_bottom_;
|
|
break;
|
|
|
|
case BORDER_RIGHT:
|
|
return room_right_;
|
|
break;
|
|
|
|
case BORDER_LEFT:
|
|
return room_left_;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
// Devuelve el tipo de tile que hay en ese pixel
|
|
TileType Room::getTile(SDL_Point point)
|
|
{
|
|
const int pos = ((point.y / TILE_SIZE_) * MAP_WIDTH_) + (point.x / TILE_SIZE_);
|
|
return getTile(pos);
|
|
}
|
|
|
|
// Devuelve el tipo de tile que hay en ese indice
|
|
TileType Room::getTile(int index)
|
|
{
|
|
// const bool onRange = (index > -1) && (index < mapWidth * mapHeight);
|
|
const bool onRange = (index > -1) && (index < (int)tile_map_.size());
|
|
|
|
if (onRange)
|
|
{
|
|
// Las filas 0-8 son de tiles t_wall
|
|
if ((tile_map_[index] >= 0) && (tile_map_[index] < 9 * tile_set_width_))
|
|
{
|
|
return TileType::WALL;
|
|
}
|
|
|
|
// Las filas 9-17 son de tiles t_passable
|
|
else if ((tile_map_[index] >= 9 * tile_set_width_) && (tile_map_[index] < 18 * tile_set_width_))
|
|
{
|
|
return TileType::PASSABLE;
|
|
}
|
|
|
|
// Las filas 18-20 es de tiles t_animated
|
|
else if ((tile_map_[index] >= 18 * tile_set_width_) && (tile_map_[index] < 21 * tile_set_width_))
|
|
{
|
|
return TileType::ANIMATED;
|
|
}
|
|
|
|
// La fila 21 es de tiles t_slope_r
|
|
else if ((tile_map_[index] >= 21 * tile_set_width_) && (tile_map_[index] < 22 * tile_set_width_))
|
|
{
|
|
return TileType::SLOPE_R;
|
|
}
|
|
|
|
// La fila 22 es de tiles t_slope_l
|
|
else if ((tile_map_[index] >= 22 * tile_set_width_) && (tile_map_[index] < 23 * tile_set_width_))
|
|
{
|
|
return TileType::SLOPE_L;
|
|
}
|
|
|
|
// La fila 23 es de tiles t_kill
|
|
else if ((tile_map_[index] >= 23 * tile_set_width_) && (tile_map_[index] < 24 * tile_set_width_))
|
|
{
|
|
return TileType::KILL;
|
|
}
|
|
}
|
|
|
|
return TileType::EMPTY;
|
|
}
|
|
|
|
// Indica si hay colision con un enemigo a partir de un rectangulo
|
|
bool Room::enemyCollision(SDL_Rect &rect)
|
|
{
|
|
for (const auto &enemy : enemies_)
|
|
{
|
|
if (checkCollision(rect, enemy->getCollider()))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Indica si hay colision con un objeto a partir de un rectangulo
|
|
bool Room::itemCollision(SDL_Rect &rect)
|
|
{
|
|
for (int i = 0; i < static_cast<int>(items_.size()); ++i)
|
|
{
|
|
if (checkCollision(rect, items_.at(i)->getCollider()))
|
|
{
|
|
ItemTracker::get()->addItem(name_, items_.at(i)->getPos());
|
|
items_.erase(items_.begin() + i);
|
|
JA_PlaySound(Resource::get()->getSound("item.wav"));
|
|
data_->items++;
|
|
options.stats.items = data_->items;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Obten la coordenada de la cuesta a partir de un punto perteneciente a ese tile
|
|
int Room::getSlopeHeight(SDL_Point p, TileType slope)
|
|
{
|
|
// Calcula la base del tile
|
|
int base = ((p.y / TILE_SIZE_) * TILE_SIZE_) + TILE_SIZE_;
|
|
#ifdef DEBUG
|
|
Debug::get()->add("BASE = " + std::to_string(base));
|
|
#endif
|
|
|
|
// Calcula cuanto se ha entrado en el tile horizontalmente
|
|
const int pos = (p.x % TILE_SIZE_); // Esto da un valor entre 0 y 7
|
|
#ifdef DEBUG
|
|
Debug::get()->add("POS = " + std::to_string(pos));
|
|
#endif
|
|
|
|
// Se resta a la base la cantidad de pixeles pos en funcion de la rampa
|
|
if (slope == TileType::SLOPE_R)
|
|
{
|
|
base -= pos + 1;
|
|
#ifdef DEBUG
|
|
Debug::get()->add("BASE_R = " + std::to_string(base));
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
base -= (TILE_SIZE_ - pos);
|
|
#ifdef DEBUG
|
|
Debug::get()->add("BASE_L = " + std::to_string(base));
|
|
#endif
|
|
}
|
|
|
|
return base;
|
|
}
|
|
|
|
// Calcula las superficies inferiores
|
|
void Room::setBottomSurfaces()
|
|
{
|
|
std::vector<int> 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)tile_map_.size() - MAP_WIDTH_; ++i)
|
|
{
|
|
if (getTile(i) == TileType::WALL && getTile(i + MAP_WIDTH_) != TileType::WALL)
|
|
{
|
|
tile.push_back(i);
|
|
|
|
// Si llega al final de la fila, introduce un separador
|
|
if (i % MAP_WIDTH_ == MAP_WIDTH_ - 1)
|
|
{
|
|
tile.push_back(-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Añade un terminador
|
|
tile.push_back(-1);
|
|
|
|
// Recorre el vector de tiles buscando tiles consecutivos para localizar las superficies
|
|
if ((int)tile.size() > 1)
|
|
{
|
|
int i = 0;
|
|
do
|
|
{
|
|
LineHorizontal line;
|
|
line.x1 = (tile[i] % MAP_WIDTH_) * TILE_SIZE_;
|
|
line.y = ((tile[i] / MAP_WIDTH_) * TILE_SIZE_) + TILE_SIZE_ - 1;
|
|
int last_one = i;
|
|
i++;
|
|
|
|
if (i <= (int)tile.size() - 1)
|
|
{
|
|
while (tile[i] == tile[i - 1] + 1)
|
|
{
|
|
last_one = i;
|
|
if (i == (int)tile.size() - 1)
|
|
{
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
line.x2 = ((tile[last_one] % MAP_WIDTH_) * TILE_SIZE_) + TILE_SIZE_ - 1;
|
|
bottom_surfaces_.push_back(line);
|
|
if (i <= (int)tile.size() - 1)
|
|
{
|
|
if (tile[i] == -1)
|
|
{ // Si el siguiente elemento es un separador, hay que saltarlo
|
|
i++;
|
|
}
|
|
}
|
|
} while (i < (int)tile.size() - 1);
|
|
}
|
|
}
|
|
|
|
// Calcula las superficies superiores
|
|
void Room::setTopSurfaces()
|
|
{
|
|
std::vector<int> 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 = MAP_WIDTH_; i < (int)tile_map_.size(); ++i)
|
|
{
|
|
if ((getTile(i) == TileType::WALL || getTile(i) == TileType::PASSABLE) && getTile(i - MAP_WIDTH_) != TileType::WALL)
|
|
{
|
|
tile.push_back(i);
|
|
|
|
// Si llega al final de la fila, introduce un separador
|
|
if (i % MAP_WIDTH_ == MAP_WIDTH_ - 1)
|
|
{
|
|
tile.push_back(-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Añade un terminador
|
|
tile.push_back(-1);
|
|
|
|
// Recorre el vector de tiles buscando tiles consecutivos para localizar las superficies
|
|
if ((int)tile.size() > 1)
|
|
{
|
|
int i = 0;
|
|
do
|
|
{
|
|
LineHorizontal line;
|
|
line.x1 = (tile[i] % MAP_WIDTH_) * TILE_SIZE_;
|
|
line.y = (tile[i] / MAP_WIDTH_) * TILE_SIZE_;
|
|
int last_one = i;
|
|
i++;
|
|
|
|
if (i <= (int)tile.size() - 1)
|
|
{
|
|
while (tile[i] == tile[i - 1] + 1)
|
|
{
|
|
last_one = i;
|
|
if (i == (int)tile.size() - 1)
|
|
{
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
line.x2 = ((tile[last_one] % MAP_WIDTH_) * TILE_SIZE_) + TILE_SIZE_ - 1;
|
|
top_surfaces_.push_back(line);
|
|
if (i <= (int)tile.size() - 1)
|
|
{
|
|
if (tile[i] == -1)
|
|
{ // Si el siguiente elemento es un separador, hay que saltarlo
|
|
i++;
|
|
}
|
|
}
|
|
} while (i < (int)tile.size() - 1);
|
|
}
|
|
}
|
|
|
|
// Calcula las superficies laterales izquierdas
|
|
void Room::setLeftSurfaces()
|
|
{
|
|
std::vector<int> 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 < MAP_WIDTH_; ++i)
|
|
{
|
|
for (int j = 0; j < MAP_HEIGHT_; ++j)
|
|
{
|
|
const int pos = (j * MAP_WIDTH_ + i);
|
|
if (getTile(pos) == TileType::WALL && getTile(pos - 1) != TileType::WALL)
|
|
{
|
|
tile.push_back(pos);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Añade un terminador
|
|
tile.push_back(-1);
|
|
|
|
// 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
|
|
if ((int)tile.size() > 1)
|
|
{
|
|
int i = 0;
|
|
do
|
|
{
|
|
LineVertical line;
|
|
line.x = (tile[i] % MAP_WIDTH_) * TILE_SIZE_;
|
|
line.y1 = ((tile[i] / MAP_WIDTH_) * TILE_SIZE_);
|
|
while (tile[i] + MAP_WIDTH_ == tile[i + 1])
|
|
{
|
|
if (i == (int)tile.size() - 1)
|
|
{
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
line.y2 = ((tile[i] / MAP_WIDTH_) * TILE_SIZE_) + TILE_SIZE_ - 1;
|
|
left_surfaces_.push_back(line);
|
|
i++;
|
|
} while (i < (int)tile.size() - 1);
|
|
}
|
|
}
|
|
|
|
// Calcula las superficies laterales derechas
|
|
void Room::setRightSurfaces()
|
|
{
|
|
std::vector<int> 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 < MAP_WIDTH_ - 1; ++i)
|
|
{
|
|
for (int j = 0; j < MAP_HEIGHT_; ++j)
|
|
{
|
|
const int pos = (j * MAP_WIDTH_ + i);
|
|
if (getTile(pos) == TileType::WALL && getTile(pos + 1) != TileType::WALL)
|
|
{
|
|
tile.push_back(pos);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Añade un terminador
|
|
tile.push_back(-1);
|
|
|
|
// 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
|
|
if ((int)tile.size() > 1)
|
|
{
|
|
int i = 0;
|
|
do
|
|
{
|
|
LineVertical line;
|
|
line.x = ((tile[i] % MAP_WIDTH_) * TILE_SIZE_) + TILE_SIZE_ - 1;
|
|
line.y1 = ((tile[i] / MAP_WIDTH_) * TILE_SIZE_);
|
|
while (tile[i] + MAP_WIDTH_ == tile[i + 1])
|
|
{
|
|
if (i == (int)tile.size() - 1)
|
|
{
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
line.y2 = ((tile[i] / MAP_WIDTH_) * TILE_SIZE_) + TILE_SIZE_ - 1;
|
|
right_surfaces_.push_back(line);
|
|
i++;
|
|
} while (i < (int)tile.size() - 1);
|
|
}
|
|
}
|
|
|
|
// 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<int> found;
|
|
for (int i = 0; i < (int)tile_map_.size(); ++i)
|
|
{
|
|
if (getTile(i) == TileType::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)
|
|
{
|
|
LineDiagonal line;
|
|
line.x1 = (found[0] % MAP_WIDTH_) * TILE_SIZE_;
|
|
line.y1 = (found[0] / MAP_WIDTH_) * TILE_SIZE_;
|
|
int lookingFor = found[0] + MAP_WIDTH_ + 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 += MAP_WIDTH_ + 1;
|
|
found.erase(found.begin() + i);
|
|
i--;
|
|
}
|
|
}
|
|
line.x2 = ((lastOneFound % MAP_WIDTH_) * TILE_SIZE_) + TILE_SIZE_ - 1;
|
|
line.y2 = ((lastOneFound / MAP_WIDTH_) * TILE_SIZE_) + TILE_SIZE_ - 1;
|
|
left_slopes_.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<int> found;
|
|
for (int i = 0; i < (int)tile_map_.size(); ++i)
|
|
{
|
|
if (getTile(i) == TileType::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)
|
|
{
|
|
LineDiagonal line;
|
|
line.x1 = ((found[0] % MAP_WIDTH_) * TILE_SIZE_) + TILE_SIZE_ - 1;
|
|
line.y1 = (found[0] / MAP_WIDTH_) * TILE_SIZE_;
|
|
int lookingFor = found[0] + MAP_WIDTH_ - 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 += MAP_WIDTH_ - 1;
|
|
found.erase(found.begin() + i);
|
|
i--;
|
|
}
|
|
}
|
|
line.x2 = (lastOneFound % MAP_WIDTH_) * TILE_SIZE_;
|
|
line.y2 = ((lastOneFound / MAP_WIDTH_) * TILE_SIZE_) + TILE_SIZE_ - 1;
|
|
right_slopes_.push_back(line);
|
|
}
|
|
}
|
|
|
|
// Calcula las superficies automaticas
|
|
void Room::setAutoSurfaces()
|
|
{
|
|
std::vector<int> 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 = MAP_WIDTH_; i < (int)tile_map_.size(); ++i)
|
|
{
|
|
if (getTile(i) == TileType::ANIMATED)
|
|
{
|
|
tile.push_back(i);
|
|
|
|
// Si llega al final de la fila, introduce un separador
|
|
if (i % MAP_WIDTH_ == MAP_WIDTH_ - 1)
|
|
{
|
|
tile.push_back(-1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Recorre el vector de tiles buscando tiles consecutivos para localizar las superficies
|
|
if ((int)tile.size() > 0)
|
|
{
|
|
int i = 0;
|
|
do
|
|
{
|
|
LineHorizontal line;
|
|
line.x1 = (tile[i] % MAP_WIDTH_) * TILE_SIZE_;
|
|
line.y = (tile[i] / MAP_WIDTH_) * TILE_SIZE_;
|
|
int last_one = i;
|
|
i++;
|
|
|
|
if (i <= (int)tile.size() - 1)
|
|
{
|
|
while (tile[i] == tile[i - 1] + 1)
|
|
{
|
|
last_one = i;
|
|
if (i == (int)tile.size() - 1)
|
|
{
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
line.x2 = ((tile[last_one] % MAP_WIDTH_) * TILE_SIZE_) + TILE_SIZE_ - 1;
|
|
auto_surfaces_.push_back(line);
|
|
if (i <= (int)tile.size() - 1)
|
|
{
|
|
if (tile[i] == -1)
|
|
{ // Si el siguiente elemento es un separador, hay que saltarlo
|
|
i++;
|
|
}
|
|
}
|
|
} while (i < (int)tile.size() - 1);
|
|
}
|
|
}
|
|
|
|
// 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)tile_map_.size(); ++i)
|
|
{
|
|
if (getTile(i) == TileType::ANIMATED)
|
|
{
|
|
// La i es la ubicación
|
|
const int x = (i % MAP_WIDTH_) * TILE_SIZE_;
|
|
const int y = (i / MAP_WIDTH_) * TILE_SIZE_;
|
|
|
|
// TileMap[i] es el tile a poner
|
|
const int xc = (tile_map_[i] % tile_set_width_) * TILE_SIZE_;
|
|
const int yc = (tile_map_[i] / tile_set_width_) * TILE_SIZE_;
|
|
|
|
AnimatedTile at;
|
|
at.sprite = std::make_shared<Sprite>(texture_, x, y, 8, 8);
|
|
at.sprite->setClip(xc, yc, 8, 8);
|
|
at.x_orig = xc;
|
|
animated_tiles_.push_back(at);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Actualiza los tiles animados
|
|
void Room::updateAnimatedTiles()
|
|
{
|
|
const int numFrames = 4;
|
|
int offset = 0;
|
|
if (auto_surface_direction_ == -1)
|
|
{
|
|
offset = ((counter_ / 3) % numFrames * TILE_SIZE_);
|
|
}
|
|
else
|
|
{
|
|
offset = ((numFrames - 1 - ((counter_ / 3) % numFrames)) * TILE_SIZE_);
|
|
}
|
|
|
|
for (auto &a : animated_tiles_)
|
|
{
|
|
SDL_Rect rect = a.sprite->getClip();
|
|
rect.x = a.x_orig + offset;
|
|
a.sprite->setClip(rect);
|
|
}
|
|
}
|
|
|
|
// Pinta los tiles animados en pantalla
|
|
void Room::renderAnimatedTiles()
|
|
{
|
|
for (const auto &a : animated_tiles_)
|
|
{
|
|
a.sprite->render();
|
|
}
|
|
}
|
|
|
|
// Comprueba las colisiones
|
|
int Room::checkRightSurfaces(SDL_Rect *rect)
|
|
{
|
|
for (const auto &s : right_surfaces_)
|
|
{
|
|
if (checkCollision(s, *rect))
|
|
{
|
|
return s.x;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
// Comprueba las colisiones
|
|
int Room::checkLeftSurfaces(SDL_Rect *rect)
|
|
{
|
|
for (const auto &s : left_surfaces_)
|
|
{
|
|
if (checkCollision(s, *rect))
|
|
{
|
|
return s.x;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
// Comprueba las colisiones
|
|
int Room::checkTopSurfaces(SDL_Rect *rect)
|
|
{
|
|
for (const auto &s : top_surfaces_)
|
|
{
|
|
if (checkCollision(s, *rect))
|
|
{
|
|
return s.y;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
// Comprueba las colisiones
|
|
int Room::checkBottomSurfaces(SDL_Rect *rect)
|
|
{
|
|
for (const auto &s : bottom_surfaces_)
|
|
{
|
|
if (checkCollision(s, *rect))
|
|
{
|
|
return s.y;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
// Comprueba las colisiones
|
|
int Room::checkAutoSurfaces(SDL_Rect *rect)
|
|
{
|
|
for (const auto &s : auto_surfaces_)
|
|
{
|
|
if (checkCollision(s, *rect))
|
|
{
|
|
return s.y;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
// Comprueba las colisiones
|
|
bool Room::checkTopSurfaces(SDL_Point *p)
|
|
{
|
|
for (const auto &s : top_surfaces_)
|
|
{
|
|
if (checkCollision(s, *p))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Comprueba las colisiones
|
|
bool Room::checkAutoSurfaces(SDL_Point *p)
|
|
{
|
|
for (const auto &s : auto_surfaces_)
|
|
{
|
|
if (checkCollision(s, *p))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Comprueba las colisiones
|
|
int Room::checkLeftSlopes(const LineVertical *line)
|
|
{
|
|
for (const auto &slope : left_slopes_)
|
|
{
|
|
const SDL_Point p = checkCollision(slope, *line);
|
|
if (p.x != -1)
|
|
{
|
|
return p.y;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
// Comprueba las colisiones
|
|
bool Room::checkLeftSlopes(SDL_Point *p)
|
|
{
|
|
for (const auto &slope : left_slopes_)
|
|
{
|
|
if (checkCollision(*p, slope))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Comprueba las colisiones
|
|
int Room::checkRightSlopes(const LineVertical *line)
|
|
{
|
|
for (const auto &slope : right_slopes_)
|
|
{
|
|
const SDL_Point p = checkCollision(slope, *line);
|
|
if (p.x != -1)
|
|
{
|
|
return p.y;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
// Comprueba las colisiones
|
|
bool Room::checkRightSlopes(SDL_Point *p)
|
|
{
|
|
for (const auto &slope : right_slopes_)
|
|
{
|
|
if (checkCollision(*p, slope))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Abre la Jail si se da el caso
|
|
void Room::openTheJail()
|
|
{
|
|
if (data_->jail_is_open && name_ == "THE JAIL")
|
|
{
|
|
// Elimina el último enemigo (Bry debe ser el último enemigo definido en el fichero)
|
|
if (!enemies_.empty())
|
|
{
|
|
enemies_.pop_back();
|
|
}
|
|
|
|
// Abre las puertas
|
|
constexpr int TILE_A = 16 + (13 * 32);
|
|
constexpr int TILE_B = 16 + (14 * 32);
|
|
if (TILE_A < tile_map_.size())
|
|
{
|
|
tile_map_[TILE_A] = -1;
|
|
}
|
|
if (TILE_B < tile_map_.size())
|
|
{
|
|
tile_map_[TILE_B] = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Inicializa las superficies de colision
|
|
void Room::initRoomSurfaces()
|
|
{
|
|
setBottomSurfaces();
|
|
setTopSurfaces();
|
|
setLeftSurfaces();
|
|
setRightSurfaces();
|
|
setLeftSlopes();
|
|
setRightSlopes();
|
|
setAutoSurfaces();
|
|
} |