MainMiniMapLayout.lua 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. local MainMiniMapLayout = class("MainMiniMapLayout", function() return cc.Node:create() end)
  2. local Res_path = global.MMO.PATH_RES_PRIVATE .. "main/"
  3. local Res_Point_1 = Res_path .. "miniMap/point_1.png"
  4. local Res_Point_2 = Res_path .. "miniMap/point_2.png"
  5. local Res_Point_3 = Res_path .. "miniMap/point_3.png"
  6. local function squLen( x, y )
  7. local maxv = math.max(math.abs(x), math.abs(y))
  8. return maxv * maxv
  9. end
  10. local TRemove = table.remove
  11. local TInsert = table.insert
  12. function MainMiniMapLayout:ctor()
  13. self._isHide = false
  14. self._released = false
  15. self._actorCounts = {} -- 位置ID 计数
  16. self._actorPoints = {} -- 位置点对象
  17. self._actorPosIDs = {} -- actorID = 位置ID
  18. self._pointCache = {}
  19. -- 右上角小地图进入范围显示相关的提示
  20. self._portals = {} -- 提示数据
  21. self._protalRange = tonumber(SL:GetMetaValue("GAME_DATA","minimap_title_range")) or 60 --检测的格子数
  22. self._markPortalIdx = nil -- 标记当前正在显示的提示下标
  23. end
  24. function MainMiniMapLayout.create()
  25. local layout = MainMiniMapLayout.new()
  26. if layout:Init() then
  27. return layout
  28. end
  29. return nil
  30. end
  31. function MainMiniMapLayout:Init()
  32. self._quickUI = ui_delegate(self)
  33. self:InitGUI()
  34. self:InitMiniMap()
  35. self:InitEditMode()
  36. return true
  37. end
  38. function MainMiniMapLayout:InitGUI()
  39. GUI.ATTACH_MAINMINIMAP = self
  40. SL:RequireFile(SLDefine.LUAFile.LUA_FILE_MAIN_MINIMAP)
  41. local meta = {}
  42. meta.CalcMiniMapPos = function(x, y)
  43. return self:CalcMiniMapPos(cc.p(x, y))
  44. end
  45. meta.__index = meta
  46. setmetatable(MainMiniMap, meta)
  47. MainMiniMap.main()
  48. self._miniScaleX = self._quickUI.Image_minimap:getScaleX()
  49. self._miniScaleY = self._quickUI.Image_minimap:getScaleY()
  50. end
  51. function MainMiniMapLayout:InitMiniMap()
  52. local icon = ccui.ImageView:create()
  53. icon:setVisible(false)
  54. self._icon = icon
  55. self._quickUI.Node_path:addChild(icon)
  56. local textName = ccui.Text:create()
  57. textName:setFontSize(16)
  58. textName:setFontName(global.MMO.PATH_FONT2)
  59. textName:setAnchorPoint(cc.p(0.5,0.5))
  60. self._textName = textName
  61. self._quickUI.Node_path:addChild(textName)
  62. -- actor白点
  63. local actorPoint = ccui.ImageView:create()
  64. self._quickUI.Node_player:addChild(actorPoint)
  65. actorPoint:loadTexture(Res_path .. "miniMap/point_main.png")
  66. actorPoint:ignoreContentAdaptWithSize(false)
  67. actorPoint:setContentSize(cc.size(4, 4))
  68. -- 打开小地图
  69. self._quickUI.Panel_minimap:addClickEventListener(function()
  70. local MapProxy = global.Facade:retrieveProxy(global.ProxyTable.Map)
  71. if false == MapProxy:CheckMiniMapAble() then
  72. return false
  73. end
  74. local MiniMapMediator = global.Facade:retrieveMediator("MiniMapMediator")
  75. if MiniMapMediator._layer then
  76. SL:CloseMiniMap()
  77. else
  78. SL:OpenMiniMap()
  79. end
  80. end)
  81. self._limitSize = self._quickUI.Panel_minimap:getContentSize()
  82. self._minimapSize = {width=0, height=0}
  83. self:UpdateMapPos()
  84. self:UpdateMiniMap()
  85. self:UpdateMiniMapPos()
  86. end
  87. function MainMiniMapLayout:InitEditMode()
  88. local items =
  89. {
  90. "LayoutClip",
  91. "Node",
  92. "Map",
  93. "MapBG",
  94. "MapName",
  95. "MapStatusBG",
  96. "MapStatus",
  97. "PlayerPos",
  98. "MapButton",
  99. "MapButtonText",
  100. "PKModelCell",
  101. "PKModelButton",
  102. "PKModelButtonText"
  103. }
  104. for _, widgetName in ipairs(items) do
  105. if self._quickUI[widgetName] then
  106. self._quickUI[widgetName].editMode = 1
  107. end
  108. end
  109. end
  110. function MainMiniMapLayout:InitAdapet()
  111. self:setPositionY(-30)
  112. end
  113. function MainMiniMapLayout:OnMainMiniMapChange(show)
  114. if MainMiniMap.ChangeShowState then
  115. MainMiniMap.ChangeShowState(not show)
  116. end
  117. end
  118. function MainMiniMapLayout:CalcMiniMapPos(mapPos)
  119. local mapData = global.sceneManager:GetMapData2DPtr()
  120. if not mapData then
  121. return cc.p(0, 0)
  122. end
  123. local posX = mapPos.x / mapData:getMapDataCols() * self._minimapSize.width
  124. local posY = (1 - mapPos.y / mapData:getMapDataRows()) * self._minimapSize.height
  125. return cc.p(posX, posY)
  126. end
  127. function MainMiniMapLayout:OnChangeScene()
  128. self:UpdateMapPos()
  129. self:UpdateMiniMap()
  130. self:UpdateMiniMapPos()
  131. self:CleanupActorPoints()
  132. self:InitActorPoints()
  133. -- debug
  134. if _DEBUG and SL:GetMetaValue("GAME_DATA","DebugMapInfoShow") then
  135. self:SetMapInfoInDebug()
  136. end
  137. end
  138. function MainMiniMapLayout:SetMapInfoInDebug()
  139. local MapProxy = global.Facade:retrieveProxy(global.ProxyTable.Map)
  140. local mapID = MapProxy:GetMapID()
  141. local mapDataID = MapProxy:GetMapDataID()
  142. if not self._quickUI.Panel_map:getChildByName("DEBUG_MAP_SHOW") then
  143. local text = ccui.Text:create()
  144. text:setAnchorPoint(cc.p(0.5, 0.5))
  145. text:setString(string.format("地图.%s\n资源.%s", mapID, mapDataID))
  146. text:setTextColor(cc.c3b(255, 255, 0))
  147. text:setFontSize(18)
  148. text:setFontName(global.MMO.PATH_FONT2)
  149. text:setPosition(cc.p(self._quickUI.Panel_map:getContentSize().width/2, self._quickUI.Panel_map:getContentSize().height/2))
  150. text:setName("DEBUG_MAP_SHOW")
  151. text:addTo(self._quickUI.Panel_map)
  152. else
  153. local text = self._quickUI.Panel_map:getChildByName("DEBUG_MAP_SHOW")
  154. text:setString(string.format("地图.%s\n资源.%s", mapID, mapDataID))
  155. end
  156. end
  157. function MainMiniMapLayout:OnMinimapDownloadSuccess(dMinimapID)
  158. local MapProxy = global.Facade:retrieveProxy(global.ProxyTable.Map)
  159. local minimapID = MapProxy:GetMiniMapID()
  160. if minimapID == dMinimapID and MapProxy:CheckMiniMapAble() then
  161. self:UpdateMapPos()
  162. self:UpdateMiniMap()
  163. self:UpdateMiniMapPos()
  164. end
  165. end
  166. function MainMiniMapLayout:UpdateMiniMap()
  167. local MapProxy = global.Facade:retrieveProxy(global.ProxyTable.Map)
  168. local MiniMapProxy = global.Facade:retrieveProxy(global.ProxyTable.MiniMapProxy)
  169. self._portals = MiniMapProxy:getPortals()
  170. self._markPortalIdx = nil
  171. if false == MapProxy:CheckMiniMapAble() then
  172. self._quickUI.Image_empty:setVisible(true)
  173. self._quickUI.Node_player:setVisible(false)
  174. self._quickUI.Image_minimap:setVisible(false)
  175. else
  176. self._quickUI.Image_empty:setVisible(false)
  177. self._quickUI.Node_player:setVisible(true)
  178. self._quickUI.Image_minimap:setVisible(true)
  179. self._quickUI.Image_minimap:loadTexture(MapProxy:GetMiniMapFile())
  180. self._quickUI.Image_minimap:ignoreContentAdaptWithSize(true)
  181. local contentSize = self._quickUI.Image_minimap:getContentSize()
  182. if contentSize.width < self._limitSize.width or contentSize.height < self._limitSize.height then
  183. contentSize.width = math.max(contentSize.width, self._limitSize.width)
  184. contentSize.height = math.max(contentSize.height, self._limitSize.height)
  185. GUI:setContentSize(self._quickUI.Image_minimap, contentSize)
  186. end
  187. local scaleX = self._miniScaleX
  188. local scaleY = self._miniScaleY
  189. self._minimapSize = {width = contentSize.width*scaleX, height = contentSize.height*scaleY}
  190. self._quickUI.Node_path:setPosition(cc.p(0, 0))
  191. self._quickUI.Node_actors:setPosition(cc.p(0, 0))
  192. end
  193. if MainMiniMap and MainMiniMap.UpdatePortal then
  194. MainMiniMap.UpdatePortal(true)
  195. else
  196. self:UpdatePortal()
  197. end
  198. end
  199. function MainMiniMapLayout:UpdateMiniMapPos()
  200. local MapProxy = global.Facade:retrieveProxy(global.ProxyTable.Map)
  201. if false == MapProxy:CheckMiniMapAble() then
  202. return false
  203. end
  204. local actor = global.gamePlayerController:GetMainPlayer()
  205. if not actor then
  206. return false
  207. end
  208. local mapWidth = global.sceneManager:GetMapWidthInPixel()
  209. local mapHeight = global.sceneManager:GetMapHeightInPixel()
  210. local worldPos = actor:getPosition()
  211. local worldX = worldPos.x
  212. local worldY = -worldPos.y
  213. local ratioX = self._minimapSize.width / mapWidth
  214. local ratioY = self._minimapSize.height / mapHeight
  215. local function calcMiniMap()
  216. local minimapX = worldX * -ratioX
  217. local minimapY = (mapHeight - worldY) * -ratioY
  218. minimapX = minimapX + self._limitSize.width/2
  219. minimapY = minimapY + self._limitSize.height/2
  220. minimapX = math.max(minimapX, -(self._minimapSize.width-self._limitSize.width))
  221. minimapX = math.min(minimapX, 0)
  222. minimapY = math.max(minimapY, -(self._minimapSize.height-self._limitSize.height))
  223. minimapY = math.min(minimapY, 0)
  224. self._quickUI.Image_minimap:setPosition({x=minimapX, y=minimapY})
  225. end
  226. local function calcPlayerPos()
  227. local playerX = self._limitSize.width/2
  228. local playerY = self._limitSize.height/2
  229. local minimapX = worldX * ratioX
  230. local minimapY = (mapHeight - worldY) * ratioY
  231. -- 校正X
  232. if minimapX < self._limitSize.width/2 then
  233. playerX = minimapX
  234. elseif minimapX > self._minimapSize.width-self._limitSize.width/2 then
  235. playerX = self._limitSize.width - (self._minimapSize.width - minimapX)
  236. end
  237. -- 校正Y
  238. if minimapY < self._limitSize.height/2 then
  239. playerY = minimapY
  240. elseif minimapY > self._minimapSize.height-self._limitSize.height/2 then
  241. playerY = self._limitSize.height - (self._minimapSize.height - minimapY)
  242. end
  243. self._quickUI.Node_player:setPosition({x=playerX, y=playerY})
  244. end
  245. calcMiniMap()
  246. calcPlayerPos()
  247. end
  248. function MainMiniMapLayout:OnPlayerMoved()
  249. self:UpdateMapPos()
  250. if MainMiniMap and MainMiniMap.UpdatePortal then
  251. MainMiniMap.UpdatePortal()
  252. else
  253. self:UpdatePortal()
  254. end
  255. self:UpdateMiniMapPos()
  256. end
  257. function MainMiniMapLayout:UpdateMapPos()
  258. if not self._quickUI.PlayerPos then
  259. return false
  260. end
  261. local actor = global.gamePlayerController:GetMainPlayer()
  262. if not actor then
  263. return false
  264. end
  265. local mapX = actor:GetMapX()
  266. local mapY = actor:GetMapY()
  267. self._quickUI.PlayerPos:setString(string.format("%s:%s", mapX, mapY))
  268. end
  269. -- 更新相关提示
  270. function MainMiniMapLayout:UpdatePortal()
  271. if not self._protalRange then
  272. return
  273. end
  274. local actor = global.gamePlayerController:GetMainPlayer()
  275. if not actor then
  276. return false
  277. end
  278. local mapX = actor:GetMapX()
  279. local mapY = actor:GetMapY()
  280. local showNameIndex = nil
  281. local mixRange = (self._protalRange+1) * (self._protalRange+1)
  282. for i, v in ipairs(self._portals) do
  283. local destMapX = tonumber(v.X) or 1
  284. local destMapY = tonumber(v.Y) or 1
  285. local len = math.abs( squLen( mapX - destMapX, mapY - destMapY ) )
  286. if len < mixRange then
  287. mixRange = len
  288. showNameIndex = i
  289. end
  290. end
  291. if showNameIndex then
  292. if self._markPortalIdx ~= showNameIndex then
  293. self._markPortalIdx = showNameIndex
  294. local showName = self._portals[showNameIndex] or {}
  295. local miniMapPos = self:CalcMiniMapPos( cc.p(tonumber(showName.X) or 1,tonumber(showName.Y) or 1) )
  296. self._textName:setPosition(miniMapPos.x,miniMapPos.y+13)
  297. self._icon:setPosition(miniMapPos.x,miniMapPos.y)
  298. local color = (showName.nColor and tonumber(showName.nColor) == nil) and GetColorFromHexString(showName.nColor) or GET_COLOR_BYID_C3B(tonumber(showName.nColor) or 1)
  299. self._textName:setTextColor(color)
  300. self._textName:enableOutline(cc.Color4B.BLACK, tonumber(showName.bOutLine) or 0)
  301. self._textName:setString( showName.sShowName )
  302. local path = showName.sImgPath or "icon_xdtzy_04.png"
  303. self._icon:loadTexture( global.MMO.PATH_RES_PRIVATE .. "minimap/" .. path)
  304. self._icon:setVisible( true )
  305. end
  306. else
  307. self._markPortalIdx = nil
  308. self._textName:setString("")
  309. self._icon:setVisible( false )
  310. end
  311. end
  312. function MainMiniMapLayout:CleanupActorPoints()
  313. for i,v in ipairs(self._quickUI.Node_actors:getChildren()) do
  314. v:retain()
  315. v:removeFromParent()
  316. table.insert(self._pointCache,v)
  317. end
  318. self._actorPoints = {}
  319. self._actorCounts = {}
  320. self._actorPosIDs = {}
  321. end
  322. function MainMiniMapLayout:InitActorPoints()
  323. local playerList, nPlayer = global.playerManager:FindPlayerIDInCurrViewField()
  324. for i = 1, nPlayer do
  325. local actor = global.actorManager:GetActor(playerList[i])
  326. if actor then
  327. self:AddActorPoint(actor)
  328. end
  329. end
  330. local npcList, nNpc = global.npcManager:FindNpcIDInCurrViewField()
  331. for i = 1, nNpc do
  332. local actor = global.actorManager:GetActor(npcList[i])
  333. if actor then
  334. self:AddActorPoint(actor)
  335. end
  336. end
  337. local monsterList, nMonster = global.monsterManager:FindMonsterIDInCurrViewField(true)
  338. for i = 1, nMonster do
  339. local actor = global.actorManager:GetActor(monsterList[i])
  340. if actor then
  341. self:AddActorPoint(actor)
  342. end
  343. end
  344. end
  345. function MainMiniMapLayout:UpdateActorPoint(actor)
  346. -- 移除上个位置
  347. self:RmvActorPoint(actor)
  348. -- 处理新位置
  349. local posID = self:GetActorPointPosID(actor)
  350. local actorID = actor:GetID()
  351. local actorPoint = self._actorPoints[posID]
  352. if actorPoint then
  353. if not self._actorCounts[posID] then
  354. self._actorCounts[posID] = 0
  355. end
  356. self._actorCounts[posID] = self._actorCounts[posID] + 1
  357. self._actorPosIDs[actorID] = posID
  358. else
  359. self:CreateActorPoint(actor, posID)
  360. self._actorCounts[posID] = 1
  361. self._actorPosIDs[actorID] = posID
  362. end
  363. end
  364. function MainMiniMapLayout:CreateActorPoint(actor, posID)
  365. local actorPoint = self:GetActorPointCache()
  366. self._actorPoints[posID] = actorPoint
  367. local path = actor:IsMonster() and Res_Point_1 or (actor:IsPlayer() and Res_Point_2 or Res_Point_3)
  368. actorPoint:loadTexture(path)
  369. local z = actor:IsMonster() and 1 or (actor:IsPlayer() and 2 or 3)
  370. actorPoint:ignoreContentAdaptWithSize(false)
  371. actorPoint:setContentSize(cc.size(5, 5))
  372. actorPoint:setLocalZOrder(z)
  373. self._quickUI.Node_actors:addChild(actorPoint)
  374. local mapPos = cc.p(actor:GetMapX(), actor:GetMapY())
  375. local miniMapPos = self:CalcMiniMapPos(mapPos)
  376. actorPoint:setPosition(miniMapPos)
  377. actorPoint:setVisible(actor:GetValueByKey(global.MMO.HUD_SNEAK)~=true)
  378. end
  379. function MainMiniMapLayout:OnMainPlayerRevive()
  380. self:UpdateMapPos()
  381. self:UpdateMiniMap()
  382. self:UpdateMiniMapPos()
  383. end
  384. function MainMiniMapLayout:AddActorPoint(actor)
  385. if nil == actor then
  386. return false
  387. end
  388. -- 死亡
  389. if actor:IsDie() or actor:IsDeath() then
  390. return false
  391. end
  392. -- 怪物石化和地下,等出生状态
  393. if actor:IsMonster() and (actor:IsBorn() or actor:IsCave()) then
  394. return false
  395. end
  396. local mainPlayerID = global.gamePlayerController:GetMainPlayerID()
  397. if nil == mainPlayerID then
  398. return false
  399. end
  400. local actorID = actor:GetID()
  401. if actorID == mainPlayerID then
  402. self:OnMainPlayerRevive()
  403. return false
  404. end
  405. -- 自己的宝宝不显示
  406. if actor:GetMasterID() == mainPlayerID then
  407. return false
  408. end
  409. if not (actor:IsMonster() or actor:IsPlayer() or actor:IsNPC()) then
  410. return false
  411. end
  412. local MapProxy = global.Facade:retrieveProxy(global.ProxyTable.Map)
  413. if false == MapProxy:CheckMiniMapAble() then
  414. return false
  415. end
  416. self:UpdateActorPoint(actor)
  417. end
  418. function MainMiniMapLayout:GetActorPointPosID(actor)
  419. local px = actor:GetMapX()
  420. local py = actor:GetMapY()
  421. local z = actor:IsMonster() and 1 or (actor:IsMonster() and 2 or 3)
  422. local posID = z * 10000000000 + KEY_MAP_XY(px, py)
  423. return posID
  424. end
  425. function MainMiniMapLayout:RmvActorPoint(actor)
  426. if nil == actor then
  427. return false
  428. end
  429. local actorID = actor:GetID()
  430. local posID = self._actorPosIDs[actorID]
  431. if not posID then
  432. return false
  433. end
  434. self._actorPosIDs[actorID] = nil
  435. if not self._actorCounts[posID] then
  436. return false
  437. end
  438. self._actorCounts[posID] = self._actorCounts[posID] - 1
  439. if self._actorCounts[posID] > 0 then
  440. return false
  441. end
  442. self._actorCounts[posID] = nil
  443. local actorPoint = self._actorPoints[posID]
  444. if not actorPoint then
  445. return false
  446. end
  447. if not tolua.isnull(actorPoint) then
  448. actorPoint:removeFromParent()
  449. end
  450. self._actorPoints[posID] = nil
  451. end
  452. function MainMiniMapLayout:GetActorPointCache()
  453. if #self._pointCache > 0 then
  454. return TRemove(self._pointCache, #self._pointCache)
  455. end
  456. local pointCell = ccui.ImageView:create()
  457. return pointCell
  458. end
  459. function MainMiniMapLayout:OnReleaseMemory()
  460. for key, value in pairs(self._pointCache) do
  461. value:autorelease()
  462. end
  463. self._pointCache = {}
  464. self._released = true
  465. end
  466. return MainMiniMapLayout