Connecting with cocos2d-x
与Cocos2d-x进行连接
For any non-trivial use of CocosBuilder you will need to connect your ccb-files with your code. This section explains how this works.
对于CocosBuilder来,任何有意义的使用,你将需要连接你的ccb文件到你的代码。本章将解释这如何工作
Using Custom Classes
使用自定义类
The way you can link your code with CocosBuilder is to use custom classes. To assign a custom class to an object in CocosBuilder, just select the object then enter the name of your custom class in the property inspector. Remember that your custom class needs to be a sub class of the selected object.
这是一种可以连接你的代码到CocosBuilder 来使用自定义类的方式。指定一个“自定义类”到CocosBuilder中的对象,只需要选择对象,然后输入你的自定义类的名字在属性栏中。记住,你的自定义类需要是你选中的对象的类的子类。(比如,一个CocosBuilder中的一个Sprite对象自定义类,必须派生自Sprite类)
When loading the ccbi-file, you need to create two custom classes (could be one).
在加载ccbi文件时,你需要创建两个自定义类(也可以是一个)。
The *custom loader* class derives from *cocos2d::extension::CCLayerLoader*.
自定义加载器类类派生自"cocos2d::extension::CCLayerLoader"
The *custom layer* class derives from *cocos2d::extension::CCBSelectorResolver*
,*cocos2d::extension::CCBMemberVariableAssigner*
,*cocos2d::extension::CCBMemberVariableAssigner*
, and *cocos2d::extension::CCNodeLoaderListener* classes.
自定义层类派生自cocos2d::extension::CCBSelectorResolver
,*cocos2d::extension::CCBMemberVariableAssigner*
,*cocos2d::extension::CCBMemberVariableAssigner*
, 和*cocos2d::extension::CCNodeLoaderListener* classes.
In your custom loader class you need to add code for initialization such as
在你的自定义加载器类中,你需要像这样添加初始代码:
public:
CCB_STATIC_NEW_AUTORELEASE_OBJECT_METHOD(CustomLayerLoaderClass, loader);
CCB_VIRTUAL_NEW_AUTORELEASE_CREATECCNODE_METHOD(CustomLayerClass));
CCBReader will initialize your custom layer class using the loader class's *loader* method.
CCBReader 将使用加载器类的“ loader”方法来初始化你的自定义层类。
Please note that CCBReader will not be able to use any custom init methods. To use a custom init method, you can call it from the custom layer class constructor.
将注意,CCBReader 将不会使用任何自定义的init方法。为了使用自定义的初始化方法,你可以在自定义层的类构造函数中调用它。
Linking Member Variables
连接成员变量
References to objects in your ccbi-file can be linked to member variables when the file is loaded. These member variables can be either in the root node of the document, in which case it must have been assigned a custom class.
引用你的ccbi文件中的对象,可以在文件加载时连接到成员变量。这些成员变量可以在文档的根节点中,这种情况,他必须被复制到一个自定义类中。
To link an object, simply declare them in the header file,
通过在头文件中简单的声明他们来连接对象。
To initialize member variables, you can override the onAssignCCBMemberVariable function in the custom layer class and use something like
你可以在自定义层类中,重写onAssignCCBMemberVariable 函数,并使下面的代码来初始化成员变量
CCB_MEMBERVARIABLEASSIGNER_GLUE(this, "sprtBurst", CCSprite *, this->mSprtBurst);
where *sprtBurst* is the property name set in CocosBuilder.
“sprtBurst”是CocosBuilder中设置的属性名.
Select the object in CocosBuilder, under Code Connections change the *Don't assign* popup menu to either *Doc* root var or *Owner var*. Then enter the name of your member variable to the right of the popup menu.
在CocosBuilder中选择对象,在“代码连接“弹菜单中,从”Don't assign*改成”Doc root val"或者"Owner var". 然后在弹出菜单右侧输入你的成员变量名。
Adding Callbacks to Menus
为菜单添加回调
To add a callback when a CCMenuItemImage is tapped, simply select the CCMenuItemImage in CocosBuilder, then add the name of the method you want to call in the *Selector* field. Set the target either to the *Document root* or the *Owner*.
添加CCMenuItemImage轻触的回调,只需要简单的在CocosBuilder中选择CCMenuItemImage,然后添加你想要调用的方法名在Selector字段中。设置目标为“DocumentDocument root“或”Owner"
The callback will send the CCMenuItemImage as its only parameter to the method that you specify (it uses the id type, and is often named *sender*). You can also chose to leave the parameter out.
CCMenuItemImage将会作为你指定的回调方法的唯一参数进行传递(在OC中经常使用ID类型,并且经常明明问sender,在C++中,通常为cocos2d::Object* sender).你也可以选择无视这个参数.
In your custon class, you override the *onResolveCCBCCMenuItemSelector* function and add code such as
在你的自定义类中,重写函数"onResolveCCBCCMenuItemSelector"像这样添加代码
CCB_SELECTORRESOLVER_CCMENUITEM_GLUE(this, "pressedA:", MenuTestLayer::onMenuItemAClicked);
inside the function.
在函数中.
where *MenuTestLayer* is the name of your custom class.
"MenuTestLayer"是你的自定义类名.
MenuTestLayer::onMenuItemAClicked can then be declared as
MenuTestLayer::onMenuItemAClicked 可以可以这样声明:
void MenuTestLayer::onMenuItemAClicked(cocos2d::CCObject *pSender) {
}
Adding Callbacks to CCControl
添加回调到CCControl
Adding a callback to a CCControl is similar to adding a callback to a CCMenuItemImage, it just have a few extra options.
添加回调到CCControl和添加回调到CCMenuItemImage是相似的,只是有一些额外的选项。
Tick the event types that you want to receive callbacks for. For CCControlButton it is most common to use the *Up inside* callback only. Select your target, either *Document root* or *Owner*, and the name of your callback method. The callback method can optionally take two arguments, the sender (i.e. the CCControl) and the type of event. The event types are defined in *CCControl.h*.
在你想收到回调的消息类型上进行标记(CheckBox). 对于CCControlButton最常用的就是只使用"Up inside"回调.选择你的目标,要么Document root,要么Owner,还有你的回调函数的名字.. 回调方法有两个可选实参,sender 和事件类型.事件类型在CCControl.h文件中进行定义
In the custom class, you override the *onResolveCCBCCControlSelector* function and add code such as
在自定义类型,重写onResolveCCBCCControlSelector函数,并且添加代码如下:
CCB_SELECTORRESOLVER_CCCONTROL_GLUE(this, "pressedMenus:", MenuTestLayer::onPressedMenus);
inside the function. Where *MenuTestLayer* is the name of your custom class.
在函数中,MenuTestLayer是你的自定义类名
MenuTestLayer::onPressedMenus can then be declared as
MenuTestLayer::onPressedMenus可以被声明为
void HelloCocosBuilderLayer::onMenuTestClicked(CCObject * pSender, cocos2d::extension::CCControlEvent pCCControlEvent) {
}
Options for Loading ccb-files
加载ccb文件的选项
CCBReader *ccbReader = new cocos2d::extension::CCBReader(ccNodeLoaderLibrary);
CCNode* myNode = ccbReader->readNodeGraphFromFile("MyNodeGraph.ccbi");
The initialization for ccNodeLoaderLibrary can be done in two ways.
1. If you're using a custom class:
CCNodeLoaderLibrary * ccNodeLoaderLibrary = CCNodeLoaderLibrary::newDefaultCCNodeLoaderLibrary();
ccNodeLoaderLibrary->registerCCNodeLoader("HelloCocosBuilderLayer", HelloCocosBuilderLayerLoader::loader());
In this case, *HelloCocosBuilderLayer* is the name of the custom class specified in CocosBuilder
2. If not using a custom class, you can initialize a default NodeLoader:
CCNodeLoaderLibrary * ccNodeLoaderLibrary = CCNodeLoaderLibrary::newDefaultCCNodeLoaderLibrary();
You may need to cast the returned value depending on what sort of object is the root node in your ccbi-file and how you will use it in your code. For instance, if you load a CCParticleSystem, use the following code.
CCParticleSystem* myParticles = (CCParticleSystem*) ccbReader->readNodeGraphFromFile("MyParticleSystem.ccbi");
For your convenience, CCBReader can also wrap your node graph in a scene. To load your ccbi-file in a scene call _sceneWithNodeGraphFromFile:_
CCScene* myScene = ccbReader->sceneWithNodeGraphFromFile("MyScene.ccbi");
### Passing an Owner Variable
Sometimes you need to be able to access member variables from and get callbacks to another object than the root node of a ccb-file. To do this you will need to pass a *owner* to the CCBReader. To get the variable or callback assigned to the owner, make sure that you've selected owner when declaring the member variable name or callback in CocosBuilder. The call the *nodeGraphFromFile(file, owner)* or *sceneWithNodeGraphFromFile(file, owner)* method of CCBReader when loading your file.
HelloCocosBuilderLayer *pOwner = new HelloCocosBuilderLayer();
CCNode* myNode = ccbReader->readNodeGraphFromFile("MyNodeGraph.ccbi", pOwner);
### Accessing Variables and Callbacks in a sub ccb-file
If you are using sub ccb-files specifying the root node as target will refer to the root node of the sub ccb-file. The owner target is the object that you pass to the CCBReader.
## Example
Please take a look at *HelloCocosBuilderLayer.h*, *HelloCocosBuilderLayer.cpp*, and *HelloCocosBuilderLayerLoader.h* from the ExtensionsTest in the TestCPP project of cocos2d-x.
## Setting scale and design size
For CocosBuilder based projects in cocos2d-x, the AppDelegate needs to setup the game to read the correct resources from the correct directories from the project files. It is based on the device screen size. You also need to set the scaling factor and the design resolution size of the GL view.
For portrait mode, you can add this code to *AppDelegate.cpp* in *AppDelegate::applicationDidFinishLaunching*
CCSize designSize = CCSizeMake(320, 480);
CCSize resourceSize = CCSizeMake(320, 480);
CCSize screenSize = CCEGLView::sharedOpenGLView()->getFrameSize();
std::vector<std::string> searchPaths;
std::vector<std::string> resDirOrders;
TargetPlatform platform = CCApplication::sharedApplication()->getTargetPlatform();
if (platform == kTargetIphone || platform == kTargetIpad)
{
searchPaths.push_back("Published-iOS"); // Resources/Published-iOS
CCFileUtils::sharedFileUtils()->setSearchPaths(searchPaths);
if (screenSize.height > 768)
{
resourceSize = CCSizeMake(1536, 2048);
resDirOrders.push_back("resources-ipadhd");
}
else if (screenSize.height > 640)
{
resourceSize = CCSizeMake(768, 1536);
resDirOrders.push_back("resources-ipad");
}else if (screenSize.height > 480)
{
resourceSize = CCSizeMake(640, 960);
resDirOrders.push_back("resources-iphonehd");
}
else
{
resDirOrders.push_back("resources-iphone");
}
CCFileUtils::sharedFileUtils()->setSearchResolutionsOrder(resDirOrders);
}
else if (platform == kTargetAndroid || platform == kTargetWindows)
{
if (screenSize.height > 960)
{
resourceSize = CCSizeMake(640, 960);
resDirOrders.push_back("resources-large");
}
else if (screenSize.height > 480)
{
resourceSize = CCSizeMake(480, 720);
resDirOrders.push_back("resources-medium");
}
else
{
resourceSize = CCSizeMake(320, 568);
resDirOrders.push_back("resources-small");
}
CCFileUtils::sharedFileUtils()->setSearchResolutionsOrder(resDirOrders);
}
pDirector->setContentScaleFactor(resourceSize.width/designSize.width);
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionShowAll);
For landscape mode, you can change the order of resolutions. So (320, 480) becomes (480,320) , (640, 960) becoms (960, 640) etc. in all places.