前言
紧跟上章,这章设计场景对象的创建管理.
在今天的学习过程中,发现好多cocos2dx操作不便的地方,没有我以前接触的框架做的友好,也可能是我还没有完全了解吧.先列出来,知道的大神可以指点一下:
1. 脚本中的泄露好多,如果打开crtdbg,能发现好一堆....
2. 对打包资源的支持不够灵活,接口分离,比如如果我要将脚本打包读取,那么就有很多的接口重新封装,比如require的调用.
3. 关于精灵的静态创建接口....
问题
请教一个问题:
如果我的场景中有一层Tmxtilemap, 我通过getchildBytag获取到它,怎么能够调用它本身的方法,比如:
1).--local mapLayer = scene:getMapLayer(); // 这个是我自己定义的接口,直接导出TmxTileMap*,是可以的
2).local mapLayer = scene:getChildByTag( ESLT_GROUND ); // 这个是不行的,getMapOrientation找不到.
if mapLayer and mapLayer:getMapOrientation() == CCTMXOrientationIso then .....
设计选择
引擎提供了多个精灵的静态创建方法,并提供了一个userData指针来保存对象的逻辑属性,但是这个需要自己管理属性集合,放在C++中实现比较合适,所以我初步考虑实现CSceneObject类,来封装场景精灵对象.
为了直接更直观,便捷的管理CSceneObject,创建ObjectLayer.
代码片段
1. CObjectLayer
// -------------------------------------------------------
// 文件名: ObjectLayer.h
// 描 述: 对象层
// 日 期: 12/3/2013
// 作 者: KevinYuen
// 版 权: Copyright (C) 2011 - All Rights Reserved
// 备 注:
// -------------------------------------------------------
#ifndef _OBJECTLAYER_H_
#define _OBJECTLAYER_H_
#include "cocos2d.h"
USING_NS_CC;
class CSceneObject;
class CObjectLayer : public CCLayer
{
public:
~CObjectLayer();
public:
// 添加对象
CSceneObject* addObject( CCSpriteFrame *pSpriteFrame );
// 删除对象
bool delObject( int tag );
// 查找对象
CSceneObject* getObject( int tag );
public:
// 实例创建
CREATE_FUNC( CObjectLayer );
private:
CObjectLayer();
int m_ObjectTagTracker; // Tag计数器
};
#endif
#include "ObjectLayer.h"
#include "SceneObject.h"
CObjectLayer::CObjectLayer() : m_ObjectTagTracker(1)
{
}
CObjectLayer::~CObjectLayer()
{
}
// 添加对象
// 返回自动产生的一个当前层唯一的tag
CSceneObject* CObjectLayer::addObject( CCSpriteFrame *pSpriteFrame )
{
// 创建
CSceneObject* pNew = CSceneObject::create();
if( !pNew || !pNew->initWithSpriteFrame( pSpriteFrame ) ) return NULL;
// 加入
addChild( pNew, 0, m_ObjectTagTracker++ );
return pNew;
}
// 删除对象
bool CObjectLayer::delObject( int tag )
{
CCNode* pObject = getChildByTag( tag );
if( !pObject ) return false;
this->removeChild( pObject );
return true;
}
// 查找对象
CSceneObject* CObjectLayer::getObject( int tag )
{
return dynamic_cast<CSceneObject*>( getChildByTag( tag ) );
}
2. 场景对象
// -------------------------------------------------------
// 文件名: SceneObject.h
// 描 述: 场景对象
// 日 期: 12/3/2013
// 作 者: KevinYuen
// 版 权: Copyright (C) 2011 - All Rights Reserved
// 备 注:
// -------------------------------------------------------
#ifndef _SCENEOBJECT_H_
#define _SCENEOBJECT_H_
#include "cocos2d.h"
USING_NS_CC;
class CSceneObject : public CCSprite
{
public:
virtual ~CSceneObject();
CREATE_FUNC( CSceneObject );
public:
// 后期扩展接口
private:
// 后期增加属性集合
};
#endif
#include "SceneObject.h"
CSceneObject::~CSceneObject()
{
}
3. 脚本使用
--------------------------------------------------------
--文件名: main.lua
--描 述: 主脚本
--日 期: 11/3/2013
--作 者: KevinYuen
--版 权: Copyright (C) 2011 - All Rights Reserved
--备 注:
---------------------------------------------------------
-- 跟踪绑定执行函数发生错误的信息并输出
function __G__TRACKBACK__(msg)
print("----------------------------------------")
print("LUA ERROR: " .. tostring(msg) .. "\n")
print(debug.traceback())
print("----------------------------------------")
end
-- 主函数
local function main()
-- 创建主场景
local scene = CMainScene:create();
if not scene then
print( "Create main scene failed!" );
return;
end
-- 加载测试场景
-- 引擎对CCTMXTiledMap有限制,每一层只能有一个瓦块包,也就是一张纹理
if not scene:loadScene( "TilesMap/Isotile_2.tmx" ) then
print( "Load tilemap failed!" );
return;
end
local mapLayer = scene:getMapLayer();
--local mapLayer = scene:getChildByTag( ESLT_GROUND );
if mapLayer and mapLayer:getMapOrientation() == CCTMXOrientationIso then
require( "script/control_iso" );
createControl( scene );
end
-- 创建一个精灵帧序列
local frameCache = CCSpriteFrameCache:sharedSpriteFrameCache();
frameCache:addSpriteFramesWithFile( "animations/redRobot-hd.plist" );
-- 这里暂时用这个作为Z排序的算法,保证遮挡顺序
local function getZOrder( posY )
local visibleSize = CCDirector:sharedDirector():getVisibleSize()
local y = visibleSize.height - posY;
return y;
end
-- 这里如果使用getChildByTag无法转换为CObjectLayer,谁知道为什么,请教一下 :)
local objectLayer = scene:getObjectLayer();
if objectLayer then
local sframe = frameCache:spriteFrameByName( "01.png" );
local sprite1 = objectLayer:addObject( sframe );
sprite1:setPosition( 400, 300 );
objectLayer:reorderChild( sprite1, getZOrder( 300 ) );
sframe = frameCache:spriteFrameByName( "03.png" );
local sprite2 = objectLayer:addObject( sframe );
sprite2:setPosition( 400, 300 );
objectLayer:reorderChild( sprite2, getZOrder( 300 ) );
sframe = frameCache:spriteFrameByName( "05.png" );
local sprite3 = objectLayer:addObject( sframe );
sprite3:setPosition( 500, 300 );
objectLayer:reorderChild( sprite3, getZOrder( 300 ) );
-- 计时回调,用于精灵的移动
local function tick()
local x, y = sprite2:getPosition();
if y > 400 then
y = 160
end
y = y + 1;
sprite2:setPositionY(y)
objectLayer:reorderChild( sprite2, getZOrder( y ) );
end
-- 加入日程表,间隔为0代表每帧
CCDirector:sharedDirector():getScheduler():scheduleScriptFunc(tick, 0, false)
end
-- 设定为当前场景并执行
CCDirector:sharedDirector():runWithScene( scene );
end
-- 执行脚本函数并捕获错误信息
-- 函数原型: xpcall( 调用函数, 错误捕获函数 );
xpcall(main, __G__TRACKBACK__)