Implement a very simple map file format for further testing

This commit is contained in:
Matthias Schiffer 2014-09-26 04:12:27 +02:00
parent 124116a8bf
commit 144d620192
5 changed files with 170 additions and 20 deletions

View file

@ -26,6 +26,10 @@
#include "Map.hpp"
#include <cstdio>
#include <cstdlib>
#include <fstream>
namespace RPGEdit {
@ -85,32 +89,74 @@ void Map::finishEntityTransition(Entity *entity) {
}
std::unique_ptr<Map> Map::load(__attribute__((unused)) const std::string &name) {
std::unique_ptr<Map> map(new Map(16, 16, 2));
std::string filename = "../resources/map/" + name + ".map";
map->tileset.emplace_back("dirt", 0);
map->tileset.emplace_back("horizontal_bar", 0);
map->tileset.emplace_back("horizontal_bar", 2);
std::ifstream file;
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
if (4 <= i && i < 12 && 4 <= j && j < 12) {
map->setTileAt(0, Position<int>{i, j}, 1);
map->setCollisionAt(Position<int>{i, j}, CollisionType::EMPTY);
}
else {
map->setTileAt(0, Position<int>{i, j}, 0);
}
file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
file.open(filename.c_str());
if (4 <= i && i < 12 && j == 7)
map->setTileAt(1, Position<int>{i, j}, 3);
else if (4 <= i && i < 12 && j == 8)
map->setTileAt(1, Position<int>{i, j}, 2);
else
map->setTileAt(1, Position<int>{i, j}, 0);
std::string line;
std::getline(file, line);
size_t w, h, layers;
if (std::sscanf(line.c_str(), "%zu %zu %zu", &w, &h, &layers) != 3)
throw std::invalid_argument("invalid map file");
std::unique_ptr<Map> map(new Map(w, h, layers));
std::getline(file, line);
if (line.length())
throw std::invalid_argument("invalid map file");
size_t n = 1;
std::unordered_map<char, size_t> tileset;
for (std::getline(file, line); line.length(); std::getline(file, line)) {
char c;
unsigned rot;
char *tile = nullptr;
if (std::sscanf(line.c_str(), "%c %u %ms", &c, &rot, &tile) != 3) {
std::free(tile);
throw std::invalid_argument("invalid map file");
}
tileset.emplace(c, n++);
map->tileset.emplace_back(tile, rot);
std::free(tile);
}
for (size_t i = 0; i < h; i++) {
std::getline(file, line);
if (line.length() != w)
throw std::invalid_argument("invalid map file");
for (size_t j = 0; j < w; j++) {
if (line[j] == '1')
map->setCollisionAt(Position<int>{int(j), int(i)}, CollisionType::EMPTY);
else if (line[j] != '0')
throw std::invalid_argument("invalid map file");
}
}
map->addEntity("square", Model::Position<int>{6, 6});
for (size_t layer = 0; layer < layers; layer++) {
std::getline(file, line);
if (line.length())
throw std::invalid_argument("invalid map file");
for (size_t i = 0; i < h; i++) {
std::getline(file, line);
if (line.length() != w)
throw std::invalid_argument("invalid map file");
for (size_t j = 0; j < w; j++) {
auto it = tileset.find(line[j]);
if (it != tileset.end())
map->setTileAt(layer, Position<int>{int(j), int(i)}, it->second);
}
}
}
return map;
}