免責聲明:本文章由fengyun1989創作,採用知識共享署名-非商業性使用-相同方式共享 2.5 中國大陸許可協議進行許可。
寫在前面:最近兩個月比較忙,很久沒更新教程了。這麼些日子,發生了不少事,WP8發佈了。我的T8788也被徹底拋棄了。。。win8也RP版了。前景未卜啊。肯定不少人在迷茫了吧。我覺得呢,都是浮雲,語言只是工具,能夠一通百通才是王道,微軟不行大不了換IOS,Android。接下來的一段時間,估計會寫些win8的教程。我感覺win8和WP8有種莫名的聯繫,不過也道不清說不明。反正就順着感覺來了。
本次教程寫一個簡單的打地鼠遊戲。如果你對cocos2d-x編程不瞭解,可以先閱讀《用cocos2d-x做一個簡單的windows phone 7遊戲》系列文章。不過,如果你有相關的經驗就另當別論了。
程序截圖:
思路簡介:
打地鼠主要是問題就在於地鼠出頭和打地鼠的點擊處理。地鼠出頭有兩種方法,一種是用動畫,一種是用Z軸的縱向效果。動畫效果的方法Nowpaper前段時間就寫了這麼一篇《Cocos2d-x for WindowsPhone:開發一個打地鼠遊戲》,我想就不在這裏囉嗦了。懶得再將這些重複的內容在做一遍。這裏就介紹下Z軸的方法。
只要把前景分爲3塊。分爲上中下三塊,在洞的中心分開。添加到層的時候設置Z軸,最下的最前,最上的最後。最後後的設置一塊黑色的背景。兩塊圖之間留着空間來讓地鼠Sprite進行move動作。這樣就能產生地鼠從洞中鑽出的視覺效果了。
現在來下載需要的圖片;http://dl.dbank.com/c0tayrr384
開始吧:
新建一個工程cocos2d的工程,命名爲cocos2dWhacAMoleDemo。當然,因爲是練習項目,所以OpenXLive沒有用到。就去掉那個勾。然後修復引用。這些操作做了很多次了。不懂的建議看下以前的文章。
然後再Classes文件夾添加一個類。命名爲AttackMoleScene.cs,使之繼承於CCScene。修改代碼如下:
namespace cocos2dWhacAMoleDemo.Classes
{
class AttackMoleScene:CCScene
{
public AttackMoleScene()
{
this.addChild(AttackMoleLayer.node());
}
}
class AttackMoleLayer : CCLayer
{
public override bool init()
{
if (!base.init())
return false;
CCSize winSize = CCDirector.sharedDirector().getWinSize();
CCSprite background = CCSprite.spriteWithFile(@"images/background");
background.position = new CCPoint(winSize.width / 2, winSize.height / 2);
this.addChild(background, -3);
CCSprite grassUpper = CCSprite.spriteWithFile(@"images/grass_upper");
grassUpper.position = new CCPoint(winSize.width / 2, winSize.height - grassUpper.contentSize.height / 2);
this.addChild(grassUpper, -2);
CCSprite grassMid = CCSprite.spriteWithFile(@"images/grass_mid");
grassMid.position = new CCPoint(winSize.width / 2,
winSize.height - grassUpper.contentSize.height - grassMid.contentSize.height / 2);
this.addChild(grassMid, 0);
CCSprite grassLower = CCSprite.spriteWithFile(@"images/grass_lower");
grassLower.position = new CCPoint(winSize.width / 2, grassLower.contentSize.height / 2);
this.addChild(grassLower, 2);
return true;
}
public new static AttackMoleLayer node()
{
AttackMoleLayer layer = new AttackMoleLayer();
if (layer.init())
return layer;
return null;
}
}
}
上面做了些什麼呢,在層裏面添加了前景。三塊,細心的朋友注意到了。我addChild的時候,Z軸的參數都不一樣。背景在最後,所以Z軸的值最小。每兩塊間留一個位置給地鼠冒頭。前景的位置也是設置成上中下三個位置。這樣,從Z軸的上頭看下就能正好成一整塊前景。
現在修改AppDelegate的applicationDidFinishLaunching方法:
//CCScene pScene = cocos2dWhacAMoleDemoScene.scene();
AttackMoleScene pScene = new AttackMoleScene();
//run
pDirector.runWithScene(pScene);
現在可以執行了。就可以看到不錯的前景了。
那麼現在來添加一個地鼠來冒一下頭試試吧。
在層的init方法上面添加:
CCSprite mole = CCSprite.spriteWithFile(@"images/mole_1");
mole.position = new CCPoint(155,30);
var move = CCMoveBy.actionWithDuration(2, new CCPoint(0, 100));
var action = CCRepeat.actionWithAction(CCSequence.actions(move, move.reverse()), 5);
mole.runAction(action);
this.addChild(mole, 1);
添加一個地鼠到層中,並且設置它在左下角的洞裏進行Move來回運動。關於這個座標(155,30)是怎麼算出來的,我用畫圖工具打開grass.png這個文件,用鼠標來大概獲取座標,然後用筆算下座標。需要注意的是,cocos2d-x裏面的座標原點在左下角。而window的是在左上角。
現在編譯運行,就能看到一個地鼠來回冒頭了。
讓地鼠隨機冒頭
我們先來思考下接下來的怎麼做,怎麼保存所以的地鼠精靈,怎麼確定初始化座標,怎麼判斷地鼠被打,然後讓他消失,怎麼確定洞裏面有地鼠而不至於重複添加。
我的方法是全部用數組來解決。比較簡單。
添加以下的聲明到層:
int[,] moleValue = new int[2, 3] { { 0, 0, 0 }, { 0, 0, 0 } };
CCSprite[,] moles = new CCSprite[2, 3];
int[] initPositionX = new int[3] { 155, 400, 640 };
int[] initPositionY = new int[2] {30, 260};
上面的moleValue記錄的是當前洞裏有沒有地鼠,1就是有,0就是沒有。moles記錄當前所有冒頭地鼠的引用。最後兩個是初始化座標,3*2=6. 這些座標都是我通過畫圖工具來計算出來的。
現在註釋到上面的單個地鼠冒頭的代碼。往層裏面添加方法:
void addMole(float dt)
{
Random r = new Random();
int i = r.Next() % 3;
int j = r.Next() % 2;
if (moleValue[j, i] == 0)
{
moles[j, i] = CCSprite.spriteWithFile(@"images/mole_1");
moles[j, i].position = new CCPoint(initPositionX[i], initPositionY[j]);
var move = CCMoveBy.actionWithDuration(2, new CCPoint(0, 100));
var action = CCSequence.actions(move, move.reverse()
, CCCallFuncN.actionWithTarget(this, spriteMoveDone));
moles[j, i].runAction(action);
moleValue[j, i] = 1;
if (j == 0)
this.addChild(moles[j, i], 1);
else
this.addChild(moles[j, i], -1);
}
}
void spriteMoveDone(object sender)
{
CCSprite sprite = sender as CCSprite;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 2; j++)
{
if (moles[j, i] == sprite)
{
moleValue[j, i] = 0;
break;
}
}
}
this.removeChild(sprite, true);
}
並且添加一行到init方法
this.schedule(addMole, 1.0f);
我們修改地鼠變爲只是上下Move一次。並且在退回後調用回調函數移除該sprite。設置該位置的moleValue值爲0.現在就能看見地鼠不怕死的不斷冒頭了。
打地鼠
既然地鼠都不怕死的冒出來了。不打貌似很不爽的樣子,但是,現在點擊屏幕,沒人任何反應。。。因爲我們還沒有對點擊進行註冊和處理。
那麼怎麼判斷是點擊了地鼠呢。我設定這麼一個範圍算是點擊了地鼠。
由於地鼠初始化在框的下面,其座標的X和在這個黑色框下邊的中點座標X一樣。Y值+70纔算和這個黑色框下邊的中點的座標Y值一樣。
現在添加一個方法來處理觸點座標:
private void handleTouchPosition(CCPoint touch)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 2; j++)
{
float tempX = initPositionX[i] - touch.x;
if ((tempX < 80 && tempX > -80) && (initPositionY[j] + 150 - touch.y > 0 && initPositionY[j] + 70 < touch.y))
{
if (moleValue[j, i] == 1)
{
if (moles[j, i] != null)
{
this.removeChild(moles[j, i], true);
}
moleValue[j, i] = 0;
moles[j, i] = null;
}
return;
}
}
}
}
這樣,遍歷所有的洞,判斷點擊是否是這個洞。然後判斷現在是否有地鼠,有地鼠就把地鼠移除。
現在在init方法中註冊觸摸事件:
this.isTouchEnabled = true;
然後重載ccTouchesEnded方法:
public override void ccTouchesEnded(List<CCTouch> touches, CCEvent event_)
{
foreach (var touch in touches)
{
CCPoint touchLocation = touch.locationInView(touch.view());
touchLocation = CCDirector.sharedDirector().convertToGL(touchLocation);
touchLocation = this.convertToNodeSpace(touchLocation);
handleTouchPosition(touchLocation);
}
}
這個方法先把座標轉換,再處理座標。現在運行,可以看到地鼠被打死了。
何去何從
現在,我們已經擁有了一個不錯的打地鼠遊戲。是不是覺得少了點什麼呢。。
- 考慮拓展地鼠被打的動作,加個錘子或者什麼的。另外,可以添加地鼠被打後的表情,這都可以用Action可以實現
- 把硬編碼的地鼠重構出來,添加多個關卡
- 去試試用動畫來製作地鼠冒頭
- 增加更多種類的地鼠,比如說有些地鼠可以捱打2下
- 添加很棒的音效
本次工程代碼下載:http://dl.dbank.com/c0bgua6l79