1099 lines
28 KiB
C++
1099 lines
28 KiB
C++
#include "room.h"
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
|
|
// Constructor
|
|
Room::Room(std::string file_path, SDL_Renderer *renderer, Screen *screen, Asset *asset, ItemTracker *itemTracker, int *items, Debug *debug)
|
|
{
|
|
// Inicializa variables
|
|
tileSize = 8;
|
|
mapWidth = 32;
|
|
mapHeight = 16;
|
|
tilesetWidth = 20;
|
|
|
|
// Copia los punteros a objetos
|
|
this->renderer = renderer;
|
|
this->asset = asset;
|
|
this->screen = screen;
|
|
this->itemTracker = itemTracker;
|
|
this->itemsPicked = items;
|
|
this->debug = debug;
|
|
|
|
// Crea los objetos
|
|
load(file_path);
|
|
texture = new LTexture(renderer, asset->get(tileset));
|
|
itemSound = JA_LoadSound(asset->get("item.wav").c_str());
|
|
|
|
// Calcula las superficies
|
|
setBottomSurfaces();
|
|
setTopSurfaces();
|
|
setLeftSurfaces();
|
|
setRightSurfaces();
|
|
setLeftSlopes();
|
|
setRightSlopes();
|
|
|
|
// 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();
|
|
|
|
// Establece el color del borde
|
|
screen->setBorderColor(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;
|
|
}
|
|
}
|
|
|
|
// 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]")
|
|
{
|
|
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 != "</data>")
|
|
{
|
|
std::stringstream ss(line);
|
|
std::string tmp;
|
|
while (getline(ss, tmp, ','))
|
|
{
|
|
tilemap.push_back(std::stoi(tmp));
|
|
}
|
|
}
|
|
} while (line != "</data>");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} 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 == "border")
|
|
{
|
|
borderColor = 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);
|
|
if (debug->getEnabled())
|
|
{
|
|
if (clip.x != -8)
|
|
{
|
|
clip.x = x * 8;
|
|
clip.y = y * 8;
|
|
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_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_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_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_RenderDrawLine(renderer, l.x, l.y1, l.x, l.y2);
|
|
}
|
|
}
|
|
|
|
// LeftSlopes
|
|
if (false)
|
|
{
|
|
for (auto l : leftSlopes)
|
|
{
|
|
SDL_SetRenderDrawColor(renderer, (rand() % 128) + 96, (rand() % 128) + 96, (rand() % 128) + 96, 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_RenderDrawLine(renderer, l.x1, l.y1, l.x2, l.y2);
|
|
}
|
|
}
|
|
}
|
|
// ****
|
|
|
|
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
|
|
tile_e Room::getTile(SDL_Point point)
|
|
{
|
|
const int maxTile = mapWidth * mapHeight;
|
|
const int pos = ((point.y / tileSize) * mapWidth) + (point.x / tileSize);
|
|
tile_e tile = t_empty;
|
|
|
|
if (pos < maxTile)
|
|
{
|
|
// Las filas 0-7 son de tiles t_wall
|
|
if ((tilemap[pos] > 0) && (tilemap[pos] < 8 * tilesetWidth))
|
|
{
|
|
return t_wall;
|
|
}
|
|
|
|
// La fila 8 es de tiles t_slope_r
|
|
else if ((tilemap[pos] >= 8 * tilesetWidth) && (tilemap[pos] < 9 * tilesetWidth))
|
|
{
|
|
return t_slope_r;
|
|
}
|
|
|
|
// La fila 9 es de tiles t_slope_l
|
|
else if ((tilemap[pos] >= 9 * tilesetWidth) && (tilemap[pos] < 10 * tilesetWidth))
|
|
{
|
|
return t_slope_l;
|
|
}
|
|
|
|
// Las filas 10-14 son de tiles t_passable
|
|
if ((tilemap[pos] >= 10 * tilesetWidth) && (tilemap[pos] < 15 * tilesetWidth))
|
|
{
|
|
return t_passable;
|
|
}
|
|
}
|
|
|
|
return tile;
|
|
}
|
|
|
|
// Devuelve el tipo de tile que hay en ese indice
|
|
tile_e Room::getTile(int index)
|
|
{
|
|
const int maxTile = mapWidth * mapHeight;
|
|
tile_e tile = t_empty;
|
|
|
|
if (index < maxTile)
|
|
{
|
|
// Las filas 0-7 son de tiles t_wall
|
|
if ((tilemap[index] > 0) && (tilemap[index] < 8 * tilesetWidth))
|
|
{
|
|
return t_wall;
|
|
}
|
|
|
|
// La fila 8 es de tiles t_slope_r
|
|
else if ((tilemap[index] >= 8 * tilesetWidth) && (tilemap[index] < 9 * tilesetWidth))
|
|
{
|
|
return t_slope_r;
|
|
}
|
|
|
|
// La fila 9 es de tiles t_slope_l
|
|
else if ((tilemap[index] >= 9 * tilesetWidth) && (tilemap[index] < 10 * tilesetWidth))
|
|
{
|
|
return t_slope_l;
|
|
}
|
|
|
|
// Las filas 10-14 son de tiles t_passable
|
|
if ((tilemap[index] >= 10 * tilesetWidth) && (tilemap[index] < 15 * tilesetWidth))
|
|
{
|
|
return t_passable;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
// 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<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 < 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;
|
|
while (i < tile.size())
|
|
{
|
|
h_line_t line;
|
|
line.x1 = (tile[i] % mapWidth) * tileSize;
|
|
line.y = ((tile[i] / mapWidth) * tileSize) + tileSize - 1;
|
|
|
|
while (tile[i] + 1 == tile[i + 1])
|
|
{
|
|
i++;
|
|
}
|
|
line.x2 = ((tile[i] % mapWidth) * tileSize) + tileSize - 1;
|
|
bottomSurfaces.push_back(line);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
// 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 = mapWidth; i < 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;
|
|
while (i < tile.size())
|
|
{
|
|
h_line_t line;
|
|
line.x1 = (tile[i] % mapWidth) * tileSize;
|
|
line.y = (tile[i] / mapWidth) * tileSize;
|
|
while (tile[i] + 1 == tile[i + 1])
|
|
{
|
|
i++;
|
|
}
|
|
line.x2 = ((tile[i] % mapWidth) * tileSize) + tileSize - 1;
|
|
topSurfaces.push_back(line);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
// 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 < 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 < 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<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 < 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 < 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<int> found;
|
|
for (int i = 0; i < 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 < 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<int> found;
|
|
for (int i = 0; i < 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 < 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);
|
|
}
|
|
}
|
|
|
|
// 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
|
|
bool Room::checkTopSurfaces(SDL_Point *p)
|
|
{
|
|
for (auto s : topSurfaces)
|
|
{
|
|
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;
|
|
} |