Android访问瓦片地图 费流量,瓦片地图注意事项

瓦片地图(Tiled Map)系列文章:

承接上一篇文章,再来聊聊一些coding方面的tips:

TileMapAtlas、FastTMX和TMXTiledMap的选择

我们看到cocos2d-x提供了三个和TiledMap相关的类:TileMapAtlas、FastTMX和TMXTiledMap,那么应该采用哪个类呢?

首先,TileMapAtlas官方不建议使用。

剩下的两个C++类FastTMX和TMXTiledMap,分别绑定到lua的ccexp.TMXTiledMap和cc.TMXTiledMap。采用FastTMX的GL verts(顶点数)较少,可惜暂时不支持staggered类型。所以,staggered类型的Tiled Map只能用TMXTiledMap,其它类型的Tiled Map建议采用FastTMX。

-- NOTE: FastTMX doesn't support staggered tmx

-- ccexp.TMXTiledMap is faster, but the grid will not be displayed normally

local map = cc.TMXTiledMap:create("xxx.tmx")

如何判断tile坐标超出地图区域

FastTMX和TMXTiledMap提供了一个方法getMapSize(),需要注意的是这个函数和cocos2d-x其他getXXXSize的函数不同,返回的大小不是以像素值为单位,而是2D地图在两个维度的tile数目。

local function isTileInMap(map, tileCoord)

-- NOTE: mapSize is measured in tile number

local mapSize = map:getMapSize()

return (tileCoord.x >= 0)

and (tileCoord.x < mapSize.width)

and (tileCoord.y >= 0)

and (tileCoord.y < mapSize.height)

end

如何获取tile的标记

上一篇文章提到,对于不能放置在地图上禁止被编辑的区域,可以在相应的Tile做上标记。例如,我在Tiled Map里创建了一个叫"meta"的图层:

1460000006214075

在TileSet Properties里设置一个标记"Collidable",表示禁止被编辑:

1460000006214077

接下来就是用这个TileSet来刷图啦!

那么我们如何在代码中获取这个标记呢?FastTMX和TMXTiledMap提供了一个方法getPropertiesForGID(GID)来获取GID所对应的tile的属性。

那么新的问题又来了,GID这个索引又如何获取呢?还有另一个函数getTileGIDAt(),传入的参数就是上次所讲的tile坐标啦!

现在你应该明白之前本渣为何要在那套坐标系下解决判断区域相交的问题了吧?

local function isValidTile(map, tileCoord)

local metaLayer = map:getLayer("meta")

local flags = 0

local GID, flags = metaLayer:getTileGIDAt(tileCoord, flags)

if not GID or GID <= 0 then

return true

end

local property = map:getPropertiesForGID(GID)

if property and property["Collidable"] then

return false

else

return true

end

end

关于tile的坐标

上回提到Staggered Tiled Map的坐标系,其实这套坐标还和你的配置有关。本渣采用的配置是:

1460000006214079

如果改变上述参数,那么你所得到的坐标也会不同,你不妨多试试啦~

另外,即使上述参数不变,但如果你需要由某一点的坐标求出它所在tile的坐标的话,还需要注意Tiled Map的Y轴tile数目(之所以是Y轴,是因为上面Staggered Axis设置为Y)的奇偶性。这里也不解释了,直接上图最直观:

1460000006769138

'Y轴有奇数个tile(图中是五个),这里tile个数是这么算的:从最底端的tile沿斜线算与它有一条公共边的tile、一直算到最顶端的tile,例如从坐标(0, 4)(0, 3)(1, 2)(1, 1)到没有显示的(2, 0)'

1460000006214081

Y轴有偶数个tile(图中是六个)

更多Tiled Map Properties配置

Tile Layer Format最好选择压缩的格式,这样生成的tmx文件比较小。

1460000006214083

关于遮挡关系的排序函数

上一篇文章还提到建筑及装饰物之间的遮挡关系处理,本渣制定了一套规则来对建筑及装饰物做排序。需要注意的是,lua的table.sort要求排序函数是stable的,所以最好给每个要被比较的对象(这里就是建筑或装饰物)一个独一无二的id,对于两者“相等”这种情况就定义为比较id大小即可。

以下给出示例的伪代码,其中building就是被封装过的建筑或装饰物对象:

local function getLineOfBuildingRegion(building)

return {

left = building:getRegionLeftPos(),

right = building:getRegionRightPos(),

}

end

local function getDistX(line)

return line.right.x - line.left.x

end

local function getLowerPoint(line)

if line.left.y < line.right.y then

return line.left

else

return line.right

end

end

local function getHigherPoint(line)

if line.left.y > line.right.y then

return line.left

else

return line.right

end

end

local function isPointEqual(posA, posB)

return posA.x == posB.x and posA.y == posB.y

end

local function isLineEqual(lineA, lineB)

return isPointEqual(lineA.left, lineB.left) and isPointEqual(lineA.right, lineB.right)

end

local function getSlope(line)

return (line.right.y - line.left.y) / (line.right.x - line.left.x)

end

local function isLineParallel(lineA, lineB)

return getSlope(lineA) == getSlope(lineB)

end

local function isLowerThanLine(point, line)

local y = getSlope(line) * (point.x - line.left.x) + line.left.y

if point.y == y then

return y > getLowerPoint(line).y

else

return point.y < y

end

end

local function updateBuildingsZOrder(buildings)

table.sort(buildings, function(a, b)

if not isValidBuilding(a) then

return false

elseif not isValidBuilding(b) then

return true

end

local lineA = getLineOfBuildingRegion(a)

local lineB = getLineOfBuildingRegion(b)

if getDistX(lineA) > getDistX(lineB) then

return isLowerThanLine(getLowerPoint(lineB), lineA)

elseif getDistX(lineA) == getDistX(lineB) then

if isLineEqual(lineA, lineB) then

return a.id < b.id

elseif isLineParallel(lineA, lineB) then

if getLowerPoint(lineA).y == getLowerPoint(lineB).y then

return a.id < b.id

else

return getLowerPoint(lineA).y > getLowerPoint(lineB).y

end

else

if getLowerPoint(lineA).y > getLowerPoint(lineB).y then

return isLowerThanLine(getLowerPoint(lineB), lineA)

elseif getLowerPoint(lineA).y == getLowerPoint(lineB).y then

if getHigherPoint(lineA).y > getHigherPoint(lineB).y then

return isLowerThanLine(getLowerPoint(lineB), lineA)

elseif getHigherPoint(lineA).y == getHigherPoint(lineB).y then

return a.id < b.id

else

return not isLowerThanLine(getLowerPoint(lineA), lineB)

end

else

return not isLowerThanLine(getLowerPoint(lineA), lineB)

end

end

else

return not isLowerThanLine(getLowerPoint(lineA), lineB)

end

end)

for i, building in ipairs(buildings) do

building:setLocalZOrder(i)

end

end

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值