(译)如何使用cocos2d来制作一个打地鼠的游戏:第一部分
免責申明(必讀!):本博客提供的所有教程的翻譯原稿均來自于互聯網,僅供學習交流之用,切勿進行商業傳播。同時,轉載時不要移除本申明。如產生任何糾紛,均與本博客所有人、發表該翻譯稿之人無任何關系。謝謝合作!
原文鏈接地址:http://www.raywenderlich.com/2560/how-to-create-a-mole-whacking-game-with-cocos2d-part-1
教程截圖:
在iOS Programming 101課程中,我的一個學生提議,讓我寫一個教程,關于如何使用cocos2d來制作一個打地鼠的游戲。?
我認為這是一個非常好的主意,原因有三:
這個教程建立在下列教程的基礎之上:
- 如何使用cocos2d來制作一個簡單的iphone游戲
- 如何在cocos2d里面使用動畫和spritesheet
- 在cocos2d里面如何使用Texture Packer和像素格式來優化spritesheet?
- 在cocos2d里面如何拖拽精靈
如果你還沒有閱讀上面這些教程,我強烈建議你先讀一讀。
這是一個兩部分的教程。在第一部分中,我們將會創建基本的游戲框架--有一些可愛的地鼠從洞里面鉆出來。我們將會花費大量的時候來討論如何組織圖片資源和坐標計算,以便于你的游戲能夠同時運行在iPhone3GS、ipad和高清顯示的iphone(其實是就是iphone4)上面,同時還要保證游戲性能!
規劃圖片資源: 總覽
因為,我們想讓這個應用能夠同時運行在iphone、retina-display iphone和ipad上面,所以,我們需要花點時間來仔細考慮一下,如何制作圖片,主要是圖片的尺寸!
為了理解到底多大的尺寸合適,首先,我們要先討論下面三個主題:
- Retina Display and UIKit
- Retina Display and Cocos2D
- iPad, iPhone, and Aspect Ratios
Retina Display and UIKit
普通的iphone和支持高清顯示的iphone之間的差別就是支持高清顯示的iphone能夠顯示2倍的像素。因此(在landscape模式下),普通的iphone顯示480×320個像素,而支持高清的iphone則可以顯示960×640個像素。
“但是,請等一下”,你可能會問,“如果顯示2倍數量的像素,那么不會破壞那些已經寫好的假設屏幕大小只有480×320的應用程序嗎?” 沒錯,特別是當你使用UIKit編程的時候,通常都是硬編碼frame的大小。但是,如果你在UIKit里面指定frame大小的時候,實際的單位是點,而不是像素。
在一個普通的iphone上面(不支持retina display),一個點就等于一個像素。但是,在支持retina的iphone上面,一個點等于2個像素。因此,當你指定(10,10),在普通的iphone上面也是(10,10),而在支持retina的iphone上面,則是(20,20),因此,那會是同樣的相對偏移量。(因為,像素加倍了,相對于圖片來說,相對偏移量相等)。
當你使用apple的控件或者Core Graphics,Apple已經寫了一些代碼來確保在Retina顯示的時候沒有問題。(因為你寫代碼指定大小都是point為單位)
唯一的需要注意的就是使用圖片的時候。比如你在一個iphone程序中使用了一張200×200的圖片,如果你什么也不做,那么retina顯示會把這張圖的尺寸放大2倍--那樣會很難看,如下圖所示,會模糊。
因此,你所需要做的就是為所有的圖片提供兩種版本,一種普清的,一種高清的。如果在高清圖片名字后面增加一個@2x后綴(比如sample@2x.png),那么不管什么時候,你只要調用[UIImage imageNamed:...]或者一些更簡單的api,當程序編譯到支持高清設備的時候,就會自動加載后綴為@2x的圖片。
因此,制作一個支持Retina顯示的UIKit程序是非常容易的,只需要為每一張普清圖片同時提供一個高清版本(2倍像素),并且指定為@2x后綴即可。
那么cocos2d里面該如何做呢?
Retina Display and Cocos2D
告訴你們一個好消息--最新版本的cocos2d完全支持retina顯示,而且使用這個功能只需要下列1-2-3步:
因此,你只需要讓美工提供給你高清格式的圖片就行了,你可以很容易地使用軟件把這些高清圖片變得普清圖片。比如TexturePacker就可以做這樣的事。
你可能會奇怪,為什么需要準備兩種不同格式的圖片--為什么不每次都加載高清的圖片,然后當需要普清圖片的時候,用程序來縮放?好吧,因為把紋理(texture)加載到內存里面是非常消耗內存的操作,如果某個程序被安裝在不支持高清顯示的設備上面(比如IPOD2),那么你就會占用兩倍大小的內存,當然是相比于只加載普清的圖片的程序。(因為高清圖片像素個數多一倍,所以必須消耗的內存要大。正確的做法就是前面說的,提供兩套圖片。)
不用擔心,你沒有必要在photoshop里面不停地縮放圖片的尺寸。TexturePaker里面有一個非常好的功能,可以很容易地通過高清圖片得到對應的普清圖片,這種方法在后面的教程中會講到。
iPad, iPhone, and Aspect Ratio
好,現在處理iphone上面的高清和普清顯示非常簡單了(準備兩套圖片),但是,iPad呢?該怎么做呢?
呃,要想編寫一個游戲,讓它同時能夠在iphone和ipad上面運行似乎是一件非常煩人的事--因為設備的縱橫比(aspect ratio)不一樣!
iphone支持480*320或者960*640---因此是1.5的縱橫比。然后,iPad是768*1024的--縱橫比等于1.33.
這意味著,如果你有一張圖片,能夠完全覆蓋iPad的背景(768*1024),如果你也想在iPhone里面繼續使用它。那恐怕不會匹配那么好。比如,你把它縮小,讓寬度等于iphone的寬度(通過乘以0.9375):你會得到720*960,因此,還是會有一部分圖像不能顯示!
這讓事情變得有點惱火了,因為,不只是背景圖片的問題,因為縱橫比的不同,原先設置節點使用的坐標就不能夠再使用了。
目前有一些方法可以解決這個問題,下面列舉了一些我看過的、聽過的和使用過的(如果你們有更好的方法,可以留言):
- 考慮一個“可玩區域”,這個區域的大小等于640*960,同時把它放置在iPad的屏幕中間。這會使得游戲區域外面有一些空白--但是,你還可以放置一張位置不動、顏色相同的背景圖片,那么玩家在玩游戲的時候就很難發現了。這樣會使你很容易地在不同的設備之間使用相同的坐標值,并且還可以重用圖片資源。這個方法也是我們這個教程里所使用的方法。
- 你可以使你的iPad的程序的縱橫比與iPhone的縱橫比一樣,在iPad屏幕的邊界留出42個像素,把“主要內容”放置在685*1024的范圍中。如果,你可以把你的應用中的內容放置在684*1024的“盒子”中,那么你就可以為每一個設備使用縮放圖片了。
- 你可以為iPhone、iPad和Retina display的iPhone提供不同的圖片和坐標值。這樣的靈活性是最大的,但是,會產生更大的二進制程序文件,并且不同的設備上面的對象位置都需要重新計算。
另一個原因,cocos2d目前對iPad的支持并不是很友好。只是可以自動加載后綴為“-hd”的圖片,轉換坐標的工作還是得由你來做。
規劃圖片資源:結論
好,基于上面的討論,下面是這篇教程的圖片資源規劃:
- 圖片被設計成一個960*640的“可玩區域”大小,在高清的iphone上面就是全屏的,在iPad上面就會居中顯示。
- 高清圖片可以通過TexturePacker轉換成普清的,并且生成相應的spritesheet。
- 高清的圖片將以“-hd”作為后綴,而普清的圖片則沒有。cocos2d會根據當前是否支持高清顯示而加載相應的圖片。
- 背景是一個特例,因為它總是需要全屏。背景將會做成1024*768的大小(因為iPad屏幕的大小是1024*768)。當這張圖片用作iPhone上面的時候,會有一部分圖片會超過屏幕邊界,但是,在這個教程中,并沒有關系。(后面將會看到,背景顏色很單一)
- iPad版本版本將會包含一些代碼,用來加載“-HD”后綴的圖片,轉換坐標并設置到“可玩區域”內,使用合適的字體大小等。
首先,下載這篇教程的圖片資源,解壓,然后看看里面有什么:
- 在“foreground”文件夾中,前景大小為1024*768(也就是iPad的大小),但是,它實際上被劃分為兩個部分:上半部和下半部。因為我們將在這兩個部分當中放置三個“地鼠洞“,這樣就會看起來,地鼠真的是從地底下鉆出來的。
- 在”background“文件夾中,iPad的縱橫比是1.33,所以一半是512*384.這是因為,背景實際上是看不到的,只有通過3個地鼠洞才可以看到背景。這么小的范圍,完全沒有必要加載一張1024*1024的圖片。相反,我們加載一張小圖片,然后放大。
- 在"sprites”文件夾中,所有的精靈都被設置成可以放到960*640的“可玩區域”內。注意,還有一個地鼠圖片,二個地鼠動畫(一個笑的動畫,一個被打中時的動畫)。
好了,有足夠的背景信息了--是時候開始動手了!、
Getting Started
打開XCode,選擇“File\New Project...",然后選擇“User Templates\cocos2d\cocos2d Application”,再點擊”Choose...“。把工程命名為WhackAMole,單擊Save。
接下來,把你剛剛下載下來的圖片資源文件夾全部拷到工程目錄下面。它的位置應該是Classes文件夾的兄弟,如下圖所示:
接下來,確保你已經安裝了TexturePacker。如果你還不知道怎么使用它,可以查看譯者翻譯的另一篇教程。
你可以打開TexturePacker工具,并為這個項目創建所有的sprite sheet。你也可以使用TexturePacker的命令行工具,它可以和XCode集成,并且處理起來更加高效!
右擊Resources,選擇”Add\New File...“,選擇Mac OS X\Other\Shell Script,再點Next。取名為PackTextures.sh,然后點Finish。
然后把PackTextures.sh里面的內容替換成下面的代碼:
#!/bin/shTP="/usr/local/bin/TexturePacker"
if [ "${ACTION}"="clean" ]
then
echo "cleaning..."
rm resources/background*
rm resources/foreground*
rm resources/sprites*
else
echo "building..."
${TP} --smart-update \
--format cocos2d \
--data resources/background-hd.plist \
--sheet resources/background-hd.pvr.ccz \
--dither-fs \
--opt RGB565 \
Art/background/*.jpg
${TP} --smart-update \
--format cocos2d \
--data resources/background.plist \
--sheet resources/background.pvr.ccz \
--dither-fs \
--scale 0.5 \
--opt RGB565 \
Art/background/*.jpg
${TP} --smart-update \
--format cocos2d \
--data resources/foreground-hd.plist \
--sheet resources/foreground-hd.pvr.ccz \
--dither-fs-alpha \
--opt RGBA4444 \
Art/foreground/*.jpg
${TP} --smart-update \
--format cocos2d \
--data resources/foreground.plist \
--sheet resources/foreground.pvr.ccz \
--dither-fs-alpha \
--scale 0.5 \
--opt RGBA4444 \
Art/foreground/*.jpg
${TP} --smart-update \
--format cocos2d \
--data resources/sprites-hd.plist \
--sheet resources/sprites-hd.pvr.ccz \
--dither-fs-alpha \
--opt RGBA4444 \
Art/sprites/*.jpg
${TP} --smart-update \
--format cocos2d \
--data resources/sprites.plist \
--sheet resources/sprites.pvr.ccz \
--dither-fs-alpha \
--scale 0.5 \
--opt RGBA4444 \
Art/sprites/*.jpg
fi
exit 0
?
這個腳本運行TexturePacker來為背景圖片、前景圖片和精靈圖片創建相應的精靈表單(sprite sheet)--同時包含高清的和普清的。
注意,每一個圖片都被保存為pvr.cca格式,因為,這是一種磁盤占用空間小,并且內存消耗也少的圖片格式。當然,像素格式和抖動選項也被設置了,這是一個折中,綜合考慮內存消耗和圖片顯示質量。
如果你對TexturePacker的這些選項的功能不是很清楚,你可以打開終端(Terminal),然后輸入TexturePacker -help,那么就會有完整的選項功能列表。
接下來,你需要做一些設置,在你的工程每次編譯的時候,可以運行這個shell腳本。右鍵點擊Targets,選擇“Add\New Target...",再選擇"External Target”(注意不要選擇Shell Script Target!),然后點擊Next。把這個Target命名為TexturePacker并點擊Finish。
然后右鍵點擊剛剛建立的這個Target,修改它的設置,如下圖所示:
最后一步,就是為你的程序設置target依賴。雙擊項目Target,然后找到General標簽,點下面的+號,再從彈出的列表中選擇TexturePacker Target,并點擊Add Target。
編譯你的工程,如果輸出結果如下圖所示,那么就證明你的配置OK。(注意,上面的這些全是針對XCode3所設置的,XCode4大同小異,只是界面不一樣了,原理不變)
接下來,把剛剛生成的精靈表單和相應的屬性列表增加到項目中。右擊Resources,選擇“Add\Existing Files...”,然后選擇background,foreground和sprites文件(總共有12個文件),再點Add.如果做完后,那么看起來會是下圖這個樣子:
如果你愿意,你可以雙擊任何一個.pvr.ccz文件,打開看看,里面到底有什么。你就會發現TexturePacker有多么方便了!
設置背景
接下來,HelloWorldScene.m文件并找到init方法。刪掉自動生成的那4行創建一個label的代碼。同時,用下面的代碼替換掉:
// Determine names of sprite sheets and plists to loadNSString *bgSheet =@"background.pvr.ccz";
NSString *bgPlist =@"background.plist";
NSString *fgSheet =@"foreground.pvr.ccz";
NSString *fgPlist =@"foreground.plist";
NSString *sSheet =@"sprites.pvr.ccz";
NSString *sPlist =@"sprites.plist";
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
bgSheet =@"background-hd.pvr.ccz";
bgPlist =@"background-hd.plist";
fgSheet =@"foreground-hd.pvr.ccz";
fgPlist =@"foreground-hd.plist";
sSheet =@"sprites-hd.pvr.ccz";
sPlist =@"sprites-hd.plist";
}
// Load background and foreground
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:bgPlist];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:fgPlist];
// Add background
CGSize winSize = [CCDirector sharedDirector].winSize;
CCSprite *dirt = [CCSprite spriteWithSpriteFrameName:@"bg_dirt.jpg"];
dirt.scale =2.0;
dirt.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:dirt z:-2];
// Add foreground
CCSprite *lower = [CCSprite spriteWithSpriteFrameName:@"grass_lower.jpg"];
lower.anchorPoint = ccp(0.5, 1);
lower.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:lower z:1];
CCSprite *upper = [CCSprite spriteWithSpriteFrameName:@"grass_upper.jpg"];
upper.anchorPoint = ccp(0.5, 0);
upper.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:upper z:-1];
// Add more here later...
?
好,讓我們一個一個來講解,因為,這里面有許多新的東西。
1.決定加載的精靈表單和plist文件的名字。這個部分,把TexturePacker生成的精靈表單和plist文件,按照某種方式加載進來了。注意,在iPhone上面,cocos2d會自動地加載“-HD”和不帶“HD”的版本,具體取決于是否激活Retina 顯示。然后,在iPad上面,它并不會加載"-hd"版本,所以你必須手動告訴它加載,因此,上面我們判斷,如果是iPad,那么就加載帶"-hd"版本的資源。
2.加載背景和前景。接下來就是把背景、前景還有精靈都加載到精靈幀緩沖(sprite frame cache)中,以便后面可以使用。注意,目前精靈并沒有加載到CCSpriteBatchNode中。
????? 3.添加背景。背景圖片作為當前層的一個孩子被加進去。(Z=-2的話,就可以使任何對象都在它上面,除非其它對象的Z小于-2)。接下來,把這張圖片放大兩倍,因為,之前,我們為了節約內存,只使用了一半大小的圖片。之后,再把圖片放置到屏幕中間。
4.前加前景。前景是當作兩個部分加上去的。這里用了一種非常簡單的設置精靈圖片坐標點的方式,通過設置精靈的錨點為圖片的中點,或者底部,或者頂部。通過這種方式,假如你要把一張圖片的左下角設置為屏幕的左下角,你只需要先把圖片的錨點設置為(0,0),然后設置position為0,0就好了。非常方便!而且,這個坐標值,在所有的設備上都通用。注意,背景部分超出屏幕之外了,但是,這并沒有關系,因為用戶看不到。還要注意的是,圖片增加的時候,使用了不同的Z值,最后面的圖片使用最小的Z值。
編譯并運行,你會看到如下的輸出。你可以通過模擬器測試,也可以通過真機測試,看看效果到底如何^^。
如果你嘗試在支持高清的設備上運行,你會注意到,圖像有模糊,似乎還是使用普清的資源。
這是因為,我們還有一步沒有做完:還需要調用CCDirector的enableRetinaDisplay方法能激活高清顯示。
為了實現這個目的,打開WhackAMoleAppDelegate.m,然后在applicationDidFinishLaunching方法里面,刪除那三句注釋:
if( ! [director enableRetinaDisplay:YES] )CCLOG(@"Retina Display Not supported");
?
編譯并運行,現在,再嘗試使用支持高清的設備吧,這時就會加載高清圖片資源了。
放置地鼠
對于這個游戲來說,你將會在場景中添加3只地鼠--每個洞一個地鼠。地鼠會躲在草的下面,但是,會突然從某個洞里冒出來,這樣你就可以打它了。
首先,讓我們為每個洞的下面添加一只地鼠。我們會先讓它們在所有的圖片上面,這樣,可以確保位置對了,然后通過修改Z值,就能夠把它們隱藏到草地后面去了。
打開HelloWorldScene.h,然后增加一個數組來保存當前關卡的地鼠,如下所示:
// Inside @interface HelloWorldNSMutableArray *moles;
通過保存地鼠的數組,我們可以很容易地遍歷每一只地鼠。
接下來,在init方法中添加一些代碼來放置地鼠(添加位置位于?“Add more here later…”注釋后面),如下所示:
// Load spritesCCSpriteBatchNode *spriteNode = [CCSpriteBatchNode batchNodeWithFile:sSheet];
[self addChild:spriteNode z:999];
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:sPlist];
moles = [[NSMutableArray alloc] init];
CCSprite *mole1 = [CCSprite spriteWithSpriteFrameName:@"mole_1.jpg"];
mole1.position = [self convertPoint:ccp(85, 85)];
[spriteNode addChild:mole1];
[moles addObject:mole1];
CCSprite *mole2 = [CCSprite spriteWithSpriteFrameName:@"mole_1.jpg"];
mole2.position = [self convertPoint:ccp(240, 85)];
[spriteNode addChild:mole2];
[moles addObject:mole2];
CCSprite *mole3 = [CCSprite spriteWithSpriteFrameName:@"mole_1.jpg"];
mole3.position = [self convertPoint:ccp(395, 85)];
[spriteNode addChild:mole3];
[moles addObject:mole3];
首先,為精靈創建一個CCSpriteBatchNode,這樣就可以更加高效地渲染這三只地鼠了。(每次只需要一個OpenGL call),并把batchNode當作當前層的一個孩子加進去。注意,Z值被臨時設置成999,因此,地鼠就會顯示在所有的圖片之前,那樣我們就可以判斷地鼠位置是否正確。
然后從精靈幀緩沖中加載所有的精靈。接著,為每一個地鼠創建一個精靈,把它們放置在場景中,同時添加到數組里面。注意,每個地鼠的坐標是在一個480*320的“可玩區域”內(iphone屏幕的大小)。對于iPad來說,這些點需要做一些轉換,因此,我們定義了一個輔助函數convertPoint。接下來,在Init方法的上面加入下列代碼:
- (CGPoint)convertPoint:(CGPoint)point {if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
return ccp(32+ point.x*2, 64+ point.y*2);
} else {
return point;
}
}
這個方法把“可玩區域”內的一個點轉換成合適的iPad屏幕上面的點。記住:
- 我們在iPad上面使用的是高清的圖像,所有的像素點都要加倍。
- 我們把960*640的區域居中放在1024*768的iPad屏幕上,因此,左右兩邊要留下32個像素的margin,上下兩邊要留下64個像素的margin。
因此, 這個方法只是做了一些簡單的數學計算,使得坐標在iPad上面不會出問題。
還有一件事---在忘記之前,我們需要做一些內存清理操作,找到dealloc方法,添加下列代碼:
[moles release];moles = nil;
?
編譯并運行,你將看到3只地鼠放置在正確的位置上了!你因此同時測試一下iPhone,Retina iPhone和iPad,確保每個設備上看起來都沒問題。
彈出地鼠
現在,我們確定地鼠的位置沒有問題了,接下來,讓我們添加一些代碼,讓他們能夠從地下鉆出來吧!
第一件事,把Z值,從999改成0,這樣的話,地鼠就會在地底下了。
改完之后,在init方法的后面添加下面的代碼:
[self schedule:@selector(tryPopMoles:) interval:0.5];如果之前你沒有見過這樣的用法,你可以調用其它的方法,比如schedelUpdate。但是,這個例子中,我們只想讓地鼠每隔0.5秒鉆出一個。
接下來,增加tryPopMoles方法:
- (void)tryPopMoles:(ccTime)dt {for (CCSprite *mole in moles) {
if (arc4random() %3==0) {
if (mole.numberOfRunningActions ==0) {
[self popMole:mole];
}
}
}
}
?
這個方法會每隔0.5秒調用一次,每一次它都會循環判斷每一個地鼠,讓它有1/3的機會從洞里面鉆出來。但是,如果它已經鉆出來,也就是運行的action的個數不等于0的話,那么也不會再鉆了。
最后,實現popMole:方法:
- (void) popMole:(CCSprite *)mole {CCMoveBy *moveUp = [CCMoveBy actionWithDuration:0.2 position:ccp(0, mole.contentSize.height)]; // 1
CCEaseInOut *easeMoveUp = [CCEaseInOut actionWithAction:moveUp rate:3.0]; // 2
CCAction *easeMoveDown = [easeMoveUp reverse]; // 3
CCDelayTime *delay = [CCDelayTime actionWithDuration:0.5]; // 4
[mole runAction:[CCSequence actions:easeMoveUp, delay, easeMoveDown, nil]]; // 5
}
?
這個代碼,使用cocos2d的action來制作彈出洞的效果,先彈出來,然后暫停半秒,再鉆回去。讓我們一行一行地解釋:
就這么多!編譯并運行代碼,你將會看到3只地鼠交替地鉆出洞來,cool吧?
何去何從?
本教程完整源代碼。
期待這個教程的后續吧,在那個教程里,我們會添加很酷的動畫,同時會添加一些游戲邏輯,使得你可以打地鼠并且得分。當然,還有非常好聽的音樂。
譯者的話:翻譯如果有語法錯誤還忘指出,最近時間比較緊,校對工作沒時間仔細做了,歡迎大家不吝指出!
?
著作權聲明:本文由http://www.cnblogs.com/andyque翻譯,歡迎轉載分享。請尊重作者勞動,轉載時保留該聲明和作者博客鏈接,謝謝!
總結
以上是生活随笔為你收集整理的(译)如何使用cocos2d来制作一个打地鼠的游戏:第一部分的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android stackover fl
- 下一篇: CACTI使用指南