123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- //
- // BIMapRhombusGrid.hpp
- // CandyCookie
- //
- // Created by 冷晓霆 on 2022/2/22.
- //
- // 将地图划分为菱形网格,用于处理角色运动
- #ifndef RUMapRhombusGrid_hpp
- #define RUMapRhombusGrid_hpp
- #include <stdio.h>
- #include "cocos2d.h"
- #include "RUDefine.h"
- ///TODO::两个物件之间的最小zOrder间距 有需求找油代辉改
- #define BLOCK_GRID_SPACE 10
- USING_NS_CC;
- NS_RU_BEGIN
- class RhombusableItem {
- public:
- // 得到该物件的z-order
- virtual int getCurZOrder() = 0;
-
- // 得到该物件中心点在地图中的位置
- virtual Vec2 getCenterPosition() = 0;
-
- // 一系列棱形网格的坐标(相对于中心点而言),表示的是可视区域
- virtual const std::vector<Vec2>& getVisibleArea() = 0;
-
- // 一系列棱形网格的坐标(相对于中心点而言),表示的是基座区域
- virtual const std::vector<Vec2>& getPedestalArea() = 0;
-
- // 一系列棱形网格的坐标(相对于中心点而言),表示的是可在上面行走的区域
- virtual const std::vector<Vec2>& getWalkableArea() = 0;
-
- // 表示该物件的基座区域在极端情况下是否是可以穿行的
- virtual bool isCrossable() = 0;
-
- // 获取某个物体的名称
- virtual std::string getRhombusableItemName() = 0;
- };
- struct RhombusPathNode {
- Vec2 posGrid;
- int zOrder; // 如果为-1, 则需要调用者自己去设置一个合适的值
- bool bImmediate = false;
- };
- struct RhomArea {
- std::set<Vec2> grid;
- int zOrderDefault;
- };
- class MapRhombusGrid : public Ref {
- public:
- MapRhombusGrid();
- ~MapRhombusGrid();
-
- /// 初始化地图的网格信息
- /// @param mapSize 整个地图的大小
- /// @param rhombusSize 棱形网格的大小
- void initialize(const cocos2d::Size& mapSize, const cocos2d::Size& rhombusSize, bool bSupportStraight = false);
-
- /// 某个物件被移除了
- /// @param pItem 可被棱形化的物件
- void itemRemoved(RhombusableItem* pItem);
-
- /// 某个物件被添加到了地图上面,如果该区域被占用了,则返回失败
- /// @param pItem 可被棱形化的物件
- /// 返回是否添加成功
- bool itemAdded(RhombusableItem* pItem);
-
- /// 设置区域信息
- /// @param areas 区域信息
- void addArea(const std::vector<Vec2>& area, int zOrderDefault);
-
- /// 设置默认的zorder
- void setDefaultZOrder(int zOrder);
-
- /// 用于编辑器同步数据
- /// @param itemName 物件名字
- RhombusableItem* getItem(const std::string& itemName);
-
- /// 找到一条路径从from到to,返回一个id表示本次请求,id会在回调里面传给调用对象
- /// @param fromGrid 起始点的坐标,网格坐标
- /// @param toGrid 终点的坐标,网格坐标
- /// @param path 路径信息
- int findFlyAPath(const Vec2& fromGrid, const Vec2& toGrid, std::list<RhombusPathNode>& path);
-
- /// 找到一条路径从from到to,返回一个id表示本次请求,id会在回调里面传给调用对象
- /// @param fromGrid 起始点的坐标,网格坐标
- /// @param toGrid 终点的坐标,网格坐标
- /// @param path 路径信息
- int findAPath(const Vec2& fromGrid, const Vec2& toGrid, std::list<RhombusPathNode>& path, bool bIgnoreCharacter, bool bFlashToEndPos);
-
- /// 从地图坐标得到网格坐标
- /// @param pos 地图坐标
- Vec2 getGridPosition(const Vec2& pos);
-
- /// 某个位置是否被占用,也就是该网格位置已经有物件了
- /// @param posGrid 该网格的位置
- bool isGridOccupied(const Vec2& posGrid);
-
- /// 在节点上面绘制棱形网格部分
- /// @param pGridContainer 棱形网格所在的节点
- void debugGridAt(Node* pGridContainer);
-
- /// 画出某个网格
- /// @param gridPos 网格坐标
- /// @param isTemp 如果为临时的话则过removeNodeDelay秒会被删除
- void drawGridNode(const Vec2& gridPos, Color4F color = Color4F::RED, bool isTemp = true, float removeNodeDelay = 20.0);
-
- void refreshDebugGrid(bool isEnable = true);
-
- /// 得到某个网格的中心点对应的坐标值
- /// @param gridPos 网格坐标
- Vec2 getGridCenter(const Vec2& gridPos);
-
- /// 在某个物件旁边找空余的位置,并返回列表
- /// @param pItem 目标物件
- /// @param found 返回空余列表,可能为空
- /// @param gridPos 物件的中心位置,网格坐标
- void findAdjEmptyPoses(RhombusableItem* pItem, const Vec2& gridPos, std::set<Vec2>& found);
-
- /// 得到某个位置被遮挡的层数
- /// @param gridPos 要查找的位置
- int getCntInOverlay(const Vec2& gridPos);
-
- /// 获取棱形网格的Zorder
- /// @param gridPos 棱形网格坐标
- /// @param pTargetItem 目标物体,用来排除自己
- /// @param bIsOverlayed 是否被遮挡
- /// @param bFlyMode 飞行模式下需要遮盖住所有东西
- int getGridZorder(const Vec2& gridPos, bool& bIsOverlayed, RhombusableItem* pTargetItem = nullptr, bool bFlyMode = false);
- /// 格子尺寸
- cocos2d::Size getRhombusSize() { return _rhombusSize; }
-
- /// 得到某个网格的四个顶点的位置
- /// @param gridPos 网格坐标
- std::vector<Vec2> getGridPointsAt(const Vec2& gridPos);
-
- /// 获取占用了某个网格的所有物件的名称
- /// @param gridPos 网格
- std::list<std::string> getItemsInGrid(const Vec2& gridPos);
-
- void setSupportStraight(bool value){_bSupportStraight = value;}
- bool getSupportStraight(){return _bSupportStraight;}
-
- /// 将某个网格标记为已经被占用
- /// @param gridPos 网格
- void setGridObstacle(const Vec2& posGrid);
- private:
- /// 得到某个网格的索引值,方便保存
- /// @param posGrid 网格坐标
- inline int getGridIndex(const Vec2& posGrid);
-
- /// 占据某个网格
- /// @param posGrid 网格坐标
- inline void occupyGrid(const Vec2& posGrid);
-
- /// 释放某个网格
- /// @param posGrid 网格坐标
- inline void releaseGrid(const Vec2& posGrid);
-
- /// 调试用,显示某个网格的调试线
- /// @param gridPos 该网格的位置
- /// @param color 线的颜色
- /// @param fill 是否填充
- void drawGridWith(const Vec2& gridPos, Color4F color, bool fill = false);
-
- /// 实际查找可行走路线
- /// @param bIgnoreCrossable 是否忽略掉可穿行区域
- int findAPathInternal(const Vec2& fromGrid, const Vec2& toGrid, std::list<RhombusPathNode>& path, bool bIgnoreCrossable);
-
- /// 实际查找可飞行路线
- int findFlyAPathInternal(const Vec2& fromGrid, const Vec2& toGrid, std::list<RhombusPathNode>& path);
- /// 获取某个位置的ZOrder
- int getDefaultZOrder(const Vec2& posGrid);
-
- /// 判断某个位置是否在物件的后面
- /// @param posGrid 网格位置
- /// @param pItem 物件
- bool isBehindItem(const Vec2& posGrid, RhombusableItem* pItem);
- private:
- static MapRhombusGrid* _instance;
- static int _nextId4Find;
-
- // 地图信息
- cocos2d::Size _mapSize;
- cocos2d::Size _rhombusSize;
- int _cntGridsInX = 1;
- int _cntGridsInY = 1;
- bool _bSupportStraight = false;
-
- // 每个菱形网格的都被哪些物件的遮挡占用了
- std::unordered_map<int, std::list<RhombusableItem*>> _itemsOverlayInGrid;
- // 每个菱形网格上面有哪些物件,包括了基座区域
- std::unordered_map<int, std::list<RhombusableItem*>> _itemsInGrid;
- // 地图上面每个网格是否有某个物件的基座,每一位表示一个网格
- unsigned char* _occupiedFlag4Grid = nullptr;
- int _flagSize = 0;
- int _zOrderDefault = 0;
- std::list<RhomArea> _areas;
- // 可以被穿越的底座区域
- // 当前的处理方法在物件可以被移动的时候会有问题,但是当前场景下效率比较高
- std::unordered_map<int, int> _gridsCrossable;
-
- // 棱形网格所在的节点
- Node* _pGridContainer = nullptr;
- DrawNode* _pDrawNode4Debug = nullptr;
- bool _isDebugEnable = false;
- };
- NS_RU_END
- #endif /* RUMapRhombusGrid_hpp */
|