WP7游戲開發(fā):TweeJump(cocos2d-xna)
TweeJump
這篇教程簡單描述了如何使用Cocos2d-XNA來制作一個簡單的WP7游戲。你可以按照教程一步步來,或者干脆直接跳到文章的最后,下載SimpleGame。
下載并安裝Cocos2d-XNA
- 你可以從下面的鏈接來下載Cocos2d-XNA的源文件
https://github.com/cocos2d/cocos2d-x-for-xna

Cocos2d-XNA主要文件作用:
install-template-mscs.msi:模板安裝程序
cocos2d-xna:主項目
CocosDenshion:聲音音效
Cocos2d.Framework、Cocos2d.Content.Pipeline.Importers:支持文本類型資源(*.fnt、*.tmx、*.plist)
HelloCocos2d:示例工程
Tests :功能演示

- 安裝模板


Next Next ..完成安裝中間如果有出現(xiàn)用戶賬戶控制提示選擇是然后繼續(xù)Next..完成安裝
接下來就能夠創(chuàng)建cocos2d-xna工程了。
Hello, Cocos2D-XNA!
啟動cocos2d-xna.sln 添加新項目選擇XNA Game Studio 4.0節(jié)點底下的 Cocos2d-xna Application,給項目起個名字叫TweeJump。

Ok后,這里會彈出一個對話框

我們確認就好了選擇ok (OpenXLive是Windows Phone 7上的游戲競技和社交網(wǎng)絡(luò)SNS平臺,允許開發(fā)者以最小的工作量為自己的游戲增加游戲競技服務(wù)和社交網(wǎng)絡(luò)SNS功能。OpenXLive是由Fulcrum Mobile Networks, Inc.開發(fā)運營的。同類的應(yīng)用還有iPhone上的OpenFeint和Plus+等。)www.openxlive.com
我們將創(chuàng)建好的工程設(shè)置為啟動項,如下圖:

F5運行,Cocos2D-XNA的HelloWorld程序,啟動模擬器,程序運行界面如下:

默認工程里面只有一個場景HelloWorldScene,除了多了大廳、積分榜、成就和示例代碼HelloCocos2d沒有什么不同。
cocos2d是按照scene的概念組織的,游戲是由多個scene切換完成的。游戲場景一般是指在某個時刻能獨立運行的部分,其中包括可見的游戲角色,地形和不可見的邏輯腳本等。例如,一個游戲的某個特定關(guān)卡,游戲菜單和過場動畫等,都是一個獨立的場景。cocos2d中的場景又由不同的層(CCLayer)組成。 TweeJump需要主菜單(MainMenu)、游戲畫面(Game)、游戲結(jié)束畫面(GameOver)三個scene來完成我們的游戲邏輯,游戲的流程如下:進入游戲>>主菜單選單play>>游戲畫面開始游戲>>游戲結(jié)束呼出GameOver畫面>> again>>游戲畫面。
Cocos2d-XNA基礎(chǔ)介紹
下面介紹一下TweeJump中主要用到的Cocos2d-XNA的類。
CCDirector負責(zé)管理場景和切換場景游戲暫停等。
CCNode是Cocos2d-XNA中最重要的對象。CCNode的addChild()方法,我個人認為是最重要的方法。它充當(dāng)了一個容器的角色可以addChild進去無數(shù)個節(jié)點,但每個節(jié)點只有一個父節(jié)點,同時他可以執(zhí)行回調(diào)函數(shù)和CCAction有postion,scale,rotation等等屬性。
CCLayer,它是CCNode的子類,層是一個可以繪制的區(qū)域.可以將ui,sprite等對象添加到其中。
CCMenu從CClayer派生而來,可以處理輸入消息,CCMenu包含多個CCMenuItem對象,在接收到輸入消息之后,根據(jù)觸摸位置,將輸入消息分發(fā)到相應(yīng)MenuItem,執(zhí)行回調(diào)函數(shù),CCMenu還提供一個對齊菜單項的功能

CCSprite, 可以看成是某一時刻,一個2D的圖片的一個剪輯部分
添加我們游戲的背景
TweeJump游戲中的背景都是藍天白云,為了重用我們把它提取成父類Main,主菜單MainMenu、游戲畫面Game、結(jié)束畫面GameOver只要繼承它就藍天白云了。
在Main中涂寫畫畫出萌萌的藍天白云,為了方便管理游戲中用到的類都盡量建到Classes文件夾中,新建類Main:

讓Main繼承CCLayer并重寫init()方法
public class Main : CCLayer
{
//調(diào)整素材比例
public const float sy = 1.666666666666667f;
public const float sx = 1.5f;
public static void Scale(CCNode sprite)
{
sprite.scaleY = sy;
sprite.scaleX = sx;
}
public override bool init()
{
if (!base.init())
{
return false;
}
//@todo
return true;
}
}
先把藍天貼到@todo哪里:
CCSpriteBatchNodespriteManager=CCSpriteBatchNode.batchNodeWithFile("Images/sprites", 10);
addChild(spriteManager, -1, (int)tags.kSpriteManager);
CCSpritebackground=CCSprite.spriteWithTexture(spriteManager.Texture, newCCRect(0, 0, 320, 480));
spriteManager.addChild(background);
Scale(background);
background.position=newCCPoint(240, 400);
//this.initClouds(); 初始化云
//this.schedule(step); 讓云變得可愛點
把tags枚舉放到類的外面
public enum tags
{
kSpriteManager = 0,
kBird,
kScoreLabel,
kCloudsStartTag = 100,//數(shù)值的意義是分出段來
kPlatformsStartTag = 200,
kBonusStartTag = 300
}
雖然只是添加了藍天但還是先來看下效果吧,運行前需要修改下Scene的入口點。在
AppDelegate.cs中的applicationDidFinishLaunching()方法里找到下面代碼并修改它:
// create a scene. it's an autorelease object
CCScene pScene = TweeJumpScene.scene();
//run
pDirector.runWithScene(pScene);
現(xiàn)在需要把pScene實例化為我們的Main,但是不好的事情是我們的Main.cs是一個CCLayer并不是CCScene,實現(xiàn)代碼如下:
CCScene pScene = CCScene.node();
pScene.addChild(Tweejump.Classes.MainMenu.node());
在Main.cs里還需要添加node()方法用來調(diào)用init()方法完成初始化工作
publicstaticnewCCLayernode()
{
Mainret=newMain ();
if (ret.init())
{
returnret;
}
returnnull;
}
F5運行,這也太丑了吧。

因為在游戲中默認是橫屏,所以需要在applicationDidFinishLaunching()里加上這句話將屏幕設(shè)置為豎屏:
pDirector.deviceOrientation = ccDeviceOrientation.CCDeviceOrientationPortrait;

藍天貼圖ok,解開我們的注釋、去掉文字說明、再把云畫上去Main我們的背景就ok了。
直接貼代碼有點長了為了顯得有技術(shù)含量少貼,詳細查看源代碼(cocos2d簡單性很容易上手)。
privatevoidinitClouds()
{
currentCloudTag= (int)tags.kCloudsStartTag;
while (currentCloudTag< (int)tags.kCloudsStartTag+kNumClouds)
{
this.initCloud();
currentCloudTag++;
}
this.resetClouds();
}
initClouds()方法他完成了云朵的初始化工作initClouds()里面調(diào)用了KNumClouds =12次initCloud()該方法從3塊云中隨機出塊,之后又調(diào)用resetClouds()完成云位置初始化,具體方法看源文件。
Main.cs注冊了spriteManager并把它添加到了Main這個CCLayer中(addChild()方法),在需要的地方取出spriteManager.Texture的某一部分保存到CCSprite里形成一個新的CCSprite對象,再spriteManager.addChild(CCSprite:) 交給spriteManage統(tǒng)一管理。
在使用的時候通過spriteManager.getChildByTag(tag:)取出相應(yīng)的sprite進行position的賦值等達到我們需要的貼圖或者移動、action等等(position的位置是圖片中心點的位置);所以給每個Sprite指定一個唯一而有規(guī)則的tag是很重要很方便的(枚舉tags的作用)。
通過getChildByTag在spriteManager中遍歷需要的sprite進行賦值的操作查看源代碼resetXXXX()方法。不光是Main.cs的,在Game中你也能找到initXXXX() resetXXXX()方法。
源代碼Solution Explorer截圖:

主菜單和結(jié)束畫面
跳過。。。略過。。。Main.cs總算是水完了,下面來一起學(xué)習(xí)下Menu和Label的使用,你可以使用它們輕松的完成Tweejump或者你自己游戲的主菜單和GameOver(如果你的游戲不十分復(fù)雜的話)。
MainMenu.cs和GameOver.cs都繼承自Main.cs因為老爸是李剛的優(yōu)勢已經(jīng)有了藍天和白云作為背景。再加上Menu、Labe、Sprite,不廢話了下面看下是如何的簡單就行了。
重復(fù)上面的步驟重寫init()添加node()方法,在init()里面貼上下面的代碼
CCMenuItem button1 = CCMenuItemImage.itemFromNormalImage(@"Images\loginButton", @"Images\loginButton", this, loginCallback);
Scale(button1);
CCMenuItem button2 = CCMenuItemImage.itemFromNormalImage(@"Images\playButton", @"Images\playButton", this, playCallback);
Scale(button2);
CCMenuItem button3 = CCMenuItemImage.itemFromNormalImage(@"Images\aboutButton", @"Images\aboutButton", this, aboutCallback);
Scale(button3);
CCMenu menu = CCMenu.menuWithItems(button1, button2, button3);
menu.alignItemsVerticallyWithPadding(15f);
menu.position = new CCPoint(240, 257);
this.addChild(menu);
CCMenuItemImage.itemFromNormalImage()前兩個參數(shù)分別是按下前和按下時的圖片資源 (CCSprite),最后一個參數(shù)為按下后的回調(diào)函數(shù),格式: void Callback(CCObject sender){}。畫上我們游戲的Logo補全回調(diào)函數(shù)的響應(yīng),把runWithScene()替換成MainMenu,效果圖如下。

GameOver.cs中最終得分的顯示是由CCLabelBMFont來實現(xiàn)的,它可以讓你的字很個性很酷,貼代碼:
CCLabelBMFont scoreLabel =CCLabelBMFont.labelWithString(currentScore.ToString(),
"Fonts/bitmapFont");
scoreLabel.scaleX = sx * 1.5f;
scoreLabel.scaleY = sy * 1.5f;//素材太小了,忽略忽略
addChild(scoreLabel, 5, (int)tags.kScoreLabel);
scoreLabel.position = new CCPoint(240, 450);

游戲效果圖,Label3961還不錯的分?jǐn)?shù)吧。
bitmapFont是資源文件bitmapFont.fnt如果沒有在屬性里設(shè)置Content Impoter為Text Importer, Content Processor為TextProcessor將會出現(xiàn)編譯錯誤。打開這個文件可以看到它是由等號連接的key value對。把目光放在char id=上32 48 …分別代表空格0123456789,每個char id后的屬性描述了這個char在bitmapFont.png上空格0123456789的位置。

.fnt文件和相應(yīng)的.png文件有相應(yīng)的位置關(guān)系,必須遵循不能改變。.fnt文件同級目錄下必須有一個Images文件盛放與之對應(yīng)的.png文件。

游戲控制-重力感應(yīng)
這個版本的cocos2d-xna是沒有封裝重力感應(yīng)的,我用的是XNA中自帶的重力感應(yīng),因為Accelerometer它也是事件驅(qū)動所以很搭不會出現(xiàn)不兼容的現(xiàn)象,應(yīng)該在以后版本中也不會對它封裝了吧。
1添加Microsoft.Devices.Sensors引用

2創(chuàng)建Accelerometer對象,3注冊Accelerometer對象的CurrentValueChanged事件,4啟動Accelerometer對象Start()方法來啟動重力感應(yīng)監(jiān)聽。
在注冊的事件處理方法中可以通過e.SensorReading.Acceleration.X和e.SensorReading.Acceleration.Y,e.SensorReading.Acceleration.Z來訪問當(dāng)前的加速度的三維偏移值。這里我要提的只有一個,很多教程里都是注冊Accelerometer對象的ReadingChanged事件,當(dāng)你使用的是Windows Phone 7.1 SDK時,VS會提示你ReadingChanged已經(jīng)過時,當(dāng)然你是可以用,但是還是建議你使用CurrentValueChanged。TimeBetweenUpdates屬性會影響到兩次觸發(fā)CurrentValueChanged事件的時間間隔,所以如果你要設(shè)置重力感應(yīng)的感應(yīng)時間間隔的話最好還是使用CurrentValueChanged。詳細見源代碼Game.cs的init()。
集成OpenXLive SDK
OpenXLive的功能:
積分榜
讓全世界都知道你是這個游戲中的最強者!積分榜,用來記錄你的游戲成績,讓你和全世界的玩家分享你超凡的游戲成績。
· 游戲成就
一個個游戲成就,像一枚枚勛章,記錄了你在游戲中的成長歷程。篝火邊,用成就,告訴你的朋友,你是如何成為游戲中最強的勇士。
· 社交網(wǎng)絡(luò)
告訴你,這世界上還有多少兄弟姐妹和你一起在游戲中奮戰(zhàn)。找到他們,和他們成為好友,一起開始一段冒險的路程。
· 個人中心
這里有你過去、現(xiàn)在和將來的故事。你的積分、你的成就、你玩過的游戲、你的好友,這是你值得珍藏的一頁。
· 云存儲
不想讓別人發(fā)現(xiàn)你在游戲中的秘密?把它放在云端吧。你可以在任何地方,打開塵封的秘密。
· 游戲公告
告訴你游戲中發(fā)生的大事件,比如,你成為了NO.1。
如果你在前面的

勾選上了OpenXLive sdk,新建項目中就會我們添加好了引用就可以很方便的使用它。
熟悉XNA的朋友會發(fā)現(xiàn)其實我們的游戲引擎Cocos2d-XNA就是一個GameComponent而我們的OpenXLive SDK也是一個GameComponent,打開我們的主游戲類Game1源代碼中叫GameMain,就是找到繼承于Microsoft.Xna.Framework.Game的類。
對比我們項目TweeJump和示例程序HelloCocos2d的Game1.cs文件,多的幾句代碼就是集成OpenXLive的方式。
Game1類中字段
//#error Please full your game Secret Key in below code
private string APISecretKey = "Y8eUF6f5xXEGSuw3DkKntbhQ";
XLiveFormManager manager;
Game1構(gòu)造函數(shù)中吧XLiveFormManager實例并Add到Component中
// Create XLive FormManager
manager = new XLiveFormManager(this, APISecretKey);
manager.OpenSession();
// Add XLive FormManager in Components
Components.Add(manager);
這里需要注意的是OpenXLive的GameComponents的Add必須放在Cocos2d-xna的游戲引擎的GameComponents之前。
在LoadContent()里加載資源給OpenXLive SDK UI添加背景和退出UI的事件。
Texture2D background = this.Content.Load<Texture2D>(@"images\OpenXLive");
manager.Background = background;
manager.UIExitingEvent += new EventHandler(manager_UIExiting);
void manager_UIExiting(object sender, EventArgs e)
{
CCDirector.sharedDirector().runningScene.visible = true;
}
如果在新建項目的時候你勾選了OpenXLive SDK這些代碼都是默認添加到Game1.cs中的。
下面以MainMenu為例教你在游戲中使用OpenXLive SDK。
init()方法中創(chuàng)建一個按鈕
CCMenuItemImage Lobby = CCMenuItemImage.itemFromNormalImage(
@"images\Lobby", @"images\Lobby1", this,
new SEL_MenuHandler(LobbyCallback));
Lobby.position = new CCPoint(0, 20);
CCMenu LMenu = CCMenu.menuWithItems(Lobby);
LMenu.position = new CCPoint(240, 60);
回調(diào)方法:
public virtual void LobbyCallback(CCObject pSender)
{
CCDirector.sharedDirector().pause();
CCDirector.sharedDirector().runningScene.visible = false;
OpenXLive.Forms.XLiveFormFactory.Factory.ShowForm("Lobby");
}
OpenXLive.Forms.XLiveFormFactory.Factory.ShowForm("Lobby");show出我們需要的窗體這里是Lobby,除了”Lobby”還有"Startup"、"Leaderboard"、"Achievements"、"Logon"、"MyCenter"、"FirendsList"、"OnlinePlayer"、"Pause"、 "OpenXLiveGames"。
TweeJump源代碼中使用了"Achievements"、"Leaderboard"、"Lobby"這三個常用功能。在Show出窗體后務(wù)必把游戲暫停當(dāng)前Scene隱藏。在回來的時候也務(wù)必把游戲開始當(dāng)前Scene顯示。
void manager_UIExitingEvent(object sender, EventArgs e)
{
CCDirector.sharedDirector().runningScene.visible = true;
CCDirector.sharedDirector().resume();
}
開發(fā)資源
源代碼下載地址
http://tweejump.codeplex.com/
網(wǎng)站
http://www.cocos2d-x.org/
QQ群
190784175
電子郵箱

浙公網(wǎng)安備 33010602011771號