【Cocos2dx 3.x Lua】TileMap使用

1、编辑TileMap地图资源

2、Cocos2dx 3.x Lua中使用TileMap

Link: http://codepad.org/P0nFP1Dx 
local TileMap=class("TileMap",function()
    local tilemap="scene/map/nearbg.tmx"
    return ccexp.TMXTiledMap:create(tilemap)
end)

TileMap.ctor=function(self)
    self._map={}
    self:init()
    self._rate=1.8 --TileMap在cc.ParallaxNode中的移动速率
end

TileMap.init=function(self)
    self._mapSize=self:getMapSize()
    local size=self._mapSize
    local obstacleLayer=self:getLayer("obstacle")
    local moveLayer=self:getLayer("move")
    obstacleLayer:setVisible(false)
    moveLayer:setVisible(false)

    for i=0,size.width-1 do
        self._map[i]={}
        for j=0,size.height-1 do
            if obstacleLayer:getTileAt(cc.p(i,j))~=nil then
                self._map[i][j]=0   --障碍物
            elseif moveLayer:getTileAt(cc.p(i,j))~=nil then
                self._map[i][j]=1   --可移动
            end
        end
    end

    self._scale=0.5
    self:setScale(self._scale)
    local s=self:getTileSize()
    self._tileSize=cc.size(s.width,s.height)
end

TileMap.getTileAtLayer=function(self,pTile)
    local obstacleLayer=self:getLayer("obstacle")
    local moveLayer=self:getLayer("move")
    if self._map[pTile.x][pTile.y]==0 then
        return obstacleLayer
    else
        return moveLayer
    end
end

--TileMap中添加Sprite
TileMap.addSprite=function(self,sprite,pTile)
    self:addChild(sprite, table.getn(self:getChildren()))
    sprite:retain()
    sprite:setPosition(self:tileToPixel(pTile))
    sprite:setAnchorPoint(cc.p(0.5,0.5))

    if sprite._name~=nil then
        sprite._moveBoard:setTileMap(self)
    end
end

--TileMap中删除Sprite
TileMap.removeSprite=function(self,sprite)
    self:removeChild(sprite)
end

----------------------------------------------------------------
--  说明:
--      由于使用tilemap,所有的sprite都是直接加入到tilemap中
--      对象使用的坐标系都是基于tilemap的,随着tilemap的移动
--      对象仍然是在地图上跟随地图移动,因此不需要加入地图相对屏幕
--      移动的相对坐标,使用sprite:getPosition()得到的坐标也是
--      基于tilemap的坐标系,例如,tilemap的格点大小为32*32,
--      sprite在tilemap上的格点为(2,11),同时地图缩放0.5,那么
--      使用sprite:getPosition得到的坐标为cc.p(2*32,11*32)
----------------------------------------------------------------
--TileMap坐标转换为TileMap格点坐标
TileMap.pixelToTile=function(self,point)
    --local pointMap=getRolePositionTable(self)
    --point=cc.pSub(point,pointMap)
    point.x =math.ceil(point.x / self._tileSize.width);
    point.y = math.ceil((self._tileSize.height * self._mapSize.height
        - point.y) /self._tileSize.height)
    return point
end

--TileMap格点坐标转换为屏幕坐标
TileMap.tileToPixel=function(self,pTile)
    local width = pTile.x * self._tileSize.width
    local height = (self._mapSize.height-pTile.y) * self._tileSize.height
    local point=cc.p(width,height)
    --local pointMap=getRolePositionTable(self)
    --point=cc.pAdd(pointMap,point)
    return point
end

TileMap.isTileMovable=function(self,pTile)
    if pTile.x >= self._mapSize.width or pTile.y >= self._mapSize.height then
        return false
    elseif self._map[pTile.x][pTile.y]==0 then
        return false
    else
        return true
    end
end

--在地图上添加Sword特效
TileMap.addSwordEffect=function(self,role,factor,callback)
    local pTile=self:pixelToTile(getRolePositionTable(role))
    local add=BaseDirection:getInstance():addWithDirection(factor,role._rotation)
    cclog(string.format("addSwordEffect:pTile(%f,%f),add:(%f,%f)",pTile.x,pTile.y,add.x,add.y))
    pTile=cc.pAdd(pTile,add)
    cclog(string.format("after added pTile(%f,%f)",pTile.x,pTile.y))
    if self:isTileMovable(pTile)==false then
        cclog("tilemap obstacle NA SwordEffect")
        if callback then
            callback()
        end
        return  --障碍物格点,不能释放技能
    end
    local sword=EffectManage:getInstance():trickEffectSword(callback)
    self:addSprite(sword,pTile)
    return pTile
end

TileMap.viewFollowX=function(self,point)
    local screenSize=cc.Director:getInstance():getVisibleSize()
    local mapSize=cc.size(self._mapSize.width*self._tileSize.width,
        self._mapSize.height * self._tileSize.height)
    local scale=self:getScale()
    mapSize=cc.size(mapSize.width*scale,mapSize.height*scale)
    local x=Max(point.x*scale,screenSize.width/2)
    local realPointX=cc.p(x,0)
    local scrollPoint=cc.pSub(cc.p(screenSize.width/2,0),realPointX)

    local mapXMin=-mapSize.width+screenSize.width
    if scrollPoint.x > mapXMin then --到达地图右边界,不能继续滑动
        return scrollPoint
    else
        return nil
    end
end

TileMap.create=function(self)
    return TileMap.new()
end

return TileMap

注:

如上红色部分标出了tilemap使用的一些用法,包括获取tilemap标记的层,在tilemap中动态添加对象,获取指定tile的精灵等

2、TileMap中添加视角跟随

代码片段一:(参考:http://blog.csdn.net/fansongy/article/details/8864561

[cpp] view plaincopyprint?

void HelloWorld::setViewPosition(CCPoint pos)
{
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();
    int x = max(pos.x,winSize.width/2);
    int y =max(pos.y,winSize.height/2);  

//  x = min(x,(m_tileMap->getMapSize().width*m_tileMap->getTileSize().width-winSize.width/2));
//  y = min(y,(m_tileMap->getMapSize().height*m_tileMap->getTileSize().height-winSize.height/2));  

    x = min(x,(m_tileMap->getContentSize().width-winSize.width/2));
    y = min(y,(m_tileMap->getContentSize().height-winSize.height/2));
    this->setPosition(ccp(winSize.width/2-x,winSize.height/2-y));
}  

参考资料2(http://blog.csdn.net/jukaiblog/article/details/8739021

接下来,我们为游戏加入场景滚动的效果。设想一下,随着人物的移动,原本不在视野内的地图需要逐渐显示出来。为了便于理解,先只讨论y轴上的场景滚动。假设勇士已经移动到Tilemap的(1,4)位置,对应cocos2d-x坐标为(32,224),如何计算出场景应该滚动多少距离?首先,将屏幕高度的1/2作为滚动的临界位置,y值小于1/2高度的不需要滚动,大于1/2的才开始滚动。为什么要把屏幕的1/2作为临界位置呢?因为这样可以保证场景在滚动时,人物始终处于屏幕高度的1/2处,这样的视觉效果最佳。当然也可以使用其他高度。现在计算出了屏幕的一半高度是320/2=160像素,而人物的y值为224,那么场景需要滚动的距离就是224-(320/2)=64像素。此外,还需要注意几点:

(1)如果地图总宽/高小于屏幕的宽/高,那么直接可以断定不需要滚动。

(2)场景滚动的最大距离不能超过地图总宽高减去屏幕宽高的1/2,否则在人物走到地图边缘时,场景继续滚动,会造成屏幕周围显示黑边。

(3)这里使用的“移动”是场景移动,而不是单纯的地图移动。实际上,我们需要连人带地图一起移动!人物相对屏幕的位置没有发生变化,仍然在屏幕1/2处。

好了,我们已经知道了场景滚动的原理,下面用代码来实现它。我们添加一个方法:setSceneScrollPosition。它有一个参数,是人物当前在cocos2d-x坐标系内的位置。此方法可以将场景移动到相应位置。首先在HelloWorldScene.h里面声明它,即添加“void setSceneScrollPosition(CCPoint position);”,然后在HelloWorldScene.cpp里实现此方法,在最后增加如下代码:

void HelloWorld::setSceneScrollPosition(CCPoint position)
{
    //获取屏幕尺寸
    CCSize screenSize=CCDirector::sharedDirector()->getWinSize();
    //计算Tilemap的宽高,单位是像素
    CCSize mapSizeInPixel=CCSizeMake(map->getMapSize().width*map->getTileSize().width,
        map->getMapSize().height*map->getTileSize().height);
    //取人物当前x坐标和屏幕中点x的最大值,如果人物的x值较大,则会滚动
    float x=MAX(position.x,screenSize.width/2.0f);
    float y=MAX(position.y,screenSize.height/2.0f);
    //地图总宽度大于屏幕宽度的时候才有可能滚动
    if(mapSizeInPixel.width>screenSize.width)
    {
        x=MIN(x,mapSizeInPixel.width-screenSize.width/2.0f);
    }
    if(mapSizeInPixel.height>screenSize.height)
    {
        y=MIN(y,mapSizeInPixel.height-screenSize.height/2.0f);
    }
    //人物的实际位置
    CCPoint heroPosition=ccp(x,y);
    //屏幕中点位置
    CCPoint screenCenter=ccp(screenSize.width/2.0f,screenSize.height/2.0f);
    //计算人物实际位置和中点位置的距离
    CCPoint scrollPosition=ccpSub(screenCenter,heroPosition);
    //将场景移动到相应位置
    this->setPosition(scrollPosition);
    CCLog("%f,%f",scrollPosition.x,scrollPosition.y);
}  

那么,什么时候使用setSceneScrollPosition方法呢?我们只能在游戏的每帧里做这件事情。我们新建一个schedule_selector:HelloWorld::update,设置其调用间隔为每帧,在里面实现对场景位置的更新。然后在场景初始化的时候启动定时器,并在析构函数里销毁定时器。

首先,我们在HelloWorldScene.h文件里声明update方法,添加代码“void update(float dt);”,然后在.cpp文件里实现它,即将下面代码添加到文件的最后。

void HelloWorld::update(float dt)
{
    //如果勇士不在行走状态,不需要更新场景位置
    if (isHeroWalking)
    {
        setSceneScrollPosition(heroSprite->getPosition());
    }
}  
时间: 2025-01-12 10:24:49

【Cocos2dx 3.x Lua】TileMap使用的相关文章

Cocos2d-x 3.2 Lua示例 CaptureScreen(截屏)

Cocos2d-x 3.2 Lua示例 CaptureScreen(截屏) 转载请注明:IT_xiao小巫 Cocos2d-x截屏功能是从3.2开始提供的,本篇博客就是介绍Cocos2d-x 3.2中Lua示例中的截屏功能.效果如下所示: 例子代码如下: --[[ 截屏测试 CaptureScreenTest ]]-- -- 获取屏幕大小 local winSize = cc.Director:getInstance():getWinSize() local kTagSprite = 1 loc

Cocos2d-x 脚本语言Lua中的面向对象

Cocos2d-x 脚本语言Lua中的面向对象 面向对象不是针对某一门语言,而是一种思想.在面向过程的语言也能够使用面向对象的思想来进行编程. 在Lua中,并没有面向对象的概念存在,没有类的定义和子类的定义.但相同在Lua中能够利用面向对象的思想来实现面向对象的类继承. 一.复制表的方式面向对象 --Lua中的面向对象 --[[ 复制表方式面向对象 參数为一张表.通过遍历这张表取值,赋给一张空表,最后返回新建的表.来达到克隆表 ]] function clone(tab) local ins =

Cocos2d-x 3.2 Lua示例 ClickAndMoveTest(点击移动测试)

Cocos2d-x 3.2 Lua示例 ClickAndMoveTest(点击移动测试) 本篇博客介绍Cocos2d-x 3.2Lua示例中点击移动的例子,在这个例子你可以得到如何创建单点触摸的事件和注册事件监听回调方法. 示例代码: --[[ ClickAndMoveTest.lua 点击与移动 ]]-- -- 获取屏幕尺寸 local size = cc.Director:getInstance():getWinSize() local layer = nil -- 层 local kTag

(原创)cocos2d-x 3.0+ lua 学习和工作(2) : 单一继承简单介绍

-- 星月相随倾心贡献~~~ -- 本章简单介绍一下:单一继承 -- 多继承本人还没有用过,主要是lua多继承感觉不好用~~~个人感觉~~~大汗~! -- example: local Base = class( "Base" ) Base.__index = Base function Base:ctor(...) print( self.__cname ) -- 输出:类名字.class( "xxx" ), self._cname 就是 xxx end func

Cocos2d-x 脚本语言Lua基本数据结构-表(table)

table是Lua中唯一的数据结构,其他语言所提供的数据结构,如:arrays.records.lists.queues.sets等,Lua都是通过table来实现,并且在lua中table很好的实现了这些数据结构.--摘自:<Programming in Lua> 看以下代码,可以很清晰的明白Lua中表的使用: -- Lua中的表,table Config = {hello="Hello Lua",world="World"} -- 赋值方式1,以键=

Cocos2d-x 3.2 Lua演示样本 ActionTest(操作测试)

Cocos2d-x 3.2 Lua演示样本 ActionTest(操作测试) 2014年博文大赛,请投上您宝贵的一票:http://vote.blog.csdn.net/Article/Details?articleid=38272837 移动开发狂热者群: 299402133,欢迎广大开发人员增加 Cocos2d-x官方真够给力的,3.1.1还没有熟悉完,3.2就出来.本篇博客继续介绍Cocos2d-x的Lua演示样例.关于3.2的样例变动不是非常大,略微介绍一下3.2的新特性吧: 3.2版本

(原创) cocos2d-x 3.0+ lua 学习和工作(4) : 公共函数(5): 返回指定表格中的所有键(key):table.keys

这里的函数主要用来做:返回指定表格中所有的键.参考资料为quick_cocos. 星月倾心贡献~~~ --[[ -- 返回指定表格中的所有键(key) -- example: local t = ( a = 1, b = 2, c = 3 ) local keys = table.keys( t ) -- keys = { "a", "b", "c" } -- @param t 要检查的表格(t表示是table) -- @param table

Cocos2d-x 3.2 Lua示例CocosDenshionTest(音频测试)

Cocos2d-x 3.2 Lua示例CocosDenshionTest(音频测试) 本篇博客介绍Cocos2d-x 3.2中Lua示例的音频测试,Cocos2d-x使用SimpleAudioEngine这个类来实现音频的控制,比如播放.暂停.停止等操作. Lua代码中,使用的是AudioEngine,具体实现可以参考AudioEngine.lua文件,只是把SimpleAudioEngin进行了封装. 示例代码: --[[ CocosDenshionTest.lua Cocos2d-x 音频支

笔记:利用Cocos2dx 3.3 lua 做一个动作类游戏(一)

在这之前,声明一下: 做不完我是小狗. 没办法,没毅力和恒心,之前的那个Quick Cocos2dx做的横版过关游戏的demo已经转成了3.3的版本了,其实也算是个半成品,战斗,UI啥的都有了,呵呵. 本次DEMO要达成的目的如下: 1 熟悉Cocos2dx 3.3 - lua 2 使用Joystick 3 完成简单的怪物AI 4 尝试扩展现有的api(可选) 嗯,差不多就以上了. 今天第一次笔记. 当前完成的任务有如下: 1 使用新的player新建项目 2 在场景中添加Sprite以及其帧动