RUMapRhombusGrid.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. //
  2. // BIMapRhombusGrid.hpp
  3. // CandyCookie
  4. //
  5. // Created by 冷晓霆 on 2022/2/22.
  6. //
  7. // 将地图划分为菱形网格,用于处理角色运动
  8. #ifndef RUMapRhombusGrid_hpp
  9. #define RUMapRhombusGrid_hpp
  10. #include <stdio.h>
  11. #include "cocos2d.h"
  12. #include "RUDefine.h"
  13. ///TODO::两个物件之间的最小zOrder间距 有需求找油代辉改
  14. #define BLOCK_GRID_SPACE 10
  15. USING_NS_CC;
  16. NS_RU_BEGIN
  17. class RhombusableItem {
  18. public:
  19. // 得到该物件的z-order
  20. virtual int getCurZOrder() = 0;
  21. // 得到该物件中心点在地图中的位置
  22. virtual Vec2 getCenterPosition() = 0;
  23. // 一系列棱形网格的坐标(相对于中心点而言),表示的是可视区域
  24. virtual const std::vector<Vec2>& getVisibleArea() = 0;
  25. // 一系列棱形网格的坐标(相对于中心点而言),表示的是基座区域
  26. virtual const std::vector<Vec2>& getPedestalArea() = 0;
  27. // 一系列棱形网格的坐标(相对于中心点而言),表示的是可在上面行走的区域
  28. virtual const std::vector<Vec2>& getWalkableArea() = 0;
  29. // 表示该物件的基座区域在极端情况下是否是可以穿行的
  30. virtual bool isCrossable() = 0;
  31. // 获取某个物体的名称
  32. virtual std::string getRhombusableItemName() = 0;
  33. };
  34. struct RhombusPathNode {
  35. Vec2 posGrid;
  36. int zOrder; // 如果为-1, 则需要调用者自己去设置一个合适的值
  37. bool bImmediate = false;
  38. };
  39. struct RhomArea {
  40. std::set<Vec2> grid;
  41. int zOrderDefault;
  42. };
  43. class MapRhombusGrid : public Ref {
  44. public:
  45. MapRhombusGrid();
  46. ~MapRhombusGrid();
  47. /// 初始化地图的网格信息
  48. /// @param mapSize 整个地图的大小
  49. /// @param rhombusSize 棱形网格的大小
  50. void initialize(const cocos2d::Size& mapSize, const cocos2d::Size& rhombusSize, bool bSupportStraight = false);
  51. /// 某个物件被移除了
  52. /// @param pItem 可被棱形化的物件
  53. void itemRemoved(RhombusableItem* pItem);
  54. /// 某个物件被添加到了地图上面,如果该区域被占用了,则返回失败
  55. /// @param pItem 可被棱形化的物件
  56. /// 返回是否添加成功
  57. bool itemAdded(RhombusableItem* pItem);
  58. /// 设置区域信息
  59. /// @param areas 区域信息
  60. void addArea(const std::vector<Vec2>& area, int zOrderDefault);
  61. /// 设置默认的zorder
  62. void setDefaultZOrder(int zOrder);
  63. /// 用于编辑器同步数据
  64. /// @param itemName 物件名字
  65. RhombusableItem* getItem(const std::string& itemName);
  66. /// 找到一条路径从from到to,返回一个id表示本次请求,id会在回调里面传给调用对象
  67. /// @param fromGrid 起始点的坐标,网格坐标
  68. /// @param toGrid 终点的坐标,网格坐标
  69. /// @param path 路径信息
  70. int findFlyAPath(const Vec2& fromGrid, const Vec2& toGrid, std::list<RhombusPathNode>& path);
  71. /// 找到一条路径从from到to,返回一个id表示本次请求,id会在回调里面传给调用对象
  72. /// @param fromGrid 起始点的坐标,网格坐标
  73. /// @param toGrid 终点的坐标,网格坐标
  74. /// @param path 路径信息
  75. int findAPath(const Vec2& fromGrid, const Vec2& toGrid, std::list<RhombusPathNode>& path, bool bIgnoreCharacter, bool bFlashToEndPos);
  76. /// 从地图坐标得到网格坐标
  77. /// @param pos 地图坐标
  78. Vec2 getGridPosition(const Vec2& pos);
  79. /// 某个位置是否被占用,也就是该网格位置已经有物件了
  80. /// @param posGrid 该网格的位置
  81. bool isGridOccupied(const Vec2& posGrid);
  82. /// 在节点上面绘制棱形网格部分
  83. /// @param pGridContainer 棱形网格所在的节点
  84. void debugGridAt(Node* pGridContainer);
  85. /// 画出某个网格
  86. /// @param gridPos 网格坐标
  87. /// @param isTemp 如果为临时的话则过removeNodeDelay秒会被删除
  88. void drawGridNode(const Vec2& gridPos, Color4F color = Color4F::RED, bool isTemp = true, float removeNodeDelay = 20.0);
  89. void refreshDebugGrid(bool isEnable = true);
  90. /// 得到某个网格的中心点对应的坐标值
  91. /// @param gridPos 网格坐标
  92. Vec2 getGridCenter(const Vec2& gridPos);
  93. /// 在某个物件旁边找空余的位置,并返回列表
  94. /// @param pItem 目标物件
  95. /// @param found 返回空余列表,可能为空
  96. /// @param gridPos 物件的中心位置,网格坐标
  97. void findAdjEmptyPoses(RhombusableItem* pItem, const Vec2& gridPos, std::set<Vec2>& found);
  98. /// 得到某个位置被遮挡的层数
  99. /// @param gridPos 要查找的位置
  100. int getCntInOverlay(const Vec2& gridPos);
  101. /// 获取棱形网格的Zorder
  102. /// @param gridPos 棱形网格坐标
  103. /// @param pTargetItem 目标物体,用来排除自己
  104. /// @param bIsOverlayed 是否被遮挡
  105. /// @param bFlyMode 飞行模式下需要遮盖住所有东西
  106. int getGridZorder(const Vec2& gridPos, bool& bIsOverlayed, RhombusableItem* pTargetItem = nullptr, bool bFlyMode = false);
  107. /// 格子尺寸
  108. cocos2d::Size getRhombusSize() { return _rhombusSize; }
  109. /// 得到某个网格的四个顶点的位置
  110. /// @param gridPos 网格坐标
  111. std::vector<Vec2> getGridPointsAt(const Vec2& gridPos);
  112. /// 获取占用了某个网格的所有物件的名称
  113. /// @param gridPos 网格
  114. std::list<std::string> getItemsInGrid(const Vec2& gridPos);
  115. void setSupportStraight(bool value){_bSupportStraight = value;}
  116. bool getSupportStraight(){return _bSupportStraight;}
  117. /// 将某个网格标记为已经被占用
  118. /// @param gridPos 网格
  119. void setGridObstacle(const Vec2& posGrid);
  120. private:
  121. /// 得到某个网格的索引值,方便保存
  122. /// @param posGrid 网格坐标
  123. inline int getGridIndex(const Vec2& posGrid);
  124. /// 占据某个网格
  125. /// @param posGrid 网格坐标
  126. inline void occupyGrid(const Vec2& posGrid);
  127. /// 释放某个网格
  128. /// @param posGrid 网格坐标
  129. inline void releaseGrid(const Vec2& posGrid);
  130. /// 调试用,显示某个网格的调试线
  131. /// @param gridPos 该网格的位置
  132. /// @param color 线的颜色
  133. /// @param fill 是否填充
  134. void drawGridWith(const Vec2& gridPos, Color4F color, bool fill = false);
  135. /// 实际查找可行走路线
  136. /// @param bIgnoreCrossable 是否忽略掉可穿行区域
  137. int findAPathInternal(const Vec2& fromGrid, const Vec2& toGrid, std::list<RhombusPathNode>& path, bool bIgnoreCrossable);
  138. /// 实际查找可飞行路线
  139. int findFlyAPathInternal(const Vec2& fromGrid, const Vec2& toGrid, std::list<RhombusPathNode>& path);
  140. /// 获取某个位置的ZOrder
  141. int getDefaultZOrder(const Vec2& posGrid);
  142. /// 判断某个位置是否在物件的后面
  143. /// @param posGrid 网格位置
  144. /// @param pItem 物件
  145. bool isBehindItem(const Vec2& posGrid, RhombusableItem* pItem);
  146. private:
  147. static MapRhombusGrid* _instance;
  148. static int _nextId4Find;
  149. // 地图信息
  150. cocos2d::Size _mapSize;
  151. cocos2d::Size _rhombusSize;
  152. int _cntGridsInX = 1;
  153. int _cntGridsInY = 1;
  154. bool _bSupportStraight = false;
  155. // 每个菱形网格的都被哪些物件的遮挡占用了
  156. std::unordered_map<int, std::list<RhombusableItem*>> _itemsOverlayInGrid;
  157. // 每个菱形网格上面有哪些物件,包括了基座区域
  158. std::unordered_map<int, std::list<RhombusableItem*>> _itemsInGrid;
  159. // 地图上面每个网格是否有某个物件的基座,每一位表示一个网格
  160. unsigned char* _occupiedFlag4Grid = nullptr;
  161. int _flagSize = 0;
  162. int _zOrderDefault = 0;
  163. std::list<RhomArea> _areas;
  164. // 可以被穿越的底座区域
  165. // 当前的处理方法在物件可以被移动的时候会有问题,但是当前场景下效率比较高
  166. std::unordered_map<int, int> _gridsCrossable;
  167. // 棱形网格所在的节点
  168. Node* _pGridContainer = nullptr;
  169. DrawNode* _pDrawNode4Debug = nullptr;
  170. bool _isDebugEnable = false;
  171. };
  172. NS_RU_END
  173. #endif /* RUMapRhombusGrid_hpp */