【吼吼睡cocos2d学习笔记】第四章 - 第一个游戏
來讓我們開始第一個游戲的制作。
這個過程可能有點艱辛,但是只要堅持下來,第一個游戲往往能給我們帶來巨大的收益(當然這個收益不是經濟上的:-P)
先上截圖:
iPad中:
游戲構思
角色
在屏幕的上方,有一定數量的敵人(蜘蛛),屏幕下方有一只玩家控制的熊貓。
游戲流程
每間隔一段時間,會有一只蜘蛛爬下來襲擊熊貓,熊貓通過移動來躲避攻擊。隨著游戲的進行,蜘蛛下降的速度會越來越快,出動的頻率會越來越高。
勝負判定
熊貓躲避過一定數目的蜘蛛以后獲勝,在此之前玩家用完所有生命則失敗。
游戲展示動畫,其實是有音效的,可能屏幕錄像的軟件不能捕捉來自模擬器的聲音:展示動畫
分析
我們按照事務流的方式來對整個游戲進行簡單分析:
1.啟動游戲,加載主頁面。本示例不做菜單,不做配置,直接進入游戲場景。
2.將游戲置為READY狀態;初始化各種數據;根據屏幕的寬度計算蜘蛛的個數,初始化蜘蛛精靈;初始化熊貓精靈
3.當玩家觸摸屏幕以后,游戲開始,游戲狀態設置為PLAYING,啟動以下計時器:
3a.播放蜘蛛幀動畫的計時器
3b.搜索下一個出動的蜘蛛計時器
3c.碰撞檢測的計時器
4.玩家用手指控制熊貓在屏幕下方移動,這里要注意的是,接收觸摸事件的是熊貓,如果觸摸點不在熊貓上,它是不能移動的。因此需要給熊貓精靈添加一個targetedTouchDelegate。同時要防止熊貓劃出屏幕邊界。
5.定時檢測下一個出動的蜘蛛,找到以后,讓蜘蛛下移的屏幕低部,然后復位,如果熊貓躲避過來此次攻擊,加分。當出動的蜘蛛次數超過一定量的時候(本游戲中是8次),加快游戲速度,加快蜘蛛出動頻率。同時判斷是否已經滿足勝利條件。
6.當碰撞檢測計時器檢測到碰撞后,停止出動蜘蛛計時器、碰撞檢測計時器、動畫播放計時器,生命減一,判斷是否還有剩余生命。如果沒有,Game Over,游戲狀態設置為END;如果還有生命,游戲狀態設置為DEAD。
7.當玩家觸摸屏幕的時候:
7.a.如果游戲狀態是READY,開始游戲。
7.b 如果游戲狀態是DEAD,復位蜘蛛和熊貓,啟動各個計時器。
7.c 如果游戲狀態為其他狀態,無視。
8.對熊貓精靈的事件分析:
當熊貓精靈接收到觸摸事件以后,判斷是否命中到了精靈范圍內,如果是,吃掉該事件,否則讓該事件繼續下發給其他對象。
9.注意,為了無縫的向iPad設備上移植,需要注意:計量避免出現假設性代碼,所有的尺寸都根據屏幕尺寸計算。
開工
XCode->New Project->IOS->cocos2d-name it->finish!
刪掉默認的helloWorld層,按照下圖,創建Group:
Sprites:盛放精靈類
Layers:盛放所有層
Scenes:盛放所有的場景
RootViewController.m
本游戲適合在豎屏模式下進行,因此需要做以下修改:
#elif GAME_AUTOROTATION == kGameAutorotationUIViewControllerreturn ( UIInterfaceOrientationIsLandscape( interfaceOrientation ) );
修改為
#elif GAME_AUTOROTATION == kGameAutorotationUIViewControllerreturn ( UIInterfaceOrientationIsLandscape( interfaceOrientation ) );
AppDelegate.m
因為刪除了HelloWorld層,現在需要啟動我們自己添加的GameScene場景,因此需要修改AppDelegate.m的相關代碼:
找到applicationDidFinishLaunching方法中[CCDirector sharedDirector] runWithScene的代碼,此代碼的作用是讓【導演】運行第一個游戲場景,將之修改成:
[[CCDirector sharedDirector] runWithScene: [GameScene scene]];GameScene使我們自己設計的場景類,在Scenes文件組中,scene是該類的初始化方法,負責返回一個GameScene對象。
?
?
做完這些以后我們來實現主場景類:GameScene
首先在.h文件中添加靜態scene方法的聲明:
+(CCScene *)scene;在.m文件中實現該方法,同時加上對資源的釋放:
-(void)dealloc{
[super dealloc];
}
+(CCScene *)scene
{
CCScene *sc = [CCScene node];
[sc addChild:[GameLayer node]];
return sc;
}
scene方法中構造了一個CCScene對象,并將GameLayer層作為子節點加入其中。
?
其實在IOS開發中,scene對象中的代碼量往往非常少,代碼大部分出現在層和精靈中。
?
在看關鍵的GameLayer以前,我們先來看一下熊貓精靈(PandaSprite)類
這個類繼承自CCSprite,同時實現了CCTargetedTouchDelegate協議。這是.m中的代碼
// GameLayer.h// CH04
//
// Created by 李慶輝 on 11-12-8.
// QQ:66927785
// Blog:http://blog.csdn.net/redparty
// Copyright 2011年 __MS__. All rights reserved.
//
#import "PandaSprite.h"
@implementation PandaSprite
@synthesize curLayer;
//釋放delegate
-(void)onExit
{
[[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
[super onExit];
}
//當被node的時候,觸發該事件,注冊targetedDelegate
-(void)onEnter
{
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
[super onEnter];
}
//獲得自身的rect,用來進行命中判定
-(CGRect)rect
{
return CGRectMake(-rect_.size.width * 0.5, -rect_.size.height * 0.5, rect_.size.width, rect_.size.height);
}
//當touch開始的時候,判定是否命中了自身,如果是,吃掉該事件,反之忽略該事件
-(BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
if (CGRectContainsPoint([self rect], [self convertTouchToNodeSpaceAR:touch])) {
return YES;
}
return NO;
}
//根據玩家的觸摸,變換主角的位置。
-(void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
//獲得GameLayer中的gameStatus的值,如果不是PLAYING,則忽略當前觸摸。
if ([curLayer getGameStatus] != @"PLAYING") {
return;
}
CGSize sizeOfWin = [[CCDirector sharedDirector] winSize];
//獲得自己的尺寸的一半,用來對左右兩邊緣的位置進行校正
CGSize halfOfMyself;
halfOfMyself = CGSizeMake([self contentSize].width * 0.5, [self contentSize].height * 0.5);
//根據自身的大小確定自己在x軸方向上的最小值和最大值
CGFloat minX = halfOfMyself.width;
CGFloat maxX = sizeOfWin.width - halfOfMyself.width;
CGPoint posOfTouch = [touch locationInView:touch.view];
CGPoint posForGL = [[CCDirector sharedDirector] convertToGL:posOfTouch];
//對越界情況進行校正
if (posForGL.x < minX) {
posForGL.x = minX;
}
if (posForGL.x > maxX) {
posForGL.x = maxX;
}
//坐標系轉換
posForGL.y = [self contentSize].height * 0.5;
self.position = posForGL;
}
@end
代碼中已經注視的非常清楚了,這里不再贅述。需要說明的是,在CCTouchMoved方法中,有如下代碼:
if ([curLayer getGameStatus] != @"PLAYING") {
return;
}
curLayer是在.h中聲明的id類型的對象:
// GameLayer.h// CH04
//
// Created by 李慶輝 on 11-12-8.
// QQ:66927785
// Blog:http://blog.csdn.net/redparty
// Copyright 2011年 __MS__. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "cocos2d.h"
@interface PandaSprite : CCSprite<CCTargetedTouchDelegate>
{
id curLayer;
}
@property (nonatomic,retain)id curLayer;
@end
id是Objective-C中所有節點的父類,相當于c#中的Object類。該對象將來會傳入一個GameLayer的對象。之所以這樣做是因為在熊貓精靈并非在任何時候都被允許移動的,只有在游戲狀態為PLAYING的時候才響應該事件。具體可以參看GameLayer.m中的getGameStatus方法。這是一種在精靈和層之間傳遞數據的方式。
?
?
好,現在看是來看重量級的GameLayer類
先看.h文件
// GameLayer.h// CH04
//
// Created by 李慶輝 on 11-12-8.
// QQ:66927785
// Blog:http://blog.csdn.net/redparty
// Copyright 2011年 __MS__. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "PandaSprite.h"
#import "SimpleAudioEngine.h"
@interface GameLayer : CCLayer {
//窗口尺寸
CGSize sizeOfWin ;
//蜘蛛的尺寸
CGSize sizeOfSpider;
//熊貓的尺寸
CGSize sizeOfPanda;
//盛放蜘蛛精靈的數組
CCArray *spiders;
//盛放熊貓生命的數組
CCArray *LivesPandas;
//主角精靈
PandaSprite *panda;
//蜘蛛的個數
int spiderNumber;
//控制游戲速度的一個因子,會被用在計算蜘蛛的下降速度和下降頻率上
CGFloat speed;
//當前的游戲狀態,分為:READY,PLAYING,DEAD,END,OVER
NSString *gameStatus;
//顯示分數的label
CCLabelTTF *lblScoreShow;
//顯示游戲信息的label
CCLabelTTF *lblInfo;
//動畫播放分數的label
CCLabelBMFont *lblScoreAnimate;
//沒有什么具體含義,僅僅被用來控制分數計算的頻率
int numSpidersMoved;
int livesCount;
//游戲得分
int score;
}
//播放蜘蛛動畫
-(void)playSpiderAnimate;
//重置蜘蛛們的位置
-(void)resetSpider;
//尋找下一個行動的蜘蛛
-(void)checkSpider:(ccTime)dt;
//將checkSpider尋找到的蜘蛛下墜并復位
-(void)downSpider:(CCSprite *)spider;
//作為downSpider中action的回調函數,負責讓到達屏幕底部的蜘蛛復位
-(void)makeSpiderBack:(CCSprite *)spider;
//碰撞檢測
-(void)checkCollision;
//停止所有發生在蜘蛛和主角上的動作。
-(void)stopAllAction;
//返回gameStatus的值,這個值會在PandaSprite中用到
-(NSString *)getGameStatus;
//該方法根據speed來改變蜘蛛出動的頻率。
-(void)changeCheckTimeout;
//創建死亡label
-(void)createLables;
//創建蜘蛛數組
-(void)createSpiderArray;
//創建顯示生命的熊貓
-(void)createLivesPandas;
//創建主角
-(void)createPanda;
//初始化游戲
-(void)initGame;
//用Action來顯示實時分數
-(void)showAnimateScore;
//當勝利的時候
-(void)whenWin;
//當碰撞的時候
-(void)whenCollision;
//根據當前剩余的生命顯示對應個數的熊貓
-(void)showLives;
//開始游戲相關的計時器
-(void)startSchedule;
//停止游戲相關的計時器
-(void)stopSchedule;
@end
有點多,但是每一行我的加上了注釋,每個方法的實現都在.m中:
// GameLayer.h// CH04
//
// Created by 李慶輝 on 11-12-8.
// QQ:66927785
// Blog:http://blog.csdn.net/redparty
// Copyright 2011年 __MS__. All rights reserved.
//
#import "GameLayer.h"
@implementation GameLayer
#define SPRITETAG 100
#define LABLE_TAG 150
#define SCORE_HEIGHT 30
#define SCALE_SPIDER 0.5
#define SCALE_PANDA 0.8
#define FADE_SCORE 45
#define SPEED 2
#define DTSPEED 250
#define MAXLIVES 5
#define SCALE_LIVESPANDA 0.25
static int framIndex;
//釋放層用到的非autoRelease資源
-(void)dealloc
{
[super dealloc];
[spiders release];
spiders = nil;
}
-(id)init
{
if (self = [super init]) {
[self initGame];
}
return self;
}
-(void)initGame
{
//獲得屏幕尺寸
sizeOfWin = [[CCDirector sharedDirector] winSize];
//創建label(分數、生命、死亡信息、win)
[self createLables];
//創建蜘蛛數組
[self createSpiderArray];
//創建主角
[self createPanda];
//創建顯示生命用的熊貓
[self createLivesPandas];
//重置蜘蛛位置
[self resetSpider];
//預加載音效文件,如果不予加載的話,第一次播放此音效的時候會卡至少一秒鐘。
[[SimpleAudioEngine sharedEngine] preloadEffect:@"bomb.caf"];
numSpidersMoved = 1;
score = 0;
livesCount = MAXLIVES;
framIndex = 1;
speed = SPEED;
gameStatus = @"READY";
[self setIsTouchEnabled:YES];
}
-(void)createPanda
{
//添加主角
CCSpriteFrameCache *frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:@"sprite.plist"];
panda = [PandaSprite node];
[panda setDisplayFrame:[frameCache spriteFrameByName:@"panda.png"]];
sizeOfPanda = [panda contentSize];
sizeOfPanda.width *= SCALE_PANDA;
sizeOfPanda.height *= SCALE_PANDA;
[self addChild:panda z:3];
//將本層傳入panda對象中,實現層和精靈的信息傳遞
panda.curLayer = self;
}
-(void)createLivesPandas
{
CCSpriteFrameCache *frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:@"sprite.plist"];
CCSprite *tmpPanda = [CCSprite spriteWithSpriteFrame:[frameCache spriteFrameByName:@"zz1.png"]];
//獲得生命區熊貓的尺寸
CGSize sizeOfLivesPanda = [tmpPanda contentSize];
sizeOfLivesPanda.width *= SCALE_LIVESPANDA;
sizeOfLivesPanda.height *= SCALE_LIVESPANDA;
LivesPandas = [[CCArray alloc] initWithCapacity:MAXLIVES];
for (int i = 0; i < MAXLIVES; i++) {
CCSprite * tmpPanda = [CCSprite spriteWithSpriteFrame:[frameCache spriteFrameByName:@"panda.png"]];
[LivesPandas addObject:tmpPanda];
tmpPanda.scale = SCALE_LIVESPANDA;
tmpPanda.position = CGPointMake((i+1)*sizeOfLivesPanda.width, sizeOfWin.height - sizeOfLivesPanda.height - 5 );
[self addChild:tmpPanda];
}
}
-(void)createSpiderArray
{
//創建蜘蛛精靈表的幀緩存,并加載蜘蛛精靈動作的plist文件
CCSpriteFrameCache *frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:@"sprite.plist"];
//生成臨時蜘蛛,獲取縮放以后蜘蛛的尺寸。
CCSprite* spider = [CCSprite spriteWithSpriteFrame:[frameCache spriteFrameByName:@"zz1.png"]];
spider.scale = SCALE_SPIDER;
sizeOfSpider = [spider contentSize];
sizeOfSpider.width *= SCALE_SPIDER;
sizeOfSpider.height *= SCALE_SPIDER;
//根據蜘蛛的尺寸計算可以放置的蜘蛛的個數,根據個數初始化蜘蛛數組
spiderNumber = sizeOfWin.width/sizeOfSpider.width;
spiders = [[CCArray alloc] initWithCapacity:spiderNumber];
for (int i = 0; i < spiderNumber; i++) {
CCSprite *tmpSpider = [CCSprite spriteWithSpriteFrame:[frameCache spriteFrameByName:@"zz1.png"]];
[spiders addObject:tmpSpider];
tmpSpider.scale = SCALE_SPIDER;
[self addChild:tmpSpider z:0 tag:SPRITETAG + i];
}
}
-(void)createLables
{
//信息
lblInfo = [CCLabelTTF labelWithString:@"" fontName:@"Arial" fontSize:22];
lblInfo.position = CGPointMake(sizeOfWin.width * 0.5, sizeOfWin.height * 0.5);
[self addChild:lblInfo z:100 tag:LABLE_TAG];
[lblInfo setVisible:NO];
[lblInfo setOpacity:125];
//分數
CCLabelTTF *lblScore = [CCLabelTTF labelWithString:@"分數:" fontName:@"Arial" fontSize:14];
lblScore.anchorPoint = CGPointMake(1, 1);
lblScore.position = CGPointMake(sizeOfWin.width - 60 - [lblScore contentSize].width/2, sizeOfWin.height - 10);
[self addChild:lblScore];
lblScoreShow = [CCLabelTTF labelWithString:@"0000000" fontName:@"Arial" fontSize:14];
lblScoreShow.anchorPoint = CGPointMake(1, 1);
lblScoreShow.position = CGPointMake(sizeOfWin.width - [lblScore contentSize].width/2,sizeOfWin.height - 10);
[self addChild:lblScoreShow];
//實時顯示當前得分的標簽,用到了BMFont,使用Hiero制作
lblScoreAnimate = [CCLabelBMFont labelWithString:@"" fntFile:@"myfont.fnt"];
lblScoreAnimate.scale = 0;
[lblScoreAnimate setOpacity:FADE_SCORE];
lblScoreAnimate.position = CGPointMake(sizeOfWin.width * 0.5, sizeOfWin.height * 0.5);
[self addChild:lblScoreAnimate];
//生命
}
-(void)resetSpider
{
//將蜘蛛們復位
CGSize halfSize = CGSizeMake(sizeOfSpider.width * 0.5, sizeOfSpider.height * 0.5);
CGFloat leftMargin = (sizeOfWin.width - sizeOfSpider.width * spiderNumber) * 0.5;
for (int i = 0; i < spiderNumber; i++) {
CCSprite *spider = (CCSprite *)[self getChildByTag:SPRITETAG + i];
spider.position = CGPointMake((i+1)*sizeOfSpider.width - halfSize.width+leftMargin , sizeOfWin.height - halfSize.height - SCORE_HEIGHT);
[spider stopAllActions];
}
//將熊貓復位
panda.position = CGPointMake(sizeOfWin.width * 0.5, sizeOfPanda.height * 0.5);
}
-(void)playSpiderAnimate
{
CCSpriteFrameCache *frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:@"sprite.plist"];
if (++framIndex >2) {
framIndex = 1;
}
for (int i = 0; i<spiderNumber; i++) {
CCSprite *tmpspider = [spiders objectAtIndex:i];
if ([tmpspider numberOfRunningActions] == 0) {
//為了讓蜘蛛的動畫產生不一致,避免所有的蜘蛛播放相同的紋理,將i也加入了計算中,最終得到的是一個介于1-2的整數
[tmpspider setDisplayFrame:[frameCache spriteFrameByName:[NSString stringWithFormat:@"zz%d.png",(framIndex + i)%2 +1]]];
}
}
}
-(void)changeCheckTimeout
{
[self unschedule:@selector(checkSpider:)];
[self schedule:@selector(checkSpider:) interval:0.25 * speed];
}
//尋找下一個出動的蜘蛛
-(void)checkSpider:(ccTime)dt
{
for (int i = 0; i<20; i++) {
int checkIndex = CCRANDOM_0_1() * spiderNumber;
CCSprite *spider = [spiders objectAtIndex:checkIndex];
//如果找到了一個本身沒有動作的蜘蛛,說明該蜘蛛還沒有出動,出動之。
if ([spider numberOfRunningActions] == 0) {
//出動蜘蛛
[self downSpider:spider];
break;
}
}
}
-(void)whenWin
{
[lblInfo setString:@"You Win!"];
[lblInfo setVisible:YES];
[self stopAllAction];
[self unschedule:@selector(checkSpider:)];
[self unschedule:@selector(checkCollision)];
gameStatus = @"END";
}
//計算分數,用動畫的方式現在在屏幕中間,同時累加到分數變量,顯示在右上角。
-(void)showAnimateScore
{
//根據當前speed計算當前得分,原則上是:速度越快,單位得分越高
int scoreBySpeed = ((SPEED+0.1)-speed) * DTSPEED;
score += scoreBySpeed;
[lblScoreAnimate setString:[NSString stringWithFormat:@"%d",scoreBySpeed]];
[lblScoreShow setString:[NSString stringWithFormat:@"%07d",score]];
//播放動畫前,將label透明度調大,尺寸縮小到0
lblScoreAnimate.scale = 0;
[lblScoreAnimate setOpacity:FADE_SCORE];
//創建一個放大動作和一個隱出動作
CCAction *acS = [CCScaleTo actionWithDuration:0.2 scale:3];
CCAction *acE= [CCFadeTo actionWithDuration:0.2 opacity:0];
//用CCSpawn的方式同步執行兩個動作
[lblScoreAnimate runAction:[CCSpawn actions:acS,acE, nil]];
}
//出動蜘蛛
-(void)downSpider:(CCSprite *)spider
{
//蜘蛛移動的目標位置
CGPoint targetPos = CGPointMake(spider.position.x, [spider contentSize].height * 0.5);
CCAction *ac = [CCMoveTo actionWithDuration:speed position:targetPos];
//當蜘蛛執行玩ac動作以后,回來執行callBack指向的回調函數:makeSpiderBack
CCCallFuncN *callBack = [CCCallFuncN actionWithTarget:self selector:@selector(makeSpiderBack:) ];
//用CCSequence的方式執行ac和callBack
[spider runAction:[CCSequence actions:ac,callBack, nil]];
}
//回調函數,讓蜘蛛復位
-(void)makeSpiderBack:(CCSprite *)spider
{
CGPoint backPos = CGPointMake(spider.position.x, sizeOfWin.height - sizeOfSpider.height * 0.5 - SCORE_HEIGHT);
CCAction *back = [CCMoveTo actionWithDuration:1 position:backPos];
[spider runAction:back];
//播放加分動畫,加分
[self showAnimateScore];
//每有一只蜘蛛被躲避開,就加快游戲速度,同時進行獲勝判定
numSpidersMoved++;
if (numSpidersMoved %5 == 0) {
//在本游戲中,如果速度快到0.7,認為玩家獲勝。
if (speed < 0.7) {
[self whenWin];
return;
}
speed -= 0.02;
[self changeCheckTimeout];
numSpidersMoved = 1;
}
}
//當用戶點擊屏幕的時候,根據不同的情景改變游戲狀態。
-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
//如果當前是死亡狀態,繼續游戲
if (gameStatus == @"DEAD") {
[panda stopAllActions];
[panda setVisible:YES];
[lblInfo setVisible:NO];
[self resetSpider];
gameStatus = @"PLAYING";
[self changeCheckTimeout];
[self startSchedule];
}
//如果當前是READY狀態,開始游戲
if (gameStatus == @"READY") {
gameStatus = @"PLAYING";
[self changeCheckTimeout];
[self startSchedule];
}
}
//開始游戲相關的計時器
-(void)startSchedule
{
//讓蜘蛛動起來
[self unschedule:@selector(playSpiderAnimate)];
[self schedule:@selector(playSpiderAnimate) interval:0.4];
//啟動碰撞檢測
[self unschedule:@selector(checkCollision)];
[self schedule:@selector(checkCollision) interval:0.02];
}
//停止游戲相關的計時器
-(void)stopSchedule
{
[self unschedule:@selector(playSpiderAnimate)];
[self unschedule:@selector(checkCollision)];
}
//碰撞檢測
-(void)checkCollision
{
//計算熊貓和蜘蛛的最大相距半徑,大于此值認為發生了碰撞。
float maxDistance = sizeOfSpider.width * 0.45 +sizeOfPanda.width * 0.45;
//依次判定每一個蜘蛛是否與熊貓發生了碰撞
for (int i = 0; i < spiderNumber; i++) {
CCSprite *spider;
spider = [spiders objectAtIndex:i];
//忽略沒有出動的蜘蛛
if ([spider numberOfRunningActions] == 0) {
continue;
}
//得到當前蜘蛛和熊貓的距離
float actualDistance = ccpDistance(spider.position, panda.position);
if (actualDistance < maxDistance) {
[self whenCollision];
break;
}
}
}
//當碰撞發生的時候,進行處理
-(void)whenCollision
{
//播放音頻
[[SimpleAudioEngine sharedEngine] playEffect:@"bomb.caf"];
[self unschedule:@selector(checkSpider:)];
[self stopSchedule];
[self stopAllAction];
gameStatus = @"DEAD";
//blink the spider
CCAction *blink = [CCBlink actionWithDuration:0.5 blinks:3];
[panda runAction:blink];
livesCount--;
[lblInfo setVisible:YES];
if (livesCount == 0) {
[lblInfo setString:@"GAME OVER!"];
gameStatus = @"OVER";
return;
}
[self showLives];
[lblInfo setString:@"你掛了!點擊屏幕重新來過!"];
}
-(void)showLives
{
for (int i = livesCount; i<MAXLIVES; i++) {
CCSprite *tmpSprite = [LivesPandas objectAtIndex:i];
[tmpSprite setVisible:NO];
}
}
//停止所有蜘蛛和主角的動作
-(void)stopAllAction
{
for (int i = 0; i < spiderNumber; i++) {
CCSprite *spider = [spiders objectAtIndex:i];
[spider stopAllActions];
}
[panda stopAllActions];
}
//該方法用在向panda精靈中傳遞游戲狀態,實現:只有在PLAYING的時候才可以移動主角。
-(NSString *)getGameStatus
{
return gameStatus;
}
@end
我想注釋已經足夠清楚了,有序考慮到了向iPad平臺的兼容,所以有大量的代碼用來計算尺寸和位置。千萬不要認為這是在浪費時間,記住一句話:
?
程序員應該盡量少寫基于假設的代碼
比如spider.positon = CGPointMake(160,32)。
你寫這行代碼的本意可能是想將熊貓精靈放在屏幕的底部的中間,聽起來似乎不錯,因為當前你做的是iphone的開發,熊貓的高度是64px。但是這都基于兩個假設:
假設一:屏幕寬度是320px,顯然并非所有的IOS設備都是這樣。
假設二:熊貓高度是64px。
事實上,我們很容易在游戲進行到一定的程度以后,要添加新的需求,比如移植到iPad上,比如說你想增加一個關卡,這次主角是一個螞蟻或者一只大象。那么這些基于假設的代碼就會成為讓你加班的原因。也很有可能會耽誤你和女兒的周末晚餐??
資源
本例中,用到了以下資源:
bomb.caf:主角死亡時候播放的音效。
sprite.plist & sprite.png:精靈貼圖列表,使用Zwoptex文件制作,這個工具使用起來非常簡單,大家可以google之。
myfont.fnt & myfont.png:自定義字體類表和圖像,使用hiero制作。游戲開發必備。
?
說得再多,不如自己動手寫一遍。
奉上源碼:cocos2d-蜘蛛人源碼
回見。
?
?
?
?
轉載于:https://www.cnblogs.com/pengyingh/articles/2393191.html
總結
以上是生活随笔為你收集整理的【吼吼睡cocos2d学习笔记】第四章 - 第一个游戏的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle 统计信息备份/表分析
- 下一篇: 1030利用三层交换机实现VLAN间通信