www.Walzer.cn - Tech & Management Blog

Focus on mobile dev
本博客文章,未在标题中写明转载的, 均为原创.
所谓高手,也就是熟悉别人制定的游戏规则、并且能在规则内跳舞的人。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

如何用cocos2d-x来开发简单的Uphone游戏:(五) 打包和发布

Posted on 2010-10-22 16:38  Walzer  阅读(4817)  评论(0编辑  收藏  举报

     到本系列文章的前四篇为止,我们已经完成了一个简单的游戏,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 文件,这就打开了游戏的资源工程,运行的界面如下图:

 

tops builder


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应用中只要使用如下代码就可以加载图片资源了:

const TBitmap* pBmp = TResource::LoadConstBitmap(COCOS2_ID_BITMAP_CloseNormal);

 

 

2.  cocos2d-x游戏中使用打包资源的方法

    上面的资源调用方法对cocos2d-x开发者来说功能不够强、不够跨平台,也不能很好地解决不同分辨率匹配不同资源的问题。同时,用资源ID调用的方法比较类似于windows mobile,而对于习惯了cocos2d-iphone的开发者来说,文件名会更符合一些。所以我们做了一个哈希表来实现 文件名(key)-> 资源ID(value) 的映射,cocos2d-x开发者只要实现填写好这份映射,然后游戏里就可以用文件名来调用资源,甚至不用理会这个资源是暴露在文件目录里还是打包编译在资源包里。 

 

(1) 首先,建立一个资源名称字符串与资源ID的映射

    我们添加一个Resource.h头文件来保存这个映射,头文件中代码如下:

#ifndef _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这个头文件)

// set the ResourceEntry and Images ResInfo (name and ResID)
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

#include  "cocos2dsimplegame_res_c.h"

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文件头部添加代码

extern const AppResourceEntry Cocos2dSimpleGameResourceEntry; 

并在initCocos2d() 函数中,在上面步骤(2)的基础上,把代码改成

// for cocos2d-x, set the ResourceEntry and Images ResInfo (name and ResID)
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) 最后,就可以使用打包的资源了

CCSprite *player = CCSprite::spriteWithFile("player.png");

 

或者

CCSprite *player = CCSprite::spriteWithFile(ResInfo[2].ResName);

 

实际上,对于按照前面教程开发的代码,在这里就不用修改一字了。

 

在 Uphone 平台下,游戏引擎根据图片名称创建 Texture 的逻辑为:根据传入的字符串先在设置的ResInfo映射表中查找是否有相应的资源ID,如果存在则加载并成功返回;如果不存在,则到文件目录下查找同名文件,若还是找不到则加载失败。

 

特别注意

1. 如果打包的资源都是直接进行使用的话,在ResInfo这个映射里的资源名称可以随意设定。但是,当打包的图片资源是被 .plist / .tmx / .fnt 等配置文件指定要使用的图片时,资源名称就不能随意设定了。示例如下:

// 代码要用.plist 文件创建SpriteFrames,其中grossini.plist 文件指定要使用 XXX.png
CCSpriteFrameCache::addSpriteFramesWithFile("animations/grossini.plist");

 

那么在Resinfo中图片XXX.png的资源名称就必须为 "animations/XXX.png" ,这样才能让游戏引擎找到

 

2. 建议在给cocos2d-x用的ResInfo中资源名称包含原始文件的扩展名。而给cocosDenshion用的T_SoundResInfo中,资源名则必须明确是.mp3还是.wav,否则SimpleAudioEngine无法识别该资源的解码类型

 


 三、交叉编译

 

     交叉编译的方法,在Uphone开发文档里有详细描述,这里就不重复了。对于cocos2d-x游戏来说,首先得把cocos2dx, CocosDenshion, chipmunk, Box2D这几个库编译好。我们已经做好了makefile文件,现在只要把四个目录挨个进去,敲一行

make -f Makefile.ARM all

 

就可以了。生成的.so文件都在 D:\Work7\PRJ_TG3\LIB\ARMLib 目录下。

 

而我们新开发的Cocos2dSimpleGame, 得在Makefile.ARM文件里增加一些DEFINE, PATH和链接的LIB,如下

DEFINES += -DCCX_UNDER_UPHONE
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, 选择好桌面快捷图标就行了。

uphone 安装包制作工具 

 

实际上,我们已经把Cocos2dSimpleGame的安装包配置文件保存为Cocos2dSimpleGame\pak\Cocos2dSimpleGame.TG3_IProc了,您可以从安装包制作工具里点“从文件加载”,并选择上述的TG3_IProc文件,就可以看到所有参数应如何填写。然后,点图中左下角的“生成安装包”,就会生成一个Cocos2dSimpleGame.TGI安装文件。这就是最后结果了。可以直接拷到手机里安装,或者发布到应用商城里。

    

《如何用cocos2d-x来开发简单的Uphone游戏 》这系列教程到这篇就结束了。后面我会从cocos2d-iphone上翻译更多的cocos2d-x文章过来。最后,祝所有用cocos2d引擎的开发者:游戏卖座、大把赚钱!

 

 

系列教程

如何用cocos2d-x来开发简单的Uphone游戏:(一) 下载安装和HelloWorld

如何用cocos2d-x来开发简单的Uphone游戏:(二) 移动的精灵

如何用cocos2d-x来开发简单的Uphone游戏:(三) 射击子弹 & 碰撞检测

如何用cocos2d-x来开发简单的Uphone游戏:(四) 音乐音效 & 最后的润色

如何用cocos2d-x来开发简单的Uphone游戏:(五) 打包和发布


著作权声明:本文由http://www.walzer.cn/原创,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!