local Map = class("Map"); require("luaScript.Map.MapDrawer")(Map); Map.ObstacleType = { -- 不是障碍块 ObstacleNone = 1, -- 是障碍块 ObstacleNormal = 0, } -- TileWidth Map.TileWidth = 60 -- tileHeight Map.TileHeight = 30 -- 构造函数 function Map:ctor() -- 默认构造一个1136 X 640的地图 -- self:initWidthAndHeight(1136, 640, 60, 30); -- 障碍信息 self.obstacles = cc.CAStar:new(); -- 当障碍块改变时回调 self.ObstacleChanged = nil; end -- 重新计算地图 function Map:recalculate() self.TileHalfWidth = self.TileWidth / 2; self.TileHalfHeight = self.TileHeight / 2; -- 根据地图大小和tile的大小,计算tile的个数以及tile的偏移 local widthLen = math.ceil(self.MapWidth / self.TileWidth); local heightLen = math.ceil(self.MapHeight / self.TileHeight); self.TileCountX = widthLen + heightLen; self.TileCountY = widthLen + heightLen; -- X轴不需要偏移,只偏移Y轴 self.OffsetX = 0; self.OffsetY = heightLen; end -- 初始化地图的宽度和高度 function Map:initWidthAndHeight(width, height, tileWidth, tileHeight) self.MapWidth = width; self.MapHeight = height; self.TileWidth = tileWidth; self.TileHeight = tileHeight; -- 重新计算地图 self:recalculate(); end -- 初始化障碍块 function Map:initObstacles() self.obstacles:resize(self.TileCountX , self.TileCountY); end -- 增加一个障碍块 -- x y 为逻辑坐标 function Map:addObstacle(x, y) -- 如果不在地图内则添加不成功 if self:isInMap(x, y) == false or self:isObstacle(x, y) then return end self.obstacles:setBlock(x , y , Map.ObstacleType.ObstacleNormal); if self.ObstacleChanged then self.ObstacleChanged(x , y , Map.ObstacleType.ObstacleNormal); end end -- 删除一个障碍块 -- x y 为逻辑坐标 function Map:removeObstacle(x, y) if self:isInMap(x, y) then self.obstacles:setBlock(x , y , Map.ObstacleType.ObstacleNone); if self.ObstacleChanged then self.ObstacleChanged(x , y , Map.ObstacleType.ObstacleNone); end end end -- 判断一个点是否是障碍点 -- x y 为逻辑坐标 function Map:isObstacle(x, y) if self:isInMap(x, y) then return self.obstacles:isBlock(x,y); end return false; end -- 根据点的坐标或者障碍数据 function Map:getObstacle(x, y) if self:isInMap(x, y) == false then return 0; end return self.obstacles:getBlock(x,y); end -- 判断一个坐标点是否在地图内 function Map:isInMap(x, y) if x < 0 or y < 0 then print("x or y is less 0", "current x is", x, "current y is", y); return false; end if x >= self.TileCountX or y >= self.TileCountY then print("Map:TileCountX is", self.TileCountX, " current x is", x); print("Map:TileCountY is", self.TileCountY, " current y is", y); return false; end return true; end function Map:loadFromLuaNode(luaNode) -- 初始化地图数据 self:initWidthAndHeight(tonumber(luaNode.width), tonumber(luaNode.height), tonumber(luaNode.tileWidth), tonumber(luaNode.tileHeight)); if luaNode.mapdata then -- 兼容老格式 self.obstacles:resize(self.TileCountX , self.TileCountY); for i , v in pairs(luaNode.mapdata) do local x = math.floor((i - 1) / self.TileCountY); local y = (i - 1) % self.TileCountY; if v == 0 then self.obstacles:setBlock(x , y , 1); else self.obstacles:setBlock(x , y , 0); end end end end function Map:saveToXmlNode(xmlNode) -- 保存tile的偏移 xmlNode.offsetX = self.OffsetX; xmlNode.offsetY = self.OffsetY; xmlNode.col = self.TileCountX; xmlNode.row = self.TileCountY; -- 保存地图宽高和Tile宽高 xmlNode.width = self.MapWidth; xmlNode.height = self.MapHeight; xmlNode.tileWidth = self.TileWidth; xmlNode.tileHeight = self.TileHeight; -- 保存障碍块 local obstaclesStr; local singleObstacleStr; -- 将障碍信息压成一个字符串 for x = 0, self.TileCountX - 1 do for y = 0, self.TileCountY - 1 do local obstacle = self:getObstacle(x, y); -- 障碍信息 if obstacle == 0 then singleObstacleStr = "1"; else singleObstacleStr = "0"; end -- 开始直接赋值,否则叠加 if obstaclesStr == nil then obstaclesStr = {singleObstacleStr}; else table.insert(obstaclesStr , "," .. singleObstacleStr); end end end xmlNode.mapdata = table.concat(obstaclesStr); end function Map:createXmlNode() local xmlNode = xml.new("map"); self:saveToXmlNode(xmlNode); return xmlNode; end -- 保存一个地图到XML文件 function Map:saveXml(fullFilePath) local xmlNode = self:createXmlNode(); xmlNode:save(fullFilePath); end -- 保存一个地图到lua文件 function Map:saveLua(fullFilePath) local luaNode = {} -- 保存tile的偏移 luaNode.offsetX = self.OffsetX; luaNode.offsetY = self.OffsetY; luaNode.col = self.TileCountX; luaNode.row = self.TileCountY; -- 保存地图宽高和Tile宽高 luaNode.width = self.MapWidth; luaNode.height = self.MapHeight; luaNode.tileWidth = self.TileWidth; luaNode.tileHeight = self.TileHeight; self.obstacles:saveToFile(fullFilePath .. ".blocks"); table.saveFile(luaNode , fullFilePath); end -- 载入一个地图文件 function Map:loadLua(luaFile) print("加载map:" , luaFile); local xmlFile = table.loadFile(luaFile); if xmlFile then self:loadFromLuaNode(xmlFile); if not xmlFile.mapdata then self.obstacles:loadFromFile(luaFile .. ".blocks"); end end print("map 加载完成"); end -- 载入一个地图文件 function Map:loadXml(nodeFile) local xmlFile = loadXmlFileWithCache(nodeFile); if xmlFile then self:loadFromXmlNode(xmlFile:find("map")); end end -- -- 获取45度A*单元格矩阵坐标 -- @param px 目标点X坐标 -- @param py 目标点Y坐标 -- @return {@link Position} 矩阵点坐标 function Map:getTilePosition(px, py) -- 界面坐标 计算以屏幕左上为原点的世界坐标 local logicalx = px / (2 * self.TileHalfWidth) + (-py) / (2 * self.TileHalfHeight) + self.OffsetX; local logicaly = px / (2 * self.TileHalfWidth) - (-py) / (2 * self.TileHalfHeight) + self.OffsetY; return cc.p(math.floor(logicalx), math.floor(logicaly)); end -- -- 获取45度A*单元格矩阵坐标(不对齐到网格) -- @param px 目标点X坐标 -- @param py 目标点Y坐标 -- @return {@link Position} 矩阵点坐标 function Map:_getTilePosition(px, py) -- 界面坐标 计算以屏幕左上为原点的世界坐标 local logicalx = px / (2 * self.TileHalfWidth) + (-py) / (2 * self.TileHalfHeight) + self.OffsetX; local logicaly = px / (2 * self.TileHalfWidth) - (-py) / (2 * self.TileHalfHeight) + self.OffsetY; return cc.p(logicalx, logicaly); end -- -- 获取45度A*单元格矩阵坐标转舞台从标(获得的是格子的中心点坐标) -- @param px 舞台X坐标 -- @param py 舞台Y坐标 -- @return {@link Position} 矩阵点坐标 function Map:getPixelPosition(tileX, tileY) local nOffX = tileX - self.OffsetX; local nOffY = tileY - self.OffsetY; local positionX = nOffX * self.TileHalfWidth + nOffY * self.TileHalfWidth; -- 斜坐标 x每加1 竖坐标x+1/2 y+1/2 local positionY = nOffX * self.TileHalfHeight - nOffY * self.TileHalfHeight; -- 斜坐标 y每加1 竖坐标x+1/2 y-1/2 return cc.p(positionX, -positionY); end -- 载入场景文件 function loadScene(nodeFile) print("加载场景" , nodeFile); TimeSpan:enterSpan("loadScene" .. nodeFile); TimeSpan:enterSpan("createNodeFromFile"); print("加载模型"); LoadingScene = true; local node = cc.StreamObject:loadFromFile(nodeFile); LoadingScene = false; node:setCollectAnimationClip(false); TimeSpan:leaveSpan(); if not EditorMode then -- 普通模式,屏蔽掉HD内容 local hd = node:findNode("HD"); if hd then local function onQualityChanged(key , value) -- 高质量 hd:setVisible(value == 1); end hd:bind(app.systemSetting.info , "graphicQuality" , onQualityChanged); end end -- 创建一个题图载入资源 TimeSpan:enterSpan("requireMap"); print("加载障碍块"); local map = require("luaScript.Map.Map"):new(); local arr = string.split(nodeFile, "."); map:loadLua(arr[1] .. ".lmap"); TimeSpan:leaveSpan(); TimeSpan:leaveSpan(); return node , map; end return Map;