Cocos2dx 学习笔记(5) ---- 场景对象的创建与排序

前言

  紧跟上章,这章设计场景对象的创建管理.

  在今天的学习过程中,发现好多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__)

 效果

posted on 2013-03-12 14:18  Kevin Game  阅读(2434)  评论(0编辑  收藏  举报