3 #include "rapidjson/document.h"
4 #include "rapidjson/prettywriter.h"
9 #include "RehtiUtils.hpp"
30 rapidjson::Document doc = readJson(Config.AREA_MAP_PATH);
34 throw std::runtime_error(
"JSON is not an array");
37 std::vector<std::vector<std::string>> areaMap;
39 for (rapidjson::SizeType i = 0; i < doc.Size(); ++i)
41 if (!doc[i].IsArray())
43 throw std::runtime_error(
"Inner structure is not an array");
46 std::vector<std::string> areaRow;
47 for (rapidjson::SizeType j = 0; j < doc[i].Size(); ++j)
49 if (!doc[i][j].IsString())
51 throw std::runtime_error(
"Element is not a string");
54 areaRow.push_back(doc[i][j].GetString());
56 areaMap.push_back(areaRow);
77 static void loadHeightAndTextureMap(
const std::vector<std::vector<std::string>>& areaMap, std::vector<std::vector<int>>& heightMap, std::vector<std::vector<int>>& textureMap)
80 populateMatrix(heightMap, areaMap, 0, Config.AREA_WIDTH, Config.AREA_HEIGHT);
81 populateMatrix(textureMap, areaMap, 0, Config.AREA_WIDTH, Config.AREA_HEIGHT);
84 for (
unsigned currentAreaRowIndex = 0; currentAreaRowIndex < areaMap.size(); currentAreaRowIndex++)
86 std::vector<std::string> areaRow = areaMap[currentAreaRowIndex];
89 for (
unsigned currentAreaColumnIndex = 0; currentAreaColumnIndex < areaRow.size(); currentAreaColumnIndex++)
91 const std::string& area = areaRow[currentAreaColumnIndex];
92 std::string areaFile = Config.AREA_FILES_PATH + area +
".png";
93 std::vector<unsigned char> image;
94 unsigned width, height;
95 readPng(image, width, height, areaFile);
96 if (width != Config.AREA_WIDTH || height != Config.AREA_HEIGHT)
98 throw std::invalid_argument(
"Image size is not " + std::to_string(Config.AREA_WIDTH) +
"x" + std::to_string(Config.AREA_HEIGHT));
101 for (
unsigned i = 0; i < height; ++i)
103 const unsigned indexY = currentAreaRowIndex * Config.AREA_HEIGHT + i;
104 for (
unsigned j = 0; j < width; ++j)
106 unsigned pixelIndex = (i * width + j) * 4;
107 unsigned char r = image[pixelIndex + 0];
108 unsigned char g = image[pixelIndex + 1];
109 unsigned char b = image[pixelIndex + 2];
112 int height = (g & 0x7F) * b;
118 const unsigned indexX = currentAreaColumnIndex * Config.AREA_WIDTH + j;
119 textureMap[indexY][indexX] = r;
120 heightMap[indexY][indexX] = height;
140 static void insertObjectTileMap(std::vector<std::vector<std::string>>& objectBlockMap, std::vector<std::vector<std::string>>& objectTileMap,
unsigned areaY,
unsigned areaX,
unsigned currentAreaRowIndex,
unsigned currentAreaColumnIndex)
143 unsigned centerX, centerY;
144 unsigned centerXMap, centerYMap;
145 bool shouldBreak =
false;
146 for (
unsigned i = 0; i < objectTileMap.size(); i++)
148 for (
unsigned j = 0; j < objectTileMap[i].size(); j++)
156 centerXMap = currentAreaColumnIndex * Config.AREA_WIDTH + areaX + j;
157 centerYMap = currentAreaRowIndex * Config.AREA_HEIGHT + areaY + i;
170 for (
unsigned i = 0; i < objectTileMap.size(); i++)
172 for (
unsigned j = 0; j < objectTileMap[i].size(); j++)
174 const int xDiff = j - centerX;
175 const int yDiff = i - centerY;
176 const int x = centerXMap + xDiff;
177 const int y = centerYMap + yDiff;
180 if (x < 0 || x >= objectBlockMap[0].size() || y < 0 || y >= objectBlockMap.size())
182 throw std::out_of_range(
"Object out of bounds");
185 objectBlockMap[y][x] = objectTileMap[i][j];
204 for (
unsigned i = 0; i < objectTileMap.size(); i++)
206 for (
unsigned j = 0; j < objectTileMap[i].size(); j++)
208 for (
unsigned k = 0; k < symbols.size(); k++)
210 const auto index = objectTileMap[i][j].find(symbols[k]);
211 if (index != std::string::npos)
213 const unsigned newSymbolIndex = (k + rotation) % symbols.size();
214 objectTileMap[i][j].replace(index, symbols[k].size(), symbols[newSymbolIndex]);
240 static const std::vector<std::vector<std::string>>
createObjectBlockMap(
const std::vector<std::vector<std::string>>& areaMap,
GameObjects gameObjects,
const std::vector<std::vector<int>>& heightMap)
243 std::vector<std::vector<std::string>> objectBlockMap;
246 std::vector<ObjectLocation> objectsLocations;
248 for (
unsigned currentAreaRowIndex = 0; currentAreaRowIndex < areaMap.size(); currentAreaRowIndex++)
250 const std::vector<std::string> areaRow = areaMap[currentAreaRowIndex];
251 for (
unsigned currentAreaColumnIndex = 0; currentAreaColumnIndex < areaRow.size(); currentAreaColumnIndex++)
253 const std::string& area = areaRow[currentAreaColumnIndex];
255 std::vector<unsigned char> image;
256 unsigned width, height;
257 std::string filepath = Config.AREA_FILES_PATH + area +
"-obj.png";
258 readPng(image, width, height, filepath);
259 if (width != Config.AREA_WIDTH || height != Config.AREA_HEIGHT)
261 throw std::invalid_argument(
"Image size is not " + std::to_string(Config.AREA_WIDTH) +
"x" + std::to_string(Config.AREA_HEIGHT));
265 for (
unsigned i = 0; i < height; ++i)
267 for (
unsigned j = 0; j < width; ++j)
269 unsigned pixelIndex = (i * width + j) * 4;
270 unsigned r = image[pixelIndex + 0];
271 unsigned g = image[pixelIndex + 1];
272 unsigned b = image[pixelIndex + 2];
274 unsigned objectId = r * g;
283 unsigned rotation = b > 3 ? 0 : b;
285 std::vector<std::vector<std::string>> objectTileMap = gameObjects.
getTileMap(objectId);
287 if (objectTileMap.empty())
289 throw std::runtime_error(
"Object tile map not found for id: " + std::to_string(objectId));
292 std::cout <<
"Object id: " << objectId <<
" read " << std::endl;
299 std::cout <<
"Object id: " << objectId <<
" rotated " << std::endl;
303 std::cout <<
"Object id: " << objectId <<
" not rotated " << std::endl;
306 int x = currentAreaColumnIndex * Config.AREA_WIDTH + j;
307 int y = currentAreaRowIndex * Config.AREA_HEIGHT + i;
308 int z = heightMap[y][x];
311 objectsLocations.push_back(objLoc);
313 insertObjectTileMap(objectBlockMap, objectTileMap, i, j, currentAreaRowIndex, currentAreaColumnIndex);
314 std::cout <<
"Object id: " << objectId <<
" inserted " << std::endl;
322 rapidjson::Document doc;
324 rapidjson::Value objects(rapidjson::kArrayType);
325 for (
const auto& objLoc : objectsLocations)
327 rapidjson::Value object(rapidjson::kObjectType);
328 object.AddMember(
"id", objLoc.id, doc.GetAllocator());
329 object.AddMember(
"x", objLoc.x, doc.GetAllocator());
330 object.AddMember(
"y", objLoc.y, doc.GetAllocator());
331 object.AddMember(
"z", objLoc.z, doc.GetAllocator());
332 object.AddMember(
"rotation", objLoc.rotation, doc.GetAllocator());
333 objects.PushBack(
object, doc.GetAllocator());
335 doc.AddMember(
"objects", objects, doc.GetAllocator());
337 const std::string str = createString(doc);
339 std::ofstream objectsFile(Config.GENERATED_OBJECT_JSON_PATH);
343 return objectBlockMap;
368 static const std::vector<std::vector<unsigned>>
generateAccessMap(
const std::vector<std::vector<int>>& heightMap,
const std::vector<std::vector<std::string>>& objectBlockMap)
370 std::vector<std::vector<unsigned>> accessMap;
373 const unsigned defaultValue = 0b1111;
376 for (
int i = 0; i < heightMap.size(); i++)
378 for (
int j = 0; j < heightMap[i].size(); j++)
380 int height = heightMap[i][j];
381 unsigned& access = accessMap[i][j];
384 if (i <= 0 || heightMap[i - 1].size() <= j || std::abs(height - heightMap[i - 1][j]) > Config.MAX_PASSABLE_HEIGHT || objectBlockMap[i][j].find(
"N") != std::string::npos)
387 access = access & 0b1110;
391 if (heightMap[i].size() <= j + 1 || std::abs(height - heightMap[i][j + 1]) > Config.MAX_PASSABLE_HEIGHT || objectBlockMap[i][j].find(
"E") != std::string::npos)
394 access = access & 0b1101;
398 if (heightMap.size() <= i + 1 || heightMap[i + 1].size() <= j || std::abs(height - heightMap[i + 1][j]) > Config.MAX_PASSABLE_HEIGHT || objectBlockMap[i][j].find(
"S") != std::string::npos)
401 access = access & 0b1011;
405 if (j <= 0 || std::abs(height - heightMap[i][j - 1]) > Config.MAX_PASSABLE_HEIGHT || objectBlockMap[i][j].find(
"W") != std::string::npos)
408 access = access & 0b0111;
412 if (objectBlockMap[i][j].find(
"B") != std::string::npos)
const std::string OBJECT_TILE_MAP_EAST_BLOCK
Definition: MapLoader.hpp:15
const std::string OBJECT_TILE_MAP_NO_BLOCK
Definition: MapLoader.hpp:19
const unsigned NON_OBJECT_ID
Definition: MapLoader.hpp:21
static const std::vector< std::vector< std::string > > fetchAreaMap()
Fetches the area map from the JSON file. Throws an exception if the file corrupted.
Definition: MapLoader.hpp:28
const std::string OBJECT_TILE_MAP_SOUTH_BLOCK
Definition: MapLoader.hpp:16
static void loadHeightAndTextureMap(const std::vector< std::vector< std::string >> &areaMap, std::vector< std::vector< int >> &heightMap, std::vector< std::vector< int >> &textureMap)
Loads a height map and map's texture map into given parameters. Loads them together to avoid reading ...
Definition: MapLoader.hpp:77
static const std::vector< std::vector< unsigned > > generateAccessMap(const std::vector< std::vector< int >> &heightMap, const std::vector< std::vector< std::string >> &objectBlockMap)
Generates access map from height map & object block map. Access map defines how tiles can or cannot b...
Definition: MapLoader.hpp:368
const std::string OBJECT_TILE_MAP_NORTH_BLOCK
Definition: MapLoader.hpp:14
const std::string OBJECT_TILE_MAP_WEST_BLOCK
Definition: MapLoader.hpp:17
static void changeBlockDirection(std::vector< std::vector< std::string >> &objectTileMap, unsigned rotation)
When object tile map is rotated, its direction needs to be rotated as well.
Definition: MapLoader.hpp:200
static const std::vector< std::vector< std::string > > createObjectBlockMap(const std::vector< std::vector< std::string >> &areaMap, GameObjects gameObjects, const std::vector< std::vector< int >> &heightMap)
Generate the object block map. The map defines how the objects block the tiles around itself.
Definition: MapLoader.hpp:240
static void insertObjectTileMap(std::vector< std::vector< std::string >> &objectBlockMap, std::vector< std::vector< std::string >> &objectTileMap, unsigned areaY, unsigned areaX, unsigned currentAreaRowIndex, unsigned currentAreaColumnIndex)
Inserts the object tile map to the map.
Definition: MapLoader.hpp:140
const std::string OBJECT_TILE_MAP_CENTER
Definition: MapLoader.hpp:13
const std::string OBJECT_TILE_MAP_FULL_BLOCK
Definition: MapLoader.hpp:18
std::string generateObjectInstanceId(ObjectLocation objectLocation)
Generates a unique id for an object instance.
Definition: ObjectReader.cpp:16
void rotateMatrix(std::vector< std::vector< T >> &matrix, uint8_t rotation)
Rotates the matrix 90 degrees counter-clockwise. Rotation is calculated by rotation-param * 90 degree...
Definition: rehtiLib/assets/loader/src/Utils.hpp:61
void readPng(std::vector< unsigned char > &image, unsigned &width, unsigned &height, std::string filepath)
Reads a PNG file and returns the image data, width and height.
Definition: rehtiLib/assets/loader/src/Utils.hpp:42
void populateMatrixFromReference(std::vector< std::vector< T >> &matrix, const std::vector< std::vector< K >> &referenceMatrix, T defaultValue)
Populates a matrix from a reference matrix. Uses a default value for empty cells. Reference matrix is...
Definition: rehtiLib/assets/loader/src/Utils.hpp:116
void populateMatrix(std::vector< std::vector< T >> &matrix, const std::vector< std::vector< std::string >> &areaMap, T defaultValue, unsigned AREA_WIDTH, unsigned AREA_HEIGHT)
Populates a matrix with a default value. The matrix is all the areas combined and expanded e....
Definition: rehtiLib/assets/loader/src/Utils.hpp:96
Contains all the objects defined in the objects.json file.
Definition: ObjectReader.hpp:101
std::vector< std::vector< std::string > > getTileMap(int id)
Definition: ObjectReader.hpp:133
Describes the location of an object on the map. This is used to spawn object instances on the map.
Definition: ObjectReader.hpp:17
std::string instanceId
Definition: ObjectReader.hpp:19