AniMapUtils.h
7.73 KB
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//
// AniMapUtils.h
// SteveMaggieCpp
//
// Created by Katarzyna Kalinowska-Górska on 05.06.2017.
//
//
#ifndef AniMapUtils_h
#define AniMapUtils_h
#include <stdio.h>
#include <vector>
#include "cocos2d.h"
class AniMapUtils {
public:
typedef struct TileData {
int col {-1};
int row {-1};
TileData(){}
TileData(int pCol, int pRow){
col = pCol;
row = pRow;
};
TileData(cocos2d::Vec2 vec){
col = vec.x;
row = vec.y;
};
// todo operator overloading would be better. or the best would be just to use Vec2 all along. But it's too late for that :(.
float distanceColRowToTile(const TileData& tileData) const {
return cocos2d::Vec2(col - tileData.col, row - tileData.row).length();
}
cocos2d::Vec2 convertToVec2() const{
return cocos2d::Vec2(col, row);
}
TileData operator-(const TileData& tile)
{
return TileData(col - tile.col, row - tile.row);
}
} TileData;
//for the path finding algorithm
class PathTileData {
public:
PathTileData(TileData tileData, std::vector<TileData> pNeighbours) {
tile = tileData;
neighbours = pNeighbours;
};
std::vector<TileData> neighbours;
int tempDistance {-1};
bool visited { false};
TileData tile {-1,-1};
TileData previousTile {-1, -1};
};
static AniMapUtils& getInstance()
{
static AniMapUtils instance;
return instance;
}
void clearMap();
std::vector<TileData> calculatePathOnTmxMap(TileData fromTile, TileData toTile, cocos2d::TMXTiledMap* tmxMap, cocos2d::TMXLayer* tmxTileLayer, bool allowStartTileInaccessible, bool useLastMapGraph = true);
// better to keep toTiles small
std::vector<TileData> calculatePathToClosestFromTileSet(TileData fromTile, std::vector<TileData> toTiles, cocos2d::TMXTiledMap* tmxMap, cocos2d::TMXLayer* tmxTileLayer, bool allowStartTileInaccessible, bool useLastMapGraph = true); // the last tile in the returned vector will be the chosen tile from the tile set
bool recalculateMapGraphAsync(cocos2d::TMXTiledMap* tmxMap, cocos2d::TMXLayer* tmxTileLayer, std::function<void()> callback);
void recalculateMapGraph(cocos2d::TMXTiledMap* tmxMap, cocos2d::TMXLayer* tmxTileLayer);
void recalculateMapGraph(cocos2d::TMXTiledMap* tmxMap, cocos2d::TMXLayer* tmxTileLayer, std::vector<AniMapUtils::TileData> justForTiles);
TileData findClosestAccessibleTile(TileData toTile, cocos2d::TMXTiledMap* tmxMap, cocos2d::TMXLayer* tmxLayer);
std::vector<TileData> listTileNeighbours(TileData tile, cocos2d::TMXTiledMap* tmxMap, cocos2d::TMXLayer* tmxLayer, bool ignoreAllChecks = false);
std::vector<TileData> calculatePath(TileData fromTile, TileData toTile, std::vector<std::vector<PathTileData*>> mapGraph);
int getTileLevel(cocos2d::TMXTiledMap* tmxMap, cocos2d::TMXLayer* tmxLayer, TileData p_tileData);
bool isTileAccessible(cocos2d::TMXTiledMap* tmxMap, cocos2d::TMXLayer* tmxLayer, int col, int row);
bool isTileAccessible(cocos2d::TMXTiledMap* tmxMap, cocos2d::TMXLayer* tmxLayer, TileData p_tileData);
bool areTilesNeighbours(TileData tile1, TileData tile2, cocos2d::TMXTiledMap* tmxMap, cocos2d::TMXLayer* tmxLayer, int maxDeltaLevel = 1, bool ignoreAllChecks = false); //TODO set to zero and load in map props
std::vector<TileData> closestTiles(TileData tile, cocos2d::TMXTiledMap* tmxMap, cocos2d::TMXLayer* tmxLayer, int dirX, int dirY, int range = 3, int maxDeltaLevel = 2);
std::vector<TileData> closestXTiles(TileData tile, cocos2d::TMXTiledMap* tmxMap, cocos2d::TMXLayer* tmxLayer, int dir, int range = 3, int maxDeltaLevel = 2); //dir -1 or 1
std::vector<TileData> closestYTiles(TileData tile, cocos2d::TMXTiledMap* tmxMap, cocos2d::TMXLayer* tmxLayer, int dir, int range = 3, int maxDeltaLevel = 2); //dir -1 or 1
TileData getClosestTileInDirection(cocos2d::TMXTiledMap* tmxMap, cocos2d::TMXLayer* tmxLayer, TileData origin, int colDir, int rowDir, int maxFlatDelta = 3, int maxLevelDelta = 2);
TileData getClosestTileInXDirection(cocos2d::TMXTiledMap* tmxMap, cocos2d::TMXLayer* tmxLayer, TileData origin, int colDir, int maxFlatDelta = 3, int maxLevelDelta = 2);
TileData getClosestTileInYDirection(cocos2d::TMXTiledMap* tmxMap, cocos2d::TMXLayer* tmxLayer, TileData origin, int rowDir, int maxFlatDelta = 3, int maxLevelDelta = 2);
// TileData closestNeighbour
TileData translateXYPointToColRow (cocos2d::Point xypoint, float tileWidth, float tileHeight, int totalMapCols, int totalMapRows);
int translateXToCol(float x, float tileWidth, int totalMapCols);
int translateYToRow(float y, float tileHeight, int totalMapRows);
cocos2d::Point getTileMiddlePosition(const cocos2d::TMXTiledMap* map, int col, int row);
cocos2d::Rect getTileRect(const cocos2d::TMXTiledMap* map, int col, int row);
cocos2d::Point translateScreenPositionToMapPosition(cocos2d::Point pointOnScreen, cocos2d::Point mapPosition);
cocos2d::Point translateMapPositionToScreenPosition(cocos2d::Point pointOnMap, cocos2d::Point mapPosition);
std::vector<TileData> getTilesIntersectingRect (cocos2d::Rect rect, float tileWidth, float tileHeight, int totalMapCols, int totalMapRows);
std::vector<TileData> getTilesIntersectingRect (cocos2d::Rect rect, float tileWidth, float tileHeight, int totalMapCols, int totalMapRows, std::vector<TileData>& borderTiles);
cocos2d::Point getRandomFreeTile(TileData& randomTile, cocos2d::TMXTiledMap* map, cocos2d::TMXLayer* layer, int minCol = 0, int maxCol = 150, int minRow = 0, int maxRow = 150);
void setTilePassable(TileData tile, bool passable);
// the pathfinding algorithm will stop and return the path after reaching a tile that is further from the starting tile than this range (by either col or row)
// can be set e.g. to the number of tiles that fit the screen
// by default, it's a number big enough not to make a difference
inline void setMaxTileRangeOnPath(int p_maxTileRange) {m_maxTileRangeOnPath = p_maxTileRange;}
cocos2d::Value getTileProperty(cocos2d::TMXTiledMap* p_map, cocos2d::TMXLayer* p_layer, const TileData& p_tile, const std::string& p_propertyName){
auto tileProperties = p_map->getPropertiesForGID(p_layer->getTileGIDAt(p_tile.convertToVec2()));
if(tileProperties.getType() == cocos2d::Value::Type::MAP){
auto map = tileProperties.asValueMap();
if(map.find(p_propertyName) != map.end()){
return map[p_propertyName];
}
}
return cocos2d::Value::Null;
}
protected:
std::vector<std::vector<PathTileData*>> _cachedMapGraph;
std::map<TileData, bool> _tempImpassableTiles;
int m_maxTileRangeOnPath {1000};
bool m_threadIsRunning { false };
cocos2d::TMXTiledMap* m_threadTempMap { nullptr};
cocos2d::TMXLayer* m_threadTempLayer { nullptr};
std::function<void()> m_threadTempCallback = [](){};
// only one should be running at a time
void asyncGraphRecalcThread();
};
bool operator==(const AniMapUtils::TileData& lhs, const AniMapUtils::TileData& rhs);
bool operator!=(const AniMapUtils::TileData& lhs, const AniMapUtils::TileData& rhs);
// for the std::map
bool operator<(const AniMapUtils::TileData& lhs, const AniMapUtils::TileData& rhs);
#endif /* AniMapUtils_h */