You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
723 lines
17 KiB
C++
723 lines
17 KiB
C++
#include <fstream>
|
|
#include <algorithm>
|
|
#include <string>
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include "RLGame.hpp"
|
|
#include "utils.hpp"
|
|
#include "Map.hpp"
|
|
|
|
#include "Entity.hpp"
|
|
|
|
#ifdef _DEBUG
|
|
#include <chrono>
|
|
#endif // _DEBUG
|
|
|
|
void CreateMapRooms(std::vector<MapRoom>& rooms, int amount);
|
|
|
|
struct MapDoor
|
|
{
|
|
Position pos;
|
|
bool isConnected;
|
|
short direction;
|
|
};
|
|
|
|
struct MapRoom
|
|
{
|
|
MapRoom(int dx, int dy, int dwidth, int dheight);
|
|
MapRoom(MapRoom&& other) noexcept;
|
|
MapRoom(const MapRoom& other) = delete;
|
|
MapRoom& operator=(const MapRoom& other) = delete;
|
|
MapRoom& operator=(MapRoom&& other) noexcept = delete;
|
|
~MapRoom();
|
|
|
|
int x;
|
|
int y;
|
|
int width;
|
|
int height;
|
|
int amountDoors;
|
|
MapDoor* doors;
|
|
};
|
|
|
|
|
|
// fuck VC++
|
|
//const std::array<wchar_t, 6> Map::WALLS_ARRAY = { L'\x2514', L'\x250c', L'\x2510', L'\x2518', L'\x2500', L'\x2502' };
|
|
|
|
Map::Map()
|
|
: Map("Default", false)
|
|
{
|
|
}
|
|
|
|
Map::Map(const std::string& name, bool rooms, const Position& position)
|
|
: m_DownStairsPos{}
|
|
, m_MapName{ "RandomLevel-" + name }
|
|
, m_pTiles{ new std::wstring[G_MAP_HEIGHT] }
|
|
//, m_Items{}
|
|
, m_IsRooms{ rooms }
|
|
{
|
|
G_CURRENT_MAP = this; // will always only have 1 map loaded
|
|
std::wifstream mapFile{ ("resources/maps/" + m_MapName + ".level") };
|
|
if(mapFile) // load if exists
|
|
LoadMap(mapFile);
|
|
else // generate if not
|
|
GenerateMap(position);
|
|
}
|
|
|
|
Map::Map(Map&& other) noexcept
|
|
: m_DownStairsPos{ other.m_DownStairsPos }
|
|
, m_MapName{ other.m_MapName }
|
|
, m_pTiles{ other.m_pTiles }
|
|
//, m_Items{ other.m_Items }
|
|
, m_IsRooms{ other.m_IsRooms }
|
|
{
|
|
other.m_pTiles = nullptr;
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
#define _DEBUG_NO_MAP_
|
|
#endif // _DEBUG
|
|
|
|
Map::~Map()
|
|
{
|
|
if(m_pTiles != nullptr)
|
|
{
|
|
#ifndef _DEBUG_NO_MAP_
|
|
SaveMap();
|
|
#endif // _DEBUG_NO_MAP_
|
|
delete[] m_pTiles;
|
|
m_pTiles = nullptr;
|
|
}
|
|
//m_Items.clear();
|
|
}
|
|
|
|
void Map::LoadMap(std::wifstream& file)
|
|
{
|
|
std::cout << "Loading map " << m_MapName << "\n";
|
|
std::wstring line;
|
|
if(file.is_open())
|
|
{
|
|
int id{};
|
|
while(std::getline(file, line))
|
|
{
|
|
m_pTiles[id] = line;
|
|
++id;
|
|
}
|
|
file.close();
|
|
|
|
bool foundStairs{};
|
|
bool foundRooms{};
|
|
for(int y{}; y < G_MAP_HEIGHT; ++y)
|
|
{
|
|
for(int x{}; x < G_MAP_WIDTH; ++x)
|
|
{
|
|
if(m_pTiles[y][x] == L'>')
|
|
{
|
|
m_DownStairsPos.x = x;
|
|
m_DownStairsPos.y = y;
|
|
foundStairs = true;
|
|
}
|
|
else if(m_pTiles[y][x] == WALLS_ARRAY[0])
|
|
{
|
|
m_IsRooms = true;
|
|
foundRooms = true;
|
|
}
|
|
|
|
if(foundStairs && foundRooms)
|
|
goto finished;
|
|
}
|
|
}
|
|
finished:
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
std::cerr << "\nMap " << m_MapName << " couldn't be read\n";
|
|
GenerateMap(Position{ G_SCREEN_WIDTH / 2, G_SCREEN_HEIGHT / 2 });
|
|
}
|
|
}
|
|
|
|
void Map::GenerateMap(const Position& position)
|
|
{
|
|
std::cout << "Generating new map...\n";
|
|
std::wstring line{};
|
|
Position start{ !(position == Position{-1, -1}) ? position : Position{G_SCREEN_WIDTH / 2, G_SCREEN_HEIGHT / 2} };
|
|
const Position reset{ start };
|
|
#ifdef _DEBUG
|
|
std::chrono::steady_clock::time_point t1{ std::chrono::steady_clock::now() };
|
|
std::chrono::steady_clock::time_point t2{};
|
|
#endif // _DEBUG
|
|
|
|
// fill the level with blocks
|
|
for(int x{}; x < G_MAP_WIDTH; ++x)
|
|
{
|
|
line += G_MAPTILE_WALL;
|
|
}
|
|
|
|
for(int y{}; y < G_MAP_HEIGHT; ++y)
|
|
{
|
|
m_pTiles[y] = line;
|
|
}
|
|
|
|
if(m_IsRooms)
|
|
{
|
|
// put new stuff here
|
|
// copy CreateRooms from Game.cpp, make it generate all rooms and store in vector, insert in level string, delete vector, save map, should work :)
|
|
std::vector<MapRoom> rooms{};
|
|
rooms.push_back(MapRoom{start.x - 1, start.y - 1, 5, 5}); // starting room
|
|
//m_Tiles[start.y - 2][start.x - 2] = L'<';
|
|
//m_Tiles[start.y - 2][start.x - 1] = L'>';
|
|
int amountToGenerate{ utils::RandomBetween(9, 25) };
|
|
CreateMapRooms(rooms, amountToGenerate);
|
|
|
|
// put in level string, copy from Room.cpp Draw()
|
|
for(auto& room : rooms)
|
|
{
|
|
for(int dx{ room.x }; dx < room.x + room.width; ++dx)
|
|
{
|
|
if(dx == room.x)
|
|
{
|
|
/*terminal_put(dx, room.y, L'┌');
|
|
terminal_put(dx, room.y + room.height - 1, L'└');*/
|
|
m_pTiles[room.y][dx] = L'\x250c';
|
|
m_pTiles[room.y + room.height - 1][dx] = L'\x2514';
|
|
}
|
|
else if(dx == room.x + room.width - 1)
|
|
{
|
|
/*terminal_put(dx, room.y, L'┐');
|
|
terminal_put(dx, room.y + room.height - 1, L'┘');*/
|
|
m_pTiles[room.y][dx] = L'\x2510';
|
|
m_pTiles[room.y + room.height - 1][dx] = L'\x2518';
|
|
}
|
|
else
|
|
{
|
|
//terminal_put(dx, room.y, L'─');
|
|
//terminal_put(dx, room.y + room.height - 1, L'─');
|
|
m_pTiles[room.y][dx] = L'\x2500';
|
|
m_pTiles[room.y + room.height - 1][dx] = L'\x2500';
|
|
}
|
|
}
|
|
|
|
for(int dy{ room.y + 1 }; dy < room.y + room.height - 1; ++dy)
|
|
{
|
|
/*terminal_put(room.x, dy, L'│');
|
|
terminal_put(room.x + room.width - 1, dy, L'│');*/
|
|
m_pTiles[dy][room.x] = L'\x2502';
|
|
m_pTiles[dy][room.x + room.width - 1] = L'\x2502';
|
|
for(int dx{ room.x + 1 }; dx < room.x + room.width - 1; ++dx)
|
|
{
|
|
//terminal_put(dx, dy, '.');
|
|
m_pTiles[dy][dx] = L'.';
|
|
}
|
|
}
|
|
|
|
for(int i{}; i < room.amountDoors; ++i)
|
|
{
|
|
//terminal_put(room.doors[i].x, room.doors[i].y, MAPTILE_DOOR);
|
|
m_pTiles[room.doors[i].pos.y][room.doors[i].pos.x] = G_MAPTILE_DOOR;
|
|
|
|
// NetHack style doors
|
|
/*switch(room.doors[i].direction)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
m_Tiles[room.doors[i].pos.y][room.doors[i].pos.x] = L'|';
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
m_Tiles[room.doors[i].pos.y][room.doors[i].pos.x] = L'─';
|
|
break;
|
|
}*/
|
|
}
|
|
}
|
|
|
|
/// TODO: fix all, read comments
|
|
|
|
// modified utils::Bresenham to insert in m_Tiles, should use an actual pathfinding algorithm instead of a line drawing algorithm
|
|
// needs more work but just testing
|
|
Position doorPos1{ rooms[0].doors[0].pos };
|
|
Position doorPos2{ rooms[1].doors[0].pos };
|
|
|
|
switch(rooms[0].doors[0].direction) // get tile in front of door
|
|
{
|
|
case 0: // up
|
|
doorPos1.y -= 1;
|
|
break;
|
|
case 1: // down
|
|
doorPos1.y += 1;
|
|
break;
|
|
case 2: // left
|
|
doorPos1.x -= 1;
|
|
break;
|
|
case 3: // right
|
|
doorPos1.x += 1;
|
|
break;
|
|
}
|
|
|
|
switch(rooms[1].doors[0].direction)
|
|
{
|
|
case 0: // up
|
|
doorPos2.y -= 1;
|
|
break;
|
|
case 1: // down
|
|
doorPos2.y += 1;
|
|
break;
|
|
case 2: // left
|
|
doorPos2.x -= 1;
|
|
break;
|
|
case 3: // right
|
|
doorPos2.x += 1;
|
|
break;
|
|
}
|
|
|
|
BresenhamMap(doorPos1.x, doorPos1.y, doorPos2.x, doorPos2.y);
|
|
|
|
// stairs
|
|
m_pTiles[start.y][start.x] = L'<';
|
|
m_pTiles[start.y + 2][start.x + 1] = L'>';
|
|
m_DownStairsPos.x = start.x + 1;
|
|
m_DownStairsPos.y = start.y + 2;
|
|
|
|
// vector isn't needed anymore
|
|
rooms.clear();
|
|
|
|
#ifdef _DEBUG
|
|
t2 = std::chrono::steady_clock::now();
|
|
float elapsedSec{ std::chrono::duration<float>(t2 - t1).count() };
|
|
std::cout << "Time to generate: " << elapsedSec << '\n';
|
|
#endif // _DEBUG
|
|
}
|
|
else
|
|
{
|
|
int amountGenerated{};
|
|
int amountToGenerate{ utils::RandomBetween(G_MAP_HEIGHT * G_MAP_WIDTH / 6, G_MAP_HEIGHT * G_MAP_WIDTH / 4) - 10000 };
|
|
int x{};
|
|
int y{};
|
|
const short horizontalDirection{ static_cast<short>(utils::RandomBetween(0, 10)) }; // the map will be more likely to generate in this direction
|
|
const short verticalDirection{ static_cast<short>(utils::RandomBetween(0, 10)) };
|
|
/*
|
|
0 - RIGHT
|
|
1 - LEFT
|
|
|
|
0 - UP
|
|
1 - DOWN
|
|
|
|
2 - CENTER
|
|
(any number above 2 is also CENTER for vertical, more chance for center)
|
|
*/
|
|
|
|
#ifdef _DEBUG
|
|
const char* hDirString[] = { "RIGHT", "LEFT", "CENTER" };
|
|
const char* vDirString[] = { "UP", "DOWN", "CENTER" };
|
|
|
|
if(horizontalDirection < 3)
|
|
std::cout << "HORIZONTAL DIRECTION: " << hDirString[horizontalDirection] << '\n';
|
|
else
|
|
std::cout << "HORIZONTAL DIRECTION: " << hDirString[2] << '\n';
|
|
|
|
if(verticalDirection < 3)
|
|
std::cout << "VERTICAL DIRECTION: " << vDirString[verticalDirection] << '\n';
|
|
else
|
|
std::cout << "VERTICAL DIRECTION: " << vDirString[2] << '\n';
|
|
#endif // _DEBUG
|
|
|
|
m_pTiles[start.y][start.x] = L'<';
|
|
do
|
|
{
|
|
x = 0;
|
|
y = 0;
|
|
|
|
if(utils::RandomBetween(0, 1) == 1)
|
|
{
|
|
x = utils::RandomBetween(-1, 1); // will sometimes be 0
|
|
if(x == 0)
|
|
{
|
|
switch(horizontalDirection)
|
|
{
|
|
case 0:
|
|
++x;
|
|
break;
|
|
case 1:
|
|
--x;
|
|
break;
|
|
case 2:
|
|
default:
|
|
if(utils::RandomBetween(0, 1) == 0)
|
|
++x;
|
|
else
|
|
--x;
|
|
break;
|
|
}
|
|
}
|
|
if(start.x + x < 1 || start.x + x >= G_MAP_WIDTH - 1)
|
|
{
|
|
/*start.x = SCREEN_WIDTH / 2;
|
|
start.y = SCREEN_HEIGHT / 2;*/
|
|
start = reset;
|
|
}
|
|
start.x += x;
|
|
}
|
|
else
|
|
{
|
|
y = utils::RandomBetween(-1, 1);
|
|
if(y == 0)
|
|
{
|
|
switch(verticalDirection)
|
|
{
|
|
case 0:
|
|
--y;
|
|
break;
|
|
case 1:
|
|
++y;
|
|
break;
|
|
case 2:
|
|
default:
|
|
if(utils::RandomBetween(0, 1) == 0)
|
|
++y;
|
|
else
|
|
--y;
|
|
break;
|
|
}
|
|
}
|
|
if(start.y + y < 1 || start.y + y >= G_MAP_HEIGHT - 1)
|
|
{
|
|
/*start.x = SCREEN_WIDTH / 2;
|
|
start.y = SCREEN_HEIGHT / 2;*/
|
|
start = reset;
|
|
}
|
|
start.y += y;
|
|
}
|
|
|
|
int tileStyle{};
|
|
if(m_pTiles[start.y][start.x] == G_MAPTILE_WALL)
|
|
{
|
|
tileStyle = utils::RandomBetween(0, 3);
|
|
wchar_t tile{};
|
|
switch(tileStyle)
|
|
{
|
|
case 0:
|
|
tile = L',';
|
|
break;
|
|
case 1:
|
|
tile = L'\'';
|
|
break;
|
|
case 2:
|
|
tile = L'`';
|
|
break;
|
|
case 3:
|
|
tile = L'.';
|
|
break;
|
|
}
|
|
m_pTiles[start.y][start.x] = tile;
|
|
--amountToGenerate;
|
|
/*if(amountToGenerate == 50 && position != Position{ -1, -1 })
|
|
{
|
|
m_Tiles[start.y][start.x] = L'<';
|
|
}
|
|
else*/ if(amountToGenerate == 250)
|
|
{
|
|
m_pTiles[start.y][start.x] = L'>';
|
|
m_DownStairsPos = start;
|
|
}
|
|
}
|
|
++amountGenerated;
|
|
}
|
|
while(amountToGenerate != 0 && amountGenerated < 20000);
|
|
|
|
#ifdef _DEBUG
|
|
t2 = std::chrono::steady_clock::now();
|
|
float elapsedSec{ std::chrono::duration<float>(t2 - t1).count() };
|
|
std::cout << "Time to generate: " << elapsedSec << '\n' << "Times called: " << amountGenerated << '\n';
|
|
#endif // _DEBUG
|
|
}
|
|
}
|
|
|
|
void Map::SaveMap()
|
|
{
|
|
std::wfstream file{ "resources/maps/" + m_MapName + ".level", std::ios::out | std::ios::trunc };
|
|
|
|
if(file.is_open())
|
|
{
|
|
std::cout << "Saving map as " << m_MapName << '\n';
|
|
for(int id{}; id < G_MAP_HEIGHT; ++id)
|
|
{
|
|
file << m_pTiles[id] << '\n';
|
|
}
|
|
}
|
|
else
|
|
std::wcerr << "\nCouldn't write to file\n";
|
|
}
|
|
|
|
void Map::Draw(const Position& playerPos) const
|
|
{
|
|
wchar_t tile;
|
|
// could change this so it doesn't draw parts of the map that can't even be seen
|
|
// ok did it
|
|
//Position onScreenPos{ playerPos.x + G_OFFSET_X, playerPos.y + G_OFFSET_Y }; // where the player actually is the screen
|
|
const int halfWidth{ G_SCREEN_WIDTH / 2 };
|
|
const int halfHeight{ G_SCREEN_HEIGHT / 2 }; // player is always at the center of the screen, so only need to remove half of it from playerPos
|
|
|
|
for(int y{}; y < G_SCREEN_HEIGHT - G_SCREEN_BOTTOM; ++y)
|
|
{
|
|
int yPos{ playerPos.y - halfHeight + y };
|
|
if(yPos >= G_MAP_HEIGHT || yPos < 0)
|
|
continue;
|
|
|
|
for(int x{}; x < G_SCREEN_WIDTH; ++x)
|
|
{
|
|
int xPos{ playerPos.x - halfWidth + x };
|
|
if(xPos >= G_MAP_WIDTH || xPos < 0)
|
|
continue;
|
|
|
|
tile = wchar_t(CheckTile(xPos, yPos));
|
|
|
|
terminal_color(G_COL_GRAY);
|
|
terminal_bkcolor(color_from_name("floor"));
|
|
|
|
if(G_CH_BITS[G_CH_CODES::FUNNYMODE])
|
|
{
|
|
terminal_color(utils::RandomColor());
|
|
}
|
|
else
|
|
{
|
|
switch(tile)
|
|
{
|
|
case G_MAPTILE_WALL:
|
|
terminal_color(color_from_name("walls"));
|
|
break;
|
|
case L'>':
|
|
case L'<':
|
|
terminal_color(G_COL_AMBER);
|
|
break;
|
|
}
|
|
}
|
|
|
|
terminal_put(xPos + G_OFFSET_X, yPos + G_OFFSET_Y, tile);
|
|
}
|
|
}
|
|
|
|
terminal_color(G_COL_WHITE);
|
|
terminal_bkcolor(G_COL_BLACK);
|
|
}
|
|
|
|
/*
|
|
int Map::GetId(int x, int y) const
|
|
{
|
|
return y * (MAP_WIDTH) + x;
|
|
}
|
|
*/
|
|
|
|
int Map::CheckTile(int x, int y) const
|
|
{
|
|
/*if(x >= G_MAP_WIDTH || x < 0 || y >= G_MAP_HEIGHT || y < 0)
|
|
return 0;
|
|
else*/
|
|
return m_pTiles[y][x];
|
|
}
|
|
|
|
int Map::CheckTile(const Position& pos) const
|
|
{
|
|
return m_pTiles[pos.y][pos.x];
|
|
}
|
|
|
|
std::string Map::GetName() const
|
|
{
|
|
return m_MapName;
|
|
}
|
|
|
|
bool Map::IsRoomLevel() const
|
|
{
|
|
return m_IsRooms;
|
|
}
|
|
|
|
// Creates randomly generated rooms with random amount
|
|
// Also checks if they intersect or appear out of the map, in which case it will be discarded and another one will be generated
|
|
void CreateMapRooms(std::vector<MapRoom>& rooms, int amount)
|
|
{
|
|
//int amountToGenerate{ utils::RandomBetween(10, 25) };
|
|
bool inWindow;
|
|
bool noOverlap;
|
|
bool isOk;
|
|
int width;
|
|
int height;
|
|
int x;
|
|
int y;
|
|
for(int index{}; index < amount; ++index)
|
|
{
|
|
// generate a room
|
|
do
|
|
{
|
|
inWindow = true;
|
|
noOverlap = true;
|
|
isOk = true;
|
|
width = utils::RandomBetween(4, 20);
|
|
height = utils::RandomBetween(4, 10);
|
|
x = utils::RandomBetween(3, G_MAP_WIDTH / 2 - width - 1);
|
|
y = utils::RandomBetween(3, G_MAP_HEIGHT / 2 - height - 1);
|
|
|
|
// check if overlaps
|
|
for(size_t id{}; id < rooms.size(); ++id)
|
|
{
|
|
if(rooms.size() < 1)
|
|
break;
|
|
|
|
noOverlap = !utils::IsOverlapping(x, y, width, height, rooms[id].x - 1, rooms[id].y - 1, rooms[id].width + 2, rooms[id].height + 2);
|
|
if(!noOverlap)
|
|
break;
|
|
}
|
|
|
|
// check if out of the window
|
|
if(x + width >= G_MAP_WIDTH || x < 0 || y + height >= G_MAP_HEIGHT || y < 0)
|
|
inWindow = false;
|
|
else
|
|
inWindow = true;
|
|
|
|
isOk = inWindow && noOverlap;
|
|
|
|
}
|
|
while(!isOk);
|
|
rooms.push_back(MapRoom{ x, y, width, height });
|
|
}
|
|
}
|
|
|
|
// From http://www.roguebasin.com/index.php?title=Bresenham%27s_Line_Algorithm
|
|
// and https://www.cs.helsinki.fi/group/goa/mallinnus/lines/bresenh.html
|
|
void Map::BresenhamMap(int x1, int y1, const int x2, const int y2)
|
|
{
|
|
int delta_x(x2 - x1);
|
|
// if x1 == x2, then it does not matter what we set here
|
|
const signed char ix((delta_x > 0) - (delta_x < 0));
|
|
delta_x = std::abs(delta_x) << 1;
|
|
|
|
int delta_y(y2 - y1);
|
|
// if y1 == y2, then it does not matter what we set here
|
|
const signed char iy((delta_y > 0) - (delta_y < 0));
|
|
delta_y = std::abs(delta_y) << 1;
|
|
|
|
//plot(x1, y1);
|
|
//std::cout << "\nx1: " << x1 << " y1: " << y1 << '\n';
|
|
//terminal_put(x1, y1, L'B');
|
|
if(m_pTiles[y1][x1] == G_MAPTILE_WALL)
|
|
m_pTiles[y1][x1] = G_MAPTILE_CORRIDOR;
|
|
//terminal_refresh();
|
|
|
|
if(delta_x >= delta_y)
|
|
{
|
|
// error may go below zero
|
|
int error(delta_y - (delta_x >> 1));
|
|
|
|
while(x1 != x2)
|
|
{
|
|
// reduce error, while taking into account the corner case of error == 0
|
|
if((error > 0) || (!error && (ix > 0)))
|
|
{
|
|
error -= delta_x;
|
|
y1 += iy;
|
|
}
|
|
// else do nothing
|
|
|
|
error += delta_y;
|
|
x1 += ix;
|
|
|
|
//plot(x1, y1);
|
|
//std::cout << "\nx1: " << x1 << " y1: " << y1 << '\n';
|
|
//terminal_put(x1 + G_OFFSET_X, y1 + G_OFFSET_Y, L'x');
|
|
if(m_pTiles[y1][x1] == G_MAPTILE_WALL)
|
|
m_pTiles[y1][x1] = G_MAPTILE_CORRIDOR;
|
|
//terminal_refresh();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// error may go below zero
|
|
int error(delta_x - (delta_y >> 1));
|
|
|
|
while(y1 != y2)
|
|
{
|
|
// reduce error, while taking into account the corner case of error == 0
|
|
if((error > 0) || (!error && (iy > 0)))
|
|
{
|
|
error -= delta_y;
|
|
x1 += ix;
|
|
}
|
|
// else do nothing
|
|
|
|
error += delta_x;
|
|
y1 += iy;
|
|
|
|
//plot(x1, y1);
|
|
//std::cout << "\nx1: " << x1 << " y1: " << y1 << '\n';
|
|
//terminal_put(x1 + G_OFFSET_X, y1 + G_OFFSET_Y, L'x');
|
|
//terminal_refresh();
|
|
if(m_pTiles[y1][x1] == G_MAPTILE_WALL)
|
|
m_pTiles[y1][x1] = G_MAPTILE_CORRIDOR;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// MapRoom struct stuff ///
|
|
MapRoom::MapRoom(int dx, int dy, int dwidth, int dheight)
|
|
: x{ dx }
|
|
, y{ dy }
|
|
, width{ dwidth }
|
|
, height{ dheight }
|
|
, amountDoors{ utils::RandomBetween(1, 4) }
|
|
, doors{ new MapDoor[amountDoors] }
|
|
{
|
|
//doors = new Position[amountDoors];
|
|
//std::wcout << "ROOM:\nx: " << std::to_wstring(x) << "\ny: " << std::to_wstring(y) << "\nwidth: " << std::to_wstring(width) << "\nheight: " << std::to_wstring(height);
|
|
//std::wcout << "\namount of doors: " << std::to_wstring(amountDoors) << '\n';
|
|
int doorPos{};
|
|
int tempPos{};
|
|
std::vector<int> positions{};
|
|
for(int i{}; i < amountDoors; ++i)
|
|
{
|
|
// this is to prevent multiple doors from being placed in the same spot
|
|
do
|
|
{
|
|
tempPos = utils::RandomBetween(0, 3);
|
|
}
|
|
while(std::find(positions.begin(), positions.end(), tempPos) != positions.end());
|
|
|
|
positions.push_back(tempPos);
|
|
doorPos = tempPos;
|
|
doors[i].direction = doorPos;
|
|
switch(doorPos)
|
|
{
|
|
// changing these to RandomBetweenSimple would barely speed up room level generation
|
|
case 0: // up
|
|
doors[i].pos.x = utils::RandomBetween(1, width - 2) + x;
|
|
doors[i].pos.y = y;
|
|
break;
|
|
case 1: // down
|
|
doors[i].pos.x = utils::RandomBetween(1, width - 2) + x;
|
|
doors[i].pos.y = y + height - 1;
|
|
break;
|
|
case 2: // left
|
|
doors[i].pos.x = x;
|
|
doors[i].pos.y = utils::RandomBetween(1, height - 2) + y;
|
|
break;
|
|
case 3: // right
|
|
doors[i].pos.x = x + width - 1;
|
|
doors[i].pos.y = utils::RandomBetween(1, height - 2) + y;
|
|
break;
|
|
}
|
|
}
|
|
positions.clear();
|
|
}
|
|
|
|
MapRoom::MapRoom(MapRoom&& other) noexcept
|
|
: x{ other.x }
|
|
, y{ other.y }
|
|
, width{ other.width }
|
|
, height{ other.height }
|
|
, amountDoors{ other.amountDoors }
|
|
, doors{ other.doors }
|
|
{
|
|
other.doors = nullptr;
|
|
}
|
|
|
|
MapRoom::~MapRoom()
|
|
{
|
|
delete[] doors;
|
|
}
|