将cocos2d-x游戏移植到win8/wp8上

1、cocos2d-x已经有win8的非官方移植版本,同样有wp8的。但是win8的版本使用的是非常古老的cocos2d-x代码,而wp8虽然有for 2.0的较新的代码,但是各种bug。所以还是自己动手丰衣足食。不过基础知识还是来自github上面的版本。理论上等cocos2d-x 3.0版本稳定之后再移植会轻松很多,但是有些迫不及待了>_<

2、此文章为小记,非教程,可能有较多错漏,毕竟作为尝试一个新的系统,各种知识都在摸索之中

3、代码暂不开源,因为刚刚开始移植,问题很多,并且不知道会不会半途而废。等稳定了再说(说不定那时候都有官方版本了)

4、移植进行中,文章暂未完成,会不定时补完,并且不会特别标注修改内容。


一、关于系统环境的一些基础知识

1、windows8和windows phone8并不一样,我们的游戏需要两个工程文件,虽然平台相关的代码有很多是通用的。如果之前没有安装windows phone 8 sdk的话,创建第一个wp8demo的时候会提示进行安装(敢不敢给个完整安装包!!) 后面使用win8代表桌面应用商店版本(如果连应用商店支持都不考虑的话,那就是原始win32应用。这个在windows8下基本上都可以正常运行,但是无法加入应用商店以及开始磁贴里),wp8代表移动版本(手机或平板)

2、如果没有安装 windows develop kit (注意不是wp 的sdk)则默认的demo代码创建dx11的device会失败,因为默认debug版本开启了D3D11_CREATE_DEVICE_DEBUG,这个需要开发环境支持。

3、wp8可以在模拟器上面调试,也可以真机调试。 我在真机调试时出现一个问题"can not write file to FolderID_SharedData.....",后来重启了下手机就好了。

4、vs2012不装sp3的话,模拟器与windows8.1不兼容。装了之后就好了。(吐槽下微软伟大的工程师,与自家操作系统都可以不兼容)

5、win8 for应用商店的程序,建立的静态库默认不开启“使用windows运行时扩展”,导致__cpluscplus_winrt未定义,在"c/c++"----"常规"选项中开启后正常.(/ZW)选项。这个也要稍微注意下,这个选项跟是否使用预编译一样,虽然可以对工程进行设置,但是本质上是对每一个文件夹的控制。所以可以自由控制某一个文件不开启(比如c语言代码)



二、引擎和游戏的移植

1、win8不支持opengl,所以渲染api都要全部替换。

win8声音播放要使用xaudio2,懒得写代码的就使用fmodex或者是cocos2d-x win8版本自带的吧。 wp8有点变态,虽然支持xaudio2但是不支持mp3解码,需要自己手动编写解码器。

win8不支持winsock2,所以socket代码要全部重写。这个暂时来看是除渲染外最大的修改。

所有动态库和静态库要使用win8的模板来创建,否则有可能不支持。就算能运行也可能上不了应用商店。注意,这个说的是可能,我可没有试过。

窗口创建代码要使用win8自带的,不能使用mfc win32api等等。这个相对好说,因为游戏基本不会接触到原生界面。

线程不能使用win32 api了,虽然部分函数依然可用,但是不要给自己找麻烦。直接使用std::thread,c++标准总没有问题。

序设置里的是编译目标目录,但是部署到编译目标目录的AppX子目录,最后上传商店需要创建AppXPackage应用程序包,不要混淆这几个概念。

字符串转码MultiByteToWideChar/WideCharToMultiByte仍然可以使用。

仍然可以使用C标准库/C++标准库,fopen/fread/stl::map/std::vector/strcpy/sprintf等基本函数保持不变。

这里要说下fopen,如果可以的话,最好还是不要使用这个函数,而是使用win8提供的异步文件读取接口。但是你知道的,对于大量的游戏代码而言,所有的功能都要兼容异步不是一件容易的事。所以暂时还是使用fopen。这个就是同步文件读取的接口了。

2、游戏资源

有两个目录先要说明下

程序只读安装目录: Platform::String^ strResPath = Package::Current->InstalledLocation->Path; 程序可写数据目录: Windows::Storage::ApplicationData::Current->LocalFolder->Path; 第一个目录就是程序目录(注意这个目录不包含Assets文件夹,需要自己拼接),第二个目录就是可写目录,也就是类似ios下面的document目录。

win8程序只能读取这两个目录中的资源,禁止读取其他目录的资源。vs2012中添加游戏资源不是一件容易的事情,如果我骂了微软的傻x工程师一晚上是错误的话,那麻烦尽快告诉我。我非常急切的想知道向vs2012中添加资源目录的方法(自己测试显示所有文件和拖拽文件的方式均无效,只能手工一个文件夹一个文件夹的建立)。有一个偷懒,但是更加靠谱的方式,就是直接把资源拷贝到编译目录下的AppX目录下面,暂时不知道将来发布时会对编译包有什么样的影响。

读取的时候就可以使用Package::Current->InstalledLocation->Path 加上文件相对路径(实际文件夹路径),来访问。

3、部分附加功能

打开外部网页 Launcher::LaunchUriAsync(ref new Windows::Foundation::Uri("www.baidu.com"));

4、调试和其他

vs2012有一个诡异的地方,还没有看究竟是什么原因。至少单从代码上面我是无法理解了。 windows metro应用的循环(在一个Run函数里面,类似win32的while true的循环)只有在窗体active的时候才会运行,这个时候cocos2d-x的action timer什么的才能正常跑,跑到后台后就不运行了(比如鼠标移动到左上角选择vs2012,这样当前程序就跑到后台了),不知道卡在哪里了。从后台到前台后可以继续正常运行。

编译到Device时可能出现LuaCocos2d.cpp编译不过的问题,开启这个选项后正常 /Gy (启用函数级链接)

部署到真机的时候,真机要保持解锁状态。

关于如何向项目中添加游戏资源。这个真是个老大难的问题了,真心被vs2012给恶心到了。 win8 metro版本的程序还有个比较简单的方法,那就是直接把资源拷贝到AppX目录下。但是wp8的项目自动打包成xap然后部署到真机和模拟器上面,无法这样做。所以只能把游戏资源加入到工程中。加入的方法是:

a、建议筛选器(可以不与实际文件夹一一对应,但是建议对应),设置筛选器支持的扩展名,如果不设置就只识别cpp文件

b、将资源文件拖拽到vs2012的工程中,并将“是否是内容”这个属性设置为True,这样它就被识别为一个资源文件而不会进行编译了

c、资源文件应该放置在Assets目录下。只有在这个目录下才能正确的按照目录生成对应的目标目录,否则资源文件会散落在xap包的根目录。

5、渲染修改

之前说过win8 metro不支持opengl/opengles,只支持dx11。我原本以为这个修改会是一个浩大的工程,但是后来发现了一个很酷的项目,一切都变得简单起来。Angle Project (http://code.google.com/p/angleproject/) .这个项目使用opengl的api将dx进行封装。opengl egl的接口与windows版本一模一样。基于此项目,我们只需要把angle接入工程,然后做少量修改(外部引擎代码几乎无修改)就可以达到移植的目的。主要的修改有:

a、shader修改,这个是第一个大难题。win 8 metro不支持运行时编译shader,所有的shader需要编译器生成(.cso扩展名),然后直接加载这个二进制的shader。 这个我不太熟悉,所以使用了有点恶心的解决方案,同时保存一份glsl的shader,和对应的hlsl编译而成的cso文件(angle支持glsl->hlsl的转换,可以获得对应的hlsl shader文本),glsl的文本交给angle进行解析(但不编译),cso的shader用于实际加载。 之所以要保存glsl是因为dx加载shader时有各种layout和attribute,如果非常熟悉angle代码可以自己修改,否则还是交给angle进行解析自动配置比较好。

b、窗体界面修改,这个是第二个大难题。win 8 metro不再使用win32 api,也就没有HWND这种东西了,因此创建dx设备和swapchain的代码都要做相应调整。不过好在修改不是非常大。我们可以使用typedef Platform::Agile<Windows::UI::Core::CoreWindow> EGLNativeWindowType; 这个东西来替代HWND作为窗口句柄。 代码基本可以保持不变,就是判断句柄有效的时候要跟nullptr进行比较而不能直接用 !mWnd这种写法。 创建dx设备的代码对应修改为dx11_1的版本。

除开这两处修改,其他的都是零零星星的修改,并且不会散落在大量文件里面,主要还是platform文件夹里面的文件替换。个人感觉这个解决方案已经非常完美了,并且是可以合并到cocos2d-x分支里面。无论后面cocos2d-x升级到什么版本,接口如何修改,都能保证win8版本的正常运行,只要opengl代码正常就可以了。并且基于此,像ogre一样渲染分离意义显得不是那么大了,单独写一个所谓的dx renderer也没有太大必要。

微软很恶心,明明希望win8和wp8平台统一,但是支持特性又有很多差别。wp8不支持d2d也就是说文字渲染相关的东西都要自己实现(freetype),feature level只支持到9.3,angle的dx11的实现还要做一些修改才能正常运行在wp8上面。

1、ID3DBuffer的bindFlag不能同时设置vertex和index,要在上层做判断,设置成其中的一个。

2、不支持非2的整次幂的图片进行mipmap,这个是angle内部代码有一处需要修改的

3、CreateSamplerState的参数中maxmod要修改为FT_MAX,原本可以设置为0.这个可能会造成部分图片无法显示的问题。完美的解决方案我再研究研究。


6、lua脚本的修改

win8可以直接编译一个对应的luajit静态库,目测没有实际问题。直接用luajit自带的make文件就可以了。 使用上也没有什么特殊的地方。

wp8暂时没有找到编译luajit的方法。暂时使用原始lua。最简单的方法就是把lua原文件加入到工程中。 这里要注意下,我使用的版本的lua貌似没有很好的兼容utf8的文本,所以需要在CocosLuaLoader文件读取的时候自己判断bom然后去除最开始的三个字节(如果文件有bom的话)。


7、一些第三方依赖库的说明

freetype是渲染文字用的。微软真tmd恶心,windows 8 支持的d2d到windows phone上面竟然不支持了。 所以只有使用freetype进行文本渲染。这个官方移植版本里面有对应的库文件,暂时不需要重新编译。

libpng这个是因为一个链接错误。setjmp没有对应的实现。这个在win8上面是没有问题的,但是wp8上面链接不过。这个是因为libpng的库版本不一致,最稳妥的解决方法是自己下载最新的libpng库,把代码加入到工程中。

模拟器上面用的是x86版本的静态库,真机上面需要的是arm版本的静态库,不同的平台可以选择不同的工程配置。


8、真机和模拟器的差异

除开x86和arm的cpu架构差异,最主要的还是对dx的支持。windows phone设备只支持feather 9.3,而模拟器和win8则支持到feather 11.1。所以我们要写如下代码以便把模拟器dx特性限定在9.3防止出现模拟器运行正常而到真机上会崩溃的问题。 而限定featherlevel最主要的影响就是shader的支持,wp8只支持sm2.0,直接来说就是angle项目中预先编译好的二进制形式的shader都不能用了,需要再想办法替换。

	D3D_FEATURE_LEVEL featureLevels[] = 
	{
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
		D3D_FEATURE_LEVEL_9_3,
		D3D_FEATURE_LEVEL_9_2,
		D3D_FEATURE_LEVEL_9_1
#else
		D3D_FEATURE_LEVEL_11_1,
		D3D_FEATURE_LEVEL_11_0,
		D3D_FEATURE_LEVEL_10_1,
		D3D_FEATURE_LEVEL_10_0,
		D3D_FEATURE_LEVEL_9_3,
		D3D_FEATURE_LEVEL_9_2,
		D3D_FEATURE_LEVEL_9_1
#endif
	};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值