一. Cocos2d-x for Windows Phone
到2013年底,幾大手游引擎都陸續支持WP8了,特別是Unity3D和Cocos2d-x。有過游戲開發經驗的朋友們應該對這兩個引擎不陌生,WP8對Native C++的支持,使得其他平台上用C++編寫的游戲移植到WP8平台上變得非常簡單。Cocos2d-x在2.2.1版本之前在WP8上只支持純Direct3D工程模式,目前在Github上已提供了支持XAML的混合托管模式,傳送門:https://github.com/MSOpenTech/cocos2d-x/tree/wp8-xaml2
Git下來之后打開cocos2d-wp8.vc2012.sln可以看到工程結構如下:
其中HelloCpp-XAML采用一個XAML與Direct3D組件混合的托管模式,是一個標准的WP8工程模板,編譯並運行可見到:
其中的C#項目負責Windows Phone常規控件和頁面邏輯,C++項目是一個基於Direct3D的Windows Phone Runtime Component,負責所有的游戲邏輯,兩者通過DrawingSurface或DrawingSurfaceBackgroundGrid控件混入Direct3D圖像,以非常小的性能代價獲取托管代碼的優秀特性。DrawingSurface 控件允許使用 Direct3D 來呈現顯示在 XAML 控件后方或與其並列顯示的圖形。
在托管的XAML中,可以發現Direct3DInterop類在XAML引擎和Direct3D之間建立起了一個通信橋梁,作為XAML引擎和Direct3D代碼之間的代理。在Direct3DInterop的實現中,CreateContentProvider方法初始化了一個Direct3DContentProvider類的實例,並強制轉化為IDrawingSurfaceContentProvider,這個接口並沒有任何內容,因為它並不是由代碼實現的接口,而是使用WRL(Windows Runtime Library)實現的,將類強制轉化為Windows Phone Runtime Component接口,以便由XAML引擎訪問。
更多關於托管的XAML和Direct3D引擎的通信,請查看MSDN文檔,傳送門:http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207012%28v=vs.105%29.aspx
二. 演練:在Cocos2d-x中調用OpenXLive
OpenXLive是Windows Phone和Windows 8平台上最大的游戲社交網絡平台,對Windows Phone游戲的開發提供了很多非常優秀的輔助功能,比如游戲基礎功能(積分榜、成就、公告、在線玩家等)、推廣功能(推薦游戲、推廣牆)、社交功能(分享、動態、任務、交友)以及支付功能(支付寶、點卡支付、禮品卡)等一些列相關功能。除了OpenXLive之外,一批優秀的第三方庫基本都是由C#編寫的,如果需要在Direct3D中使用到這些功能,就需要采用拙者在此前提到的一個解決方案,傳送門:
《WP8:在WinRT組件(C++)中調用C#類庫的解決方案》
以下我們以OpenXLive為例子,介紹如何在Cocos2d-x中進行調用。
1.創建文件並添加引用
首先在cocos2d-x\samples\Cpp\HelloCpp\Classes文件目錄下創建一個OpenXLiveHelper目錄,並在該目錄下添加以下三個文件:ICallback.h、XLiveDelegate.h和XLiveDelegate.cpp,並將他們添加到HelloCppComponent項目中:
2.定義WinRT接口ICallback
接下來在ICallback.h中定義一個WinRT接口,這個接口將在C#項目中具體實現:
1 // A callback interface for C# code to implement. 2 public interface class ICallback 3 { 4 };
3.定義C++托管類XLiveDelegate
接下來定義一個C++托管類,所有Direct3D游戲邏輯通過這個托管類,利用ICallback接口調用具體的C#代碼,這里采用單例模式管理這個托管類,在XLiveDelegate.h文件中添加以下代碼:
1 #include "ICallback.h" 2 3 namespace PhoneDirect3DXamlAppComponent 4 { 5 namespace OpenXLiveHelper 6 { 7 // A native class to pass and store an ICallback instance, calling C# code via the ICallback object. 8 [Windows::Foundation::Metadata::WebHostHidden] 9 public ref class XLiveDelegate sealed 10 { 11 public: 12 // Gets the single XLiveDelegate instance. 13 static XLiveDelegate^ GetInstance(); 14 // Set callback into the XLiveDelegate instance. 15 void SetCallback(ICallback^ callback); 16 // Gets or sets the callback. 17 property ICallback^ GlobalCallback; 18 19 private: 20 XLiveDelegate(); 21 static XLiveDelegate^ m_Instance; 22 }; 23 } 24 }
4.實現C++托管類XLiveDelegate
接下來實現XLiveDelegate這個C++托管類,在XLiveDelegate.cpp文件中添加以下代碼:
1 #include "pch.h" 2 #include "XLiveDelegate.h" 3 4 namespace PhoneDirect3DXamlAppComponent 5 { 6 namespace OpenXLiveHelper 7 { 8 XLiveDelegate::XLiveDelegate() 9 { 10 } 11 12 XLiveDelegate^ XLiveDelegate::GetInstance() 13 { 14 if (m_Instance == nullptr) 15 { 16 m_Instance = ref new XLiveDelegate(); 17 } 18 return m_Instance; 19 } 20 21 void XLiveDelegate::SetCallback(ICallback^ callback) 22 { 23 GlobalCallback = callback; 24 } 25 26 XLiveDelegate^ XLiveDelegate::m_Instance; 27 } 28 }
5.定義實現ICallback接口的C#類XLiveCallback
在C#項目HelloCpp中,在OpenXLive\OpenXLiveHelper中添加XLiveCallback.cs文件,並添加以下代碼:
1 using PhoneDirect3DXamlAppComponent.OpenXLiveHelper; 2 3 namespace PhoneDirect3DXamlAppInterop 4 { 5 public sealed class XLiveCallback : ICallback 6 { 7 } 8 }
6.根據需求補充ICallback的接口方法,並在XLiveCallback中實現
例如需要在Direct3D游戲邏輯中獲取一個成就,則在ICallback.h中定義一個接口方法:
1 // Award an achievement completed event. 2 event Windows::Foundation::EventHandler<CompletedEventArgs^>^ OnAwardComplted; 3 void Achievement_Award(Platform::String^ achievementKey);
在XLiveCallback.cs中實現:
1 public void Achievement_Award(string achievementKey) 2 { 3 Achievement ac = new Achievement(XLiveGameManager.CurrentSession, achievementKey); 4 ac.AwardCompleted += ac_AwardCompleted; 5 ac.Award(); 6 } 7 8 void ac_AwardCompleted(object sender, AsyncEventArgs e) 9 { 10 if (OnAwardComplted != null) 11 { 12 OnAwardComplted(sender, new CompletedEventArgs(e.Result.ReturnValue, e.Result.ErrorCode, e.Result.ErrorMessage)); 13 } 14 } 15
觀察上述邏輯,可以發現這實現過程其實是一個適配器模式的實現:
其中的ICallback為目標接口(Target),Achievement為需要適配的類(Adaptee),XLiveCallback則為適配器(Adapter),將原有接口轉換為目標接口,而XLiveDelegate則為客戶端(Client),負責管理和調用目標接口,而不必關心具體的適配接口。
至於其余的OpenXLive接口,拙者認為需要從游戲邏輯中向外POST並且獲取返回通知的接口才需要進行封裝,而UI跳轉或其他GET類型的接口只需要在托管XAML示例中調用即可,附上拙者封裝的一些接口。