Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/game/StarDungeonImagePart.cpp
blob: 86b388741edc312611656950265d1a70fc20d1aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include "StarRoot.hpp"
#include "StarAssets.hpp"
#include "StarCasting.hpp"
#include "StarImage.hpp"
#include "StarJsonExtra.hpp"
#include "StarDungeonImagePart.hpp"

namespace Star {

namespace Dungeon {

  void ImagePartReader::readAsset(String const& asset) {
    auto assets = Root::singleton().assets();
    m_images.push_back(make_pair(asset, assets->image(asset)));
  }

  Vec2U ImagePartReader::size() const {
    if (m_images.empty())
      return Vec2U{0, 0};
    return m_images[0].second->size();
  }

  void ImagePartReader::forEachTile(TileCallback const& callback) const {
    for (auto const& entry : m_images) {
      String const& file = entry.first;
      ImageConstPtr const& image = entry.second;
      for (size_t y = 0; y < image->height(); y++) {
        for (size_t x = 0; x < image->width(); x++) {

          Vec2I position(x, y);
          Vec4B tileColor = image->get(x, y);

          if (auto const& tile = m_tileset->getTile(tileColor)) {
            bool exitEarly = callback(position, *tile);
            if (exitEarly)
              return;
          } else {
            throw StarException::format("Dungeon image {} uses unknown tile color: #{:02x}{:02x}{:02x}{:02x}",
                file,
                tileColor[0],
                tileColor[1],
                tileColor[2],
                tileColor[3]);
          }
        }
      }
    }
  }

  void ImagePartReader::forEachTileAt(Vec2I pos, TileCallback const& callback) const {
    for (auto const& entry : m_images) {
      String const& file = entry.first;
      ImageConstPtr const& image = entry.second;
      Vec4B tileColor = image->get(pos.x(), pos.y());

      if (auto const& tile = m_tileset->getTile(tileColor)) {
        bool exitEarly = callback(pos, *tile);
        if (exitEarly)
          return;
      } else {
        throw StarException::format("Dungeon image {} uses unknown tile color: #{:02x}{:02x}{:02x}{:02x}",
            file,
            tileColor[0],
            tileColor[1],
            tileColor[2],
            tileColor[3]);
      }
    }
  }

  String connectorColorValue(Vec4B const& color) {
    return strf("{},{},{},{}", color[0], color[1], color[2], color[3]);
  }

  Tile variantMapToTile(JsonObject const& tile) {
    Tile result;
    if (tile.contains("brush"))
      result.brushes = Brush::readBrushes(tile.get("brush"));
    if (tile.contains("rules"))
      result.rules = Rule::readRules(tile.get("rules"));

    if (tile.contains("connector") && tile.get("connector").toBool()) {
      auto connector = TileConnector();

      connector.forwardOnly = tile.contains("connectForwardOnly") && tile.get("connectForwardOnly").toBool();

      Json connectorValue = tile.get("value");
      if (Maybe<Json> value = tile.maybe("connector-value"))
        connectorValue = value.take();

      if (connectorValue.isType(Json::Type::String))
        connector.value = connectorValue.toString();
      else
        connector.value = connectorColorValue(jsonToVec4B(connectorValue));

      if (tile.contains("direction"))
        connector.direction = DungeonDirectionNames.getLeft(tile.get("direction").toString());

      result.connector = connector;
    }

    return result;
  }

  ImageTileset::ImageTileset(Json const& tileset) {
    for (Json const& tileDef : tileset.iterateArray()) {
      Vec4B color = jsonToVec4B(tileDef.get("value"));
      m_tiles.insert(colorAsInt(color), variantMapToTile(tileDef.toObject()));
    }
  }

  Tile const* ImageTileset::getTile(Vec4B color) const {
    if (color[3] == 0)
      color = Vec4B(255, 255, 255, 0);
    if (color[3] != 255)
      return nullptr;
    return &m_tiles.get(colorAsInt(color));
  }

  unsigned ImageTileset::colorAsInt(Vec4B color) const {
    if ((color[3] != 0) && (color[3] != 255)) {
      starAssert(false);
      return 0;
    }
    if (color[3] == 0)
      color = Vec4B(255, 255, 255, 0);
    return (((unsigned)color[2]) << 16) | (((unsigned)color[1]) << 8) | ((unsigned)color[0]);
  }
}

}