到本系列文章的前四篇为止,我们已经完成了一个简单的游戏,Ray Wenderlic的那篇文章也翻译完了。但实际上工作还没有结束。游戏开发者应该没人愿意像前文那样,把图片和音乐资源存储在公开的文件目录下,被人拷走就能轻易被山寨了。所以这篇里我们先来讲下怎么对资源进行打包,最后和程序混在一起,编译成一个二进制文件发布。这个资源打包工作是uPhone机制提供的。
一、图片和音乐资源打包
前面的Cocos2dSimpleGame中,如上图,我们一共使用了5张图片资源:
图片名称 |
图片用途 |
CloseNormal.png |
关闭按钮的正常状态图片 |
CloseSelected.png |
关闭按钮被点击时的图片 |
Player.png |
带头大哥 |
Projectile.png |
带头大哥的暗器 |
Target.png |
不知死活的小喽啰 |
下面,我们使用Uphone开发平台自带的资源编辑器TOPS Builder将资源进行打包。步骤如下:
1. 使用 TOPS Builder 打开游戏的资源工程:
双击 D:\Work7\cocos2d\Cocos2dSimpleGame\Res\Cocos2dSimpleGame_Res.TRG 文件,这就打开了游戏的资源工程,运行的界面如下图:
2. 将需要使用的图片和音乐添加到资源编辑器中
在资源编辑器中添加图片的示意图如下:
- 首先,单击图中 1 所示的"Bitmaps"标签,进入图片资源编辑分页;
- 然后,右击图中 2 所示的空白区域,弹出如图中 3 所示的菜单,选择“添加图片”,即可选择图片加到资源比编辑器中。
- 添加成功后,图中 2 所示的空白区域会把已添加的图片名字列出。
- 使用同样的方法添加音乐资源(mp3,wav等),但注意第一步选资源类型时,应点到"Raw data"标签内
3. 对添加的资源进行编译
在资源编辑器中,点击界面左上角的闪电符号按钮,对资源进行编译。
注意:在进行编译之前,需要讲使用的图片、音月资源文件添加到代码的Visual Studio工程中,添加后Visual Studio工程的文件视图如下:
注意:此编译过程是将图片文件的数据以 Uphone 内部的结构形式保存到 .h 文件中,并为每个图片资源分配一个资源 ID,在应用中通过该 ID 使用该图片资源。编译后,你可以看到这个巨大的.h文件D:\Work7\cocos2d\Cocos2dSimpleGame\Res\cocos2dsimplegame_res_def.h 。
通过上面的几个简单步骤,我们就完成了资源打包。这样我们的游戏在编译完成后,资源和代码就在同一个二进制包里了
二、在cocos2d游戏中使用打包的资源
资源打包的工作完成了。接下来我们就可以在cocos2d游戏中使用这些资源了。使用前,我们先了解一下普通的Uphone应用是如何使用打包资源的
1. 普通Uphone应用使用打包资源的方法
在Uphone SDK中,有一个TResource类,这个类提供了静态接口函数用于获取当前上下文的bitmap和rawdata资源数据,接口及注释是这样的:
@brief 获取当前上下文资源里的图片类实例。
此函数返回的TBitmap实例,无须释放。
@param nResId 资源ID。
@return TBitmap指针。
*/
static const TBitmap * LoadConstBitmap(Int32 nResId);
/**
@brief 获取当前上下文资源里的原始数据。
此函数直接返回资源中的原始数据的地址(即原始数据内容不可更改)。
@param nResId 资源ID。
@param puLength 原始数据长度。
@return 原始数据指针。
*/
static const void * LoadConstRawData(Int32 nResId, UInt32 * puLength = NULL);
所以,在Uphone应用中只要使用如下代码就可以加载图片资源了:
2. cocos2d-x游戏中使用打包资源的方法
上面的资源调用方法对cocos2d-x开发者来说功能不够强、不够跨平台,也不能很好地解决不同分辨率匹配不同资源的问题。同时,用资源ID调用的方法比较类似于windows mobile,而对于习惯了cocos2d-iphone的开发者来说,文件名会更符合一些。所以我们做了一个哈希表来实现 文件名(key)-> 资源ID(value) 的映射,cocos2d-x开发者只要实现填写好这份映射,然后游戏里就可以用文件名来调用资源,甚至不用理会这个资源是暴露在文件目录里还是打包编译在资源包里。
(1) 首先,建立一个资源名称字符串与资源ID的映射
我们添加一个Resource.h头文件来保存这个映射,头文件中代码如下:
#define _RESOURCE_H_
#include "SimpleAudioEngine.h"
#include "cocos2dsimplegame_res_def.h"
#include "cocos2d.h"
const T_ResourceInfo ResInfo[] =
{
{ "CloseNormal", COCOS2_ID_BITMAP_CloseNormal },
{ "CloseSelected", COCOS2_ID_BITMAP_CloseSelected },
{ "Player", COCOS2_ID_BITMAP_Player },
{ "Projectile", COCOS2_ID_BITMAP_Projectile },
{ "Target", COCOS2_ID_BITMAP_Target },
{ "CloseNormal@WVGA", COCOS2_ID_BITMAP_CloseNormal_WVGA },
{ "CloseSelected@WVGA", COCOS2_ID_BITMAP_CloseSelected_WVGA },
{ "Player@WVGA", COCOS2_ID_BITMAP_Player_WVGA },
{ "Projectile@WVGA", COCOS2_ID_BITMAP_Projectile_WVGA },
{ "Target@WVGA", COCOS2_ID_BITMAP_Target_WVGA },
};
/**
@warning 在声音数据信息的结构体中,FileName必须包含文件的扩展名,并且需要与原始文件的扩展名一致
否则无法播放
*/
const T_SoundResInfo SoundResInfo[] =
{
{ "background-music-aac.mp3", COCOS2_ID_RAWDATA_background_music_aac },
{ "pew-pew-lei.wav", COCOS2_ID_RAWDATA_pew_pew_lei },
};
#endif
这里面@WVGA的资源,将在下一篇文章中解释
(2) 其次,需要让游戏引擎“知道”这个映射关系的存在:
在Cocos2dSimpleGameAppDelegate.cpp文件的initCocos2d() 函数中添加代码如下(当然,别忘记添加Resource.h这个头文件)
CCFileUtils::setResourceInfo(ResInfo,
sizeof(ResInfo) / sizeof(T_ResourceInfo));
// set the ResourceEntry and sound ResInfo (filename and ResID)
SimpleAudioEngine::getSharedEngine()->setSoundResInfo(SoundResInfo,
sizeof(SoundResInfo) / sizeof(T_SoundResInfo));
(3) 第三,需要让游戏引擎“知道”当前的上下文
在上面我们了解了普通Uphone应用通过TResource类来获取上下文资源。现在游戏引擎已经“知道”了打包资源的ID,但是还需要让游戏引擎“知道”当前的上下文信息,它才能根据资源ID获取数据。具体做法如下
extern const AppResourceEntry Cocos2dSimpleGameResourceEntry;
(a) 在D:\Work7\cocos2d\Cocos2dSimpleGame\main.cpp文件中,使用extern声明变量Cocos2dSimpleGameResourceEntry
const ResourceRegisterEntry ResRegList_Cocos2dSimpleGame[] =
{
TG_RESOURCE_DEFINE
};
extern const AppResourceEntry Cocos2dSimpleGameResourceEntry =
{
(ResourceRegisterEntry*)ResRegList_Cocos2dSimpleGame, // res list in this app
sizeof(ResRegList_Cocos2dSimpleGame) / sizeof(ResourceRegisterEntry), // number of item in res
};
(b) 在Cocos2dSimpleGameAppDelegate.cpp文件头部添加代码
并在initCocos2d() 函数中,在上面步骤(2)的基础上,把代码改成
CCFileUtils::setResourceEntry(&Cocos2dSimpleGameResourceEntry);
CCFileUtils::setResourceInfo(ResInfo, sizeof(ResInfo) / sizeof(T_ResourceInfo));
// for cocosDenshion, set the ResourceEntry and sound ResInfo (filename and ResID)
SimpleAudioEngine::getSharedEngine()->setResourceEntry(&Cocos2dSimpleGameResourceEntry);
SimpleAudioEngine::getSharedEngine()->setSoundResInfo(SoundResInfo, sizeof(SoundResInfo) / sizeof(T_SoundResInfo));
之所以需要两步,是因为cocos2d处理图像,cocosDenshion处理音频,是两个不同的库。
(4) 最后,就可以使用打包的资源了
或者
实际上,对于按照前面教程开发的代码,在这里就不用修改一字了。
在 Uphone 平台下,游戏引擎根据图片名称创建 Texture 的逻辑为:根据传入的字符串先在设置的ResInfo映射表中查找是否有相应的资源ID,如果存在则加载并成功返回;如果不存在,则到文件目录下查找同名文件,若还是找不到则加载失败。
三、交叉编译
交叉编译的方法,在Uphone开发文档里有详细描述,这里就不重复了。对于cocos2d-x游戏来说,首先得把cocos2dx, CocosDenshion, chipmunk, Box2D这几个库编译好。我们已经做好了makefile文件,现在只要把四个目录挨个进去,敲一行
就可以了。生成的.so文件都在 D:\Work7\PRJ_TG3\LIB\ARMLib 目录下。
而我们新开发的Cocos2dSimpleGame, 得在Makefile.ARM文件里增加一些DEFINE, PATH和链接的LIB,如下
INCLUDE_PATH += -I. \
-I./Res \
-I../cocos2dx \
-I../cocos2dx/include \
-I../cocosDenshion/include
LIBS +=-lcocos2d -lCocosDenshion -lTG3_EGL -lTG3_GLESv1_CM
LIBS里面,第一个是cocos2d图形库,第二个是CocosDenshion音效库,然后是EGL库和GLES 1.1的库。虽然Uphone上有GLES 2.0,但cocos2d仍然使用1.1
同上面那条指令一样make之,我们就可以看到libCocos2dSimpleGame.so这个文件生成在 D:\Work7\PRJ_TG3\LIB\ARMLib 目录下了
四、安装包制作
和uphone普通应用的打包过程一样,详细步骤的文档在uphone开发指南和开发者社区里都有。在 D:\Work7\PRJ_TG3\Tools\ 目录下有个 TG3_Publish_Maker_V1.04.exe ,启动之。然后填入安装目录、装入libCocos2dSimpleGame.so, 选择好桌面快捷图标就行了。
实际上,我们已经把Cocos2dSimpleGame的安装包配置文件保存为Cocos2dSimpleGame\pak\Cocos2dSimpleGame.TG3_IProc了,您可以从安装包制作工具里点“从文件加载”,并选择上述的TG3_IProc文件,就可以看到所有参数应如何填写。然后,点图中左下角的“生成安装包”,就会生成一个Cocos2dSimpleGame.TGI安装文件。这就是最后结果了。可以直接拷到手机里安装,或者发布到应用商城里。
《如何用cocos2d-x来开发简单的Uphone游戏 》这系列教程到这篇就结束了。后面我会从cocos2d-iphone上翻译更多的cocos2d-x文章过来。最后,祝所有用cocos2d引擎的开发者:游戏卖座、大把赚钱!
著作权声明:本文由http://www.walzer.cn/原创,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!