Skip to content
Snippets Groups Projects
Commit b06d1321 authored by TheUltimateOptimist's avatar TheUltimateOptimist
Browse files

started integrating placement changes

parent 0cb5903b
No related branches found
No related tags found
No related merge requests found
...@@ -12,9 +12,11 @@ ...@@ -12,9 +12,11 @@
#include <QPoint> #include <QPoint>
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp> #include <boost/property_tree/xml_parser.hpp>
#include <vector>
#include "highfive/H5File.hpp" #include "highfive/H5File.hpp"
#include "SpriteProvider.hpp" #include "SpriteProvider.hpp"
#include <cstdint>
namespace editor namespace editor
{ {
...@@ -23,7 +25,7 @@ LevelScene::LevelScene( ...@@ -23,7 +25,7 @@ LevelScene::LevelScene(
const std::string& name, int width, int height, std::vector<uint8_t> tile_ids, const std::string& name, int width, int height, std::vector<uint8_t> tile_ids,
const std::string& file_path, QWidget* parent) const std::string& file_path, QWidget* parent)
: QGraphicsScene(parent), m_name(name), m_width(width), m_height(height), m_tile_ids(tile_ids), : QGraphicsScene(parent), m_name(name), m_width(width), m_height(height), m_tile_ids(tile_ids),
m_file_path(file_path), m_selected_tile_id(2) m_file_path(file_path), m_apply_advanced_placement(false), m_selected_tile_id(2)
{ {
setSceneRect(0, 0, m_width * 16, m_height * 16); setSceneRect(0, 0, m_width * 16, m_height * 16);
m_tile_occupants = {}; m_tile_occupants = {};
...@@ -138,6 +140,200 @@ bool LevelScene::is_water_tile(uint8_t id) ...@@ -138,6 +140,200 @@ bool LevelScene::is_water_tile(uint8_t id)
return false; return false;
} }
std::vector<std::pair<int, uint8_t>> LevelScene::getAdvancedPlacementChanges(int index, uint8_t placedID)
{
std::vector<std::pair<int, uint8_t>> output;
if(placedID > 5 && placedID < 17){ //Straße plaziert
placeRoad(output, index, true);
return output;
}
if((placedID > 16 && placedID < 30) || placedID == 1){ //Wasser plaziert
if(placedID == 17){
output.push_back(std::pair<int, uint8_t>(index, 17));
} else {
output.push_back(std::pair<int, uint8_t>(index, 1));
}
placeCliff(output, false, index);
return output;
}
if(placedID == 0 || placedID == 2 || placedID == 3){ //Land plaziert
output.push_back(std::pair<int, uint8_t>(index, placedID));
placeCliff(output, true, index);
return output;
}
output.push_back(std::pair<int, uint8_t>(index, placedID)); //Gebäude plaziert
return output;
}
void LevelScene::placeCliff(std::vector<std::pair<int, uint8_t>> &output, bool placedLand, int index)
{
const int16_t IdToSum[12] = {12,3,9,6,2,1,4,8,13,14,11,7};
const int16_t SumToId[16] = {1,23,22,19,24,24,21,29,25,20,25,28,18,26,27,0};
int16_t surroundingIDs[8] = {-2,-2,-2,-2,-2,-2,-2,-2}; //-2 = uninitialisiert, -1 = kartenrand
bool marchingSquares[8][4] = {false};
//Überprüfe Kartenränder, setze diese auf -1
if(index < m_width){ //oberer Kartenrand
surroundingIDs[7] = -1;
surroundingIDs[0] = -1;
surroundingIDs[1] = -1;
}
if((index + 1) % m_width == 0){ //rechter Kartenrand
surroundingIDs[1] = -1;
surroundingIDs[2] = -1;
surroundingIDs[3] = -1;
}
if(index > m_width * (m_height - 1)){ //unterer Kartenrand
surroundingIDs[3] = -1;
surroundingIDs[4] = -1;
surroundingIDs[5] = -1;
}
if(index % m_width == 0){ //linker Kartenrand
surroundingIDs[5] = -1;
surroundingIDs[6] = -1;
surroundingIDs[7] = -1;
}
//Erhalte IDs von den umliegenden 8 Feldern, die kein Kartenrand sind
//startet in der mitte Oben, gehe im Uhrzeigersinn
if(surroundingIDs[0] == -2) surroundingIDs[0] = (int16_t) m_tile_ids[index - m_width];
if(surroundingIDs[1] == -2) surroundingIDs[1] = (int16_t) m_tile_ids[index - m_width + 1];
if(surroundingIDs[2] == -2) surroundingIDs[2] = (int16_t) m_tile_ids[index + 1];
if(surroundingIDs[3] == -2) surroundingIDs[3] = (int16_t) m_tile_ids[index + m_width + 1];
if(surroundingIDs[4] == -2) surroundingIDs[4] = (int16_t) m_tile_ids[index + m_width];
if(surroundingIDs[5] == -2) surroundingIDs[5] = (int16_t) m_tile_ids[index + m_width - 1];
if(surroundingIDs[6] == -2) surroundingIDs[6] = (int16_t) m_tile_ids[index - 1];
if(surroundingIDs[7] == -2) surroundingIDs[7] = (int16_t) m_tile_ids[index - m_width - 1];
//Ids können nicht lesbare Tiles enthalten, diese Herausfiltern
for(int i = 0; i < 8; i++){
if(surroundingIDs[i] == 17) surroundingIDs[i] = 1; //Riff als Wasser angesehen
if(surroundingIDs[i] == 2 || surroundingIDs[i] == 3) surroundingIDs[i] = 0; //Wald, Gebirge als Land angesehen
if(surroundingIDs[i] > 3 && surroundingIDs[i] < 17) surroundingIDs[i] = -1; //Straßen werden nicht verändert
if(surroundingIDs[i] > 29) surroundingIDs[i] = 0; //Gebäude werden als Land angesehen
}
//ID remapping um damit arbeiten zu können
for(int i = 0; i < 8; i++){
if(surroundingIDs[i] == 0){
surroundingIDs[i] = 15;
} else if(surroundingIDs[i] == 1){
surroundingIDs[i] = 0;
} else{
surroundingIDs[i]= IdToSum[surroundingIDs[i] - 18];
}
}
//Berechne Marching Squares aus der remapped Id
for(int i = 0; i < 8; i++){
if(surroundingIDs[i] / 8 == 1){
marchingSquares[i][0] = true; //top left
surroundingIDs[i] -= 8;
}
if(surroundingIDs[i] / 4 == 1){
marchingSquares[i][1] = true; //top right
surroundingIDs[i] -= 4;
}
if(surroundingIDs[i] / 2 == 1){
marchingSquares[i][2] = true; //bottom right
surroundingIDs[i] -= 2;
}
if(surroundingIDs[i] == 1){
marchingSquares[i][3] = true; //bottom left
}
}
//Einfügen/Abziehen des Landes
marchingSquares[0][2] = placedLand; //oben
marchingSquares[0][3] = placedLand;
marchingSquares[1][3] = placedLand; //oben rechts
marchingSquares[2][3] = placedLand; //rechts
marchingSquares[2][0] = placedLand;
marchingSquares[3][0] = placedLand; //untern rechts
marchingSquares[4][0] = placedLand; //unten
marchingSquares[4][1] = placedLand;
marchingSquares[5][1] = placedLand; //unten links
marchingSquares[6][1] = placedLand; //links
marchingSquares[6][2] = placedLand;
marchingSquares[7][2] = placedLand; //oben links
//Berechne remapped ID aus Marching Squares
for(int i = 0; i < 8; i++){
surroundingIDs[i] = 0;
if(marchingSquares[i][0]) surroundingIDs[i] += 8;
if(marchingSquares[i][1]) surroundingIDs[i] += 4;
if(marchingSquares[i][2]) surroundingIDs[i] += 2;
if(marchingSquares[i][3]) surroundingIDs[i] += 1;
}
//Remappe ID für setzbare Tiles
for(int i = 0; i < 8; i++){
surroundingIDs[i] = SumToId[ surroundingIDs[i] ];
}
//Plaziere Tiles
if(surroundingIDs[0] != -1) output.push_back( std::pair( index - m_width ,(uint8_t)surroundingIDs[0] ));
if(surroundingIDs[1] != -1) output.push_back( std::pair( index - m_width + 1 ,(uint8_t)surroundingIDs[1] ));
if(surroundingIDs[2] != -1) output.push_back( std::pair( index + 1 ,(uint8_t)surroundingIDs[2] ));
if(surroundingIDs[3] != -1) output.push_back( std::pair( index + m_width + 1 ,(uint8_t)surroundingIDs[3] ));
if(surroundingIDs[4] != -1) output.push_back( std::pair( index + m_width ,(uint8_t)surroundingIDs[4] ));
if(surroundingIDs[5] != -1) output.push_back( std::pair( index + m_width - 1 ,(uint8_t)surroundingIDs[5] ));
if(surroundingIDs[6] != -1) output.push_back( std::pair( index - 1 ,(uint8_t)surroundingIDs[6] ));
if(surroundingIDs[7] != -1) output.push_back( std::pair( index - m_width - 1 ,(uint8_t)surroundingIDs[7] ));
}
void LevelScene::placeRoad(std::vector<std::pair<int, uint8_t>> &output, int index, bool updateFlag)
{
const int16_t IdToSum[] = {5,10,13,14,11,7,15,6,3,12,9};
const uint8_t SumToId[] = {6,6,7,14,6,6,13,11,7,16,7,10,15,8,9,12};
bool tileDirections[] = {false,false,false,false};
int16_t surroundingIDs[] = {-1,-1,-1,-1}; //-1 = kartenrand oder keine strasse
uint8_t placedID = 0;
//Erhalte IDs der umliegenden Felder - im Uhrzeigersinn, start: oben
//Vorgehen: überprüfe, ob die obere Zelle im Kartenrand ist. Wenn nicht erhalte index der oberen Zelle
if(!(index < m_width)) surroundingIDs[0] = (int16_t) m_tile_ids[index - m_width];
if(!((index + 1) % m_width == 0)) surroundingIDs[1] = (int16_t) m_tile_ids[index + 1];
if(!(index > m_width * (m_height-1))) surroundingIDs[2] = (int16_t) m_tile_ids[index + m_width];
if(!(index % m_width == 0)) surroundingIDs[3] = (int16_t) m_tile_ids[index - 1];
//Umformen der IDs oder ID ist keine Straße
for(int i = 0; i < 4; i++){
if(surroundingIDs[i] < 6 || surroundingIDs[i] > 16){
surroundingIDs[i] = -1; //ID ist keine Strasse
} else {
surroundingIDs[i] = IdToSum[ surroundingIDs[i] - 6]; //id remapping
}
}
//Berechne in welche Richtungen das neue Tile Zeigt
for(int i = 0; i < 4; i++){
if(surroundingIDs[i] > -1) tileDirections[i] = true;
}
//Berechne die Remapped ID
placedID = 0;
if(tileDirections[0]) placedID += 8;
if(tileDirections[1]) placedID += 4;
if(tileDirections[2]) placedID += 2;
if(tileDirections[3]) placedID += 1;
if(placedID == 0) updateFlag = false; //Umliegende Tiles müssen nicht geupdated werden, da keine Strassen
placedID = SumToId[placedID]; //Berechnete Summe in Valide ID umformen
output.push_back(std::pair(index, placedID)); //Tile setzen
//Update umliegende Tiles
if(updateFlag){
if(tileDirections[0]) placeRoad(output, (index - m_width), false); //update oben
if(tileDirections[1]) placeRoad(output, (index + 1), false); //update rechts
if(tileDirections[2]) placeRoad(output, (index + m_width), false); //update unten
if(tileDirections[3]) placeRoad(output, (index - 1), false); //update links
}
}
void LevelScene::onLevelNameUpdated(std::string new_name) void LevelScene::onLevelNameUpdated(std::string new_name)
{ {
m_name = new_name; m_name = new_name;
...@@ -185,6 +381,18 @@ void LevelScene::onTileEntered(int index) ...@@ -185,6 +381,18 @@ void LevelScene::onTileEntered(int index)
{ {
m_tile_occupants[index] = occupy_tile(index, m_selected_tile_id); m_tile_occupants[index] = occupy_tile(index, m_selected_tile_id);
} }
if (m_apply_advanced_placement) {
std::vector<std::pair<int, uint8_t>> changes = getAdvancedPlacementChanges(index, m_tile_ids[index]);
for (const auto& change : changes)
{
if (m_tile_occupants[change.first] != nullptr) {
removeItem(m_tile_occupants[change.first]);
delete m_tile_occupants[change.first];
m_tile_occupants[change.first] = nullptr;
}
m_tile_occupants[change.first] = occupy_tile(change.first, change.second);
}
}
} }
void LevelScene::onTileExited(int index) void LevelScene::onTileExited(int index)
...@@ -203,6 +411,18 @@ void LevelScene::onTileExited(int index) ...@@ -203,6 +411,18 @@ void LevelScene::onTileExited(int index)
{ {
m_tile_occupants[index] = occupy_tile(index, m_tile_ids[index]); m_tile_occupants[index] = occupy_tile(index, m_tile_ids[index]);
} }
if (m_apply_advanced_placement) {
std::vector<std::pair<int, uint8_t>> changes = getAdvancedPlacementChanges(index, m_tile_ids[index]);
for (const auto& change : changes)
{
if (m_tile_occupants[change.first] != nullptr) {
removeItem(m_tile_occupants[change.first]);
delete m_tile_occupants[change.first];
m_tile_occupants[change.first] = nullptr;
}
m_tile_occupants[change.first] = occupy_tile(change.first, change.second);
}
}
} }
void LevelScene::onTileClicked(int index) void LevelScene::onTileClicked(int index)
......
...@@ -30,6 +30,9 @@ public: ...@@ -30,6 +30,9 @@ public:
private: private:
bool is_border(int index); bool is_border(int index);
bool is_water_tile(uint8_t id); bool is_water_tile(uint8_t id);
std::vector<std::pair<int, uint8_t>> getAdvancedPlacementChanges(int index, uint8_t placedID);
void placeCliff(std::vector<std::pair<int, uint8_t>> &output, bool placedLand, int index);
void placeRoad(std::vector<std::pair<int, uint8_t>> &output, int index, bool updateFlag);
void onLevelNameUpdated(std::string new_name) override; void onLevelNameUpdated(std::string new_name) override;
void onLevelWriteRequested(QString file_path) override; void onLevelWriteRequested(QString file_path) override;
void onTileEntered(int index) override; void onTileEntered(int index) override;
...@@ -37,6 +40,7 @@ private: ...@@ -37,6 +40,7 @@ private:
void onTileClicked(int index) override; void onTileClicked(int index) override;
void onNewTileIdSelected(uint8_t tile_id) override; void onNewTileIdSelected(uint8_t tile_id) override;
QGraphicsPixmapItem* occupy_tile(int index, uint8_t tile_id); QGraphicsPixmapItem* occupy_tile(int index, uint8_t tile_id);
bool m_apply_advanced_placement;
uint8_t m_selected_tile_id; uint8_t m_selected_tile_id;
std::string m_name; std::string m_name;
int m_width; int m_width;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment