[置顶] 使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面
[Cocos2d-x相关教程来源于红孩儿的游戏编程之路CSDN博客地址:http://blog.csdn.net/honghaier
使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面
游戏的UI界面编程是一个既重要,又麻烦的工具。如何能够更快的完成界面的处理是游戏开发中一个必须要面对的问题。其实现在已经有很多工具能够完成界面的编辑和导出,比如mygui,CEGUI,CocosBuilder等。今天呢?我就向大家隆重自荐一下本人开发的“红孩儿工具箱”,通过一个简单的编辑过程让大家感受一下游戏开发中如何处理界面才更快,效率更高。
红孩儿工具箱 0.1.7 版本
下载地址:红孩儿工具箱用户QQ群: 20970366及红孩儿Cocos2d-x学习园地QQ群共享
下载后的目录如下:
这里要说明的是Editor.ini:这是工具的配置文件,它里面有
[ResDir]
ResDir=IMAGE
注意:ResDir用于指定资源所在目录。这个很关键,工具所用到的所有图片必须放在这个目录下。
[UIInfo]
PicDir =IMAGE\UI
注意:RicDir用于指定资源中UI图片所在目录。这只是为了方便在选图时的默认打开路径。并不是说使用到的图片就必须是在UI目录中。
第一步:我们先将我们的资源放在此目录下。
好,我们现在利用这些资源来制做一个游戏动画界面,要求为:
(1) 有不停UV滚动的背景图。
(2) 有一个LOGO面板。
(3) 有一个问号按钮,能够响应按下事件,按下后弹出一个金币或者一朵咬人花.
嘿嘿,有点意思吧?
OK,下面运行程序:
输入game2z.com论坛注册的账号和密码,点击“登录”进入工具的主界面。
第二步:为了提高渲染的效率,我们需要将一些图片进行合并处理,在拼图界面,选择相应的资源目录,然后点击“立即导出!”,我们就可以进行图片的合并。
注意:bk这张图是使用纹理UV滚动的,这种情况不能合并进来,另外Cocos2d-x对于这类纹理要求是2的幂次方的宽高。
合并完之后:
第三步:将所用到的动画进行处理:
打开“动画编辑”界面,然后在左边的树列表中增加一个图片结点,之后对其右键弹出菜单项中点击“创建固定帧间隔的关键帧动画”。在弹出的对话框中选择“拼合图生成”,之后在选图对话框中找到相应的拼合图后确点。
我们先做一下花的序列帧,点击”flower1.png”,然后双击它或者点击“应用此图块”,之后就可以返回到固定关键帧间隔动画的生成对话框:
这里面会自动的将flower系列图块加入进来,我们修改一下间隔时间为500毫秒。点击“确定”后会在动画编辑界面生成相应的动画。
点击下方的帧展示面板右边的“播放动画”,即可看到此动画的播放演示。
现在我们将其保存为flower.ani.在弹出的动画名称输入框中输入“flower”:
点击“导出”后在相应的目录内导出动画:
保存的ani文件是工具编辑使用的文件。导出的gan文件(GAME ANI)即是可以在Cocos2d-x中使用的动画最终文件。
这样我们就将咬人花的动画编辑好了。现在我们可以点击“新建动画”,然后创建一个新图片结点,设定其使用图片coin3.png,然后在下面的帧显示区域中第二帧和第三帧的位置右键弹出菜单中新增两个关键帧。我们在第二帧中双击图片结点设定其使用图片coin2.png,并点击选中它之后右键弹出菜单中选中“调整相对位置”。在Y值框里填写-50,将其Y值设为向上抬高50像素。
同样的方式,在第三帧我们设定图片结点选用coin1.png并点击选中它之后右键弹出菜单中选中“调整相对位置”。在Y值框里填写-100,将其Y值设为向上抬高100像素。
点击“播放动画”我们就可以看到一个向上跳出金币的动画。
保存为cion.ani并导出cion.gan文件。
现在呢,我们来做一下背景动画。
新建动画,命名为“bk”,然后新建一个图片结点,双击它或者在右边面板的“选择图片”打开选图对话框,然后我们找到这张背景图。
点击“打开”后这张背景图就会被加进来。选中它后点击“应用此图片”。
注意:如果图片过大我们可以先点击“限制大小”,这样对话框就被限制大小了。更易操作。
现在这个图片就被加入动画编辑区域里了,我们把帧间隔调整为30毫秒。然后在下面帧显示条上第50帧处右键,在弹出菜单中点击“加入关键帧”,然后修改右边面板“纹理横向偏移”,输入“1.0”。
保存,导出为bk.ani和bk.gan。
第四步:现在我们要来编辑界面了。点击“界面编辑”,然后在上面一排控件中最左边选择“面板”,在主视窗中拖动创建出一个面板。
从左上角到右下角拖动创建好面板后松开鼠标,即可看到一个空白面板产生出来,我们点击选中它,可以在右边的属性编辑区域里输入位置和宽高来调整它,并点击“Normal_Image”对应按钮来选择一张图片或动画。
在弹出的选择UI图片对话框里我们点击“加载资源文件”,找到之前做的背景动画bk.ani.
选中后点击“应用此动画”,这样面板就应用了这个动画。
在左边的控件树结点”UICtrl1_Rect”上右键弹出菜单中点击“增加子结点_面板”,新增一个面板并放置中间。
点击选中子面板,按照上面的方法为其设定标题图片。
这里注意选择ImageShowType属性值为“改变控件”,即按照标题图大小来重设控件大小。
修改好后:
下面我们来增加一个按钮控件,在左边的控件树结点”UICtrl1_Rect”上右键弹出菜单中点击“增加子结点_按钮”,新增一个按钮并放置中间靠下位置。
然后我们设定其Normal_Image项为UI_Pack_0.png中的ob5_2.png,设定LButtonDown_Image为ob5_0.png。这样我们就成功创建了按钮。
按钮创建成功后,我们再继续为按钮结点”UICtrl3_Button”新增一个面板动画。设定其使用金币动画,放置在按钮所在位置,我们在这里先将它的Visible设为False,留待Cocos2d-x中运行时点击按钮再设为显示。
同样做法我们为按钮结点”UICtrl3_Button”新增一个面板动画。设定其使用咬人花动画,放置在按钮上面位置,我们在这里也将它的Visible设为False。
现在我们保存为mali.xml并导出mali.ui。
OK,所有的编辑工作都做完了。现在我们将尝试在Cocos2d-x中运行它。
我们打开编辑器资源目录IMAGE\UI,将所要用到的文件拷到Cocos2d-x的HelloCpp工程中的资源目录中。
工具箱资源目录:红色框选的是要拷到Cocos2d-x工程中使用的资源。
然后我们将对应的游戏开发库中的include设置为工程的包含目录。Lib设置为工程的库目录。并将HHRLib_d.lib和HHRLib.lib分别加到工程的debug和release引用库中。
现在我们打开HelloWorldScene.h。为按钮按下时创建一个回调函数:
class HelloWorld : public cocos2d::CCLayer { public: // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone virtual bool init(); // there's no 'id' in cpp, so we recommend returning the class instance pointer static cocos2d::CCScene* scene(); // a selector callback void menuCloseCallback(CCObject* pSender); //设置按钮按下时响应的回调函数 void OnBtnClicked(CCNode* pSender, void* data); //设置动画结束时响应的回调函数 void OnAniEnd(CCNode* pSender, void* data); CREATE_FUNC(HelloWorld); };
对应的CPP:
bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !CCLayer::init() ) { return false; } CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin(); ///////////////////////////// // 2. add a menu item with "X" image, which is clicked to quit the program // you may modify it. // add a "close" icon to exit the progress. it's an autorelease object CCMenuItemImage *pCloseItem = CCMenuItemImage::create( "CloseNormal.png", "CloseSelected.png", this, menu_selector(HelloWorld::menuCloseCallback)); pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2 , origin.y + pCloseItem->getContentSize().height/2)); // create menu, it's an autorelease object CCMenu* pMenu = CCMenu::create(pCloseItem, NULL); pMenu->setPosition(CCPointZero); this->addChild(pMenu, 1); ///////////////////////////// // 3. add your codes below... // add a label shows "Hello World" // create and initialize a label CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", TITLE_FONT_SIZE); // position the label on the center of the screen pLabel->setPosition(ccp(origin.x + visibleSize.width/2, origin.y + visibleSize.height - pLabel->getContentSize().height)); // add the label as a child to this layer this->addChild(pLabel, 1 , 200); //加载界面 CGameUI* pNewUI = new CGameUI(); pNewUI->LoadUITree("mali.ui"); //设置界面的位置 pNewUI->setOffset(visibleSize.width/2, visibleSize.height/2); this->addChild(pNewUI,1,100); //取得按钮 CUICtrl* pUICtrl = pNewUI->QueryUICtrl("UICtrl3_Button"); if(pUICtrl) { CUIButton* pUIButton = dynamic_cast<CUIButton*>(pUICtrl); if(pUIButton) { //设置在按下时响应的回调函数,可带自定义参数。 pUIButton->setClickBeginCallFuncND(CCCallFuncND::create(this, callfuncND_selector(HelloWorld::StartCionAni), (void*)0xbebabeba)); } } //金币动画面板 pUICtrl = pNewUI->QueryUICtrl("UICtrl4_Rect"); if(pUICtrl) { CUIRect* pAniRect = dynamic_cast<CUIRect*>(pUICtrl); if(pAniRect) { C2DSkinAni* pSkinAni = pAniRect->getSkinAni(); if(pSkinAni) { pSkinAni->SetEndFrameCallFuncND(CCCallFuncND::create(this, callfuncND_selector(HelloWorld::AniEndFrame), (void*)0xbebabeba)); } } //咬人花动画面板 pUICtrl = pNewUI->QueryUICtrl("UICtrl5_Rect"); if(pUICtrl) { CUIRect* pAniRect = dynamic_cast<CUIRect*>(pUICtrl); if(pAniRect) { C2DSkinAni* pSkinAni = pAniRect->getSkinAni(); if(pSkinAni) { pSkinAni->SetEndFrameCallFuncND(CCCallFuncND::create(this, callfuncND_selector(HelloWorld::OnAniEnd), (void*)0xbebabeba)); } } } } return true; }
回调函数的处理:
//设置在点击按钮时响应的函数 void HelloWorld::OnBtnClicked(CCNode* pSender, void* data) { CCNode* pNode = getChildByTag(100); if(pNode) { CGameUI* pMainUI = dynamic_cast<CGameUI*>(pNode); if(pMainUI) { //随机产生金币动画或咬人花动画 float r = CCRANDOM_0_1(); if(r > 0.5) { CUICtrl* pUICtrl = pMainUI->QueryUICtrl("UICtrl4_Rect"); if(pUICtrl) { CUIRect* pAniRect = dynamic_cast<CUIRect*>(pUICtrl); if(pAniRect) { C2DSkinAni* pSkinAni = pAniRect->getSkinAni(); if(pSkinAni) { pSkinAni->Play(1); pSkinAni->setVisible(true); pAniRect->setVisible(true); } } } } else { CUICtrl* pUICtrl = pMainUI->QueryUICtrl("UICtrl5_Rect"); if(pUICtrl) { CUIRect* pAniRect = dynamic_cast<CUIRect*>(pUICtrl); if(pAniRect) { C2DSkinAni* pSkinAni = pAniRect->getSkinAni(); if(pSkinAni) { pSkinAni->Play(1); pSkinAni->setVisible(true); pAniRect->setVisible(true); } } } } } } } //设置在动画结束时响应的函数 void HelloWorld::OnAniEnd(CCNode* pSender, void* data) { CCNode* pNode = getChildByTag(100); if(pNode) { CGameUI* pMainUI = dynamic_cast<CGameUI*>(pNode); if(pMainUI) { //将金币动画设为不显示 CUICtrl* pUICtrl = pMainUI->QueryUICtrl("UICtrl4_Rect"); if(pUICtrl) { CUIRect* pAniRect = dynamic_cast<CUIRect*>(pUICtrl); if(pAniRect) { C2DSkinAni* pSkinAni = pAniRect->getSkinAni(); if(pSkinAni) { pSkinAni->setVisible(false); } } } //将咬人花动画设为不显示 pUICtrl = pMainUI->QueryUICtrl("UICtrl5_Rect"); if(pUICtrl) { CUIRect* pAniRect = dynamic_cast<CUIRect*>(pUICtrl); if(pAniRect) { C2DSkinAni* pSkinAni = pAniRect->getSkinAni(); if(pSkinAni) { pSkinAni->setVisible(false); } } } } } }
好了,现在编译并运行。
或者有时候是出现咬人花
OK,总实算是完成了~,这样我们就实现了一个完整的动画控制界面。希望大家在这个过程中学到一些动画和界面制做的思想,能够更好的开发出精美的游戏。下次再见!