天天看點

flappybird android源碼,iOS學習之flappyBird遊戲的實作

導言

在本人還是學生的時候,flappyBird這款遊戲非常火爆,最後等到Android版的出來之後,也是很癡迷的玩了一把。可是,本人遊戲天賦一直平平,幾度玩得想摔手機。本文主要介紹如何開發iOS平台的flappyBird,遊戲中使用了原本軟體的圖檔資源,僅作學習交流使用。本人實作的flappyBird遊戲包含遊戲等級設定,排行榜,音效等功能。

技術點

flappyBird是單機遊戲,主要涉及界面邏輯、圖檔資源、遊戲動畫、得分排行。

為了實作這幾個功能,需要使用以下幾個技術架構:

1)AVFoundation

2)歸檔

3)模态視圖

4)NSTimer

5)視圖控件,包括UIImageView、UILabel、UITableView等

實作過程

1、建立工程

1)打開Xcode,點選建立工程,選擇Single View Application模闆

flappybird android源碼,iOS學習之flappyBird遊戲的實作

2)填寫工程資訊

flappybird android源碼,iOS學習之flappyBird遊戲的實作

2、移除Main.storyboard檔案

flappybird android源碼,iOS學習之flappyBird遊戲的實作

上圖是flappyBird的檔案目錄,因為Xcode6使用模闆建立工程時會自動生成Main.storyboard檔案,而工程中本人使用代碼布局,是以可以移除Main.storyboard檔案。具體操作方法可以參看本人另一篇文章:

《iOS學習之移除Main.storyboard》

3、遊戲界面布局

整體效果圖如下

flappybird android源碼,iOS學習之flappyBird遊戲的實作

效果圖.gif

需要說明的是,Game Over這個界面,首先需要隐藏或者等到遊戲結束才建立。本人是選擇在遊戲判定結束時才建立并顯示。

4、遊戲運作

這款遊戲的兩個關鍵點:

1)使用定時器驅動遊戲界面運作,即遊戲界面中的柱子高低變化與柱子的消失與産生。

2)遊戲結束的判定,這裡涉及兩個問題,一是碰撞檢測,二是計分統計。

具體實作部分代碼

1、計分統計

-(void)columnLabelClick {

if (topPipeFrame.origin.x == (100 + 30 - 70)) {

columnNumber++;

columnLabel.text = [NSString stringWithFormat:@"%zi",columnNumber];

}

}

2、繪制柱子

-(void)pipe {

//通道高度

NSInteger tunnelHeight = 0;

//根據遊戲難度設定通道高度

if([[DataTool stringForKey:kRateKey] isEqualToString:@"ordinary"]) {

tunnelHeight = 100;

}else if([[DataTool stringForKey:kRateKey] isEqualToString:@"general"]) {

tunnelHeight = 90;

}else if([[DataTool stringForKey:kRateKey] isEqualToString:@"difficult"]) {

tunnelHeight = 80;

}else if([[DataTool stringForKey:kRateKey] isEqualToString:@"hard"]) {

tunnelHeight = 75;

} else if([[DataTool stringForKey:kRateKey] isEqualToString:@"crazy"]) {

tunnelHeight = 70;

}

//柱子圖像

NSInteger tall = arc4random() % 200 + 40;

topPipe = [[UIImageView alloc]initWithFrame:CGRectMake(320, -20, 70, tall)];

topPipe.image = [UIImage imageNamed:@"pipe"];

[self.view addSubview:topPipe];

bottomPipe = [[UIImageView alloc]initWithFrame:CGRectMake(320, tall + tunnelHeight, 70, 400)];

bottomPipe.image = [UIImage imageNamed:@"pipe"];

[self.view addSubview:bottomPipe];

//把底部圖檔視圖放在柱子視圖上面

[self.view insertSubview:roadView aboveSubview:bottomPipe];

}

3、使用定時器,驅動遊戲界面運作,并進行碰撞檢測

//添加定時器

timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(onTimer) userInfo:nil repeats:YES];

//定時器操作

-(void)onTimer {

//底部動畫移動

CGRect frame = roadView.frame;

if (frame.origin.x == -15) {

frame.origin.x = 0;

}

frame.origin.x--;

roadView.frame = frame;

//上升

if (isTap == NO) {

CGRect frame = birdsView.frame;

frame.origin.y -= 3;

number += 3;

birdsView.frame = frame;

if (number >= 60) {

isTap = YES;

}

}

//下降

if(isTap == YES && birdsView.frame.origin.y < 370){

CGRect frame = birdsView.frame;

frame.origin.y++;

number -= 2;

birdsView.frame = frame;

number = 0;

}

//柱子移動

topPipeFrame = topPipe.frame;

CGRect bottomPipeFrame = bottomPipe.frame;

topPipeFrame.origin.x--;

bottomPipeFrame.origin.x--;

topPipe.frame = topPipeFrame;

bottomPipe.frame = bottomPipeFrame;

if (topPipeFrame.origin.x < -70) {

[self pipe];

}

//碰撞檢測(交集)

bool topRet = CGRectIntersectsRect(birdsView.frame, topPipe.frame);

bool bottomRet = CGRectIntersectsRect(birdsView.frame, bottomPipe.frame);

if (topRet == true || bottomRet == true) {

[self.soundTool playSoundByFileName:@"punch"];

[self onStop];

}

if (topPipeFrame.origin.x == (100 + 30 - 70)) {

[self.soundTool playSoundByFileName:@"pipe"];

[self columnLabelClick];

}

}

4、更新分數,更新最佳分數與排行榜分數,并使用歸檔将資料持久化

-(void)updateScore {

//更新最佳成績

if (columnNumber > [DataTool integerForKey:kBestScoreKey]) {

[DataTool setInteger:columnNumber forKey:kBestScoreKey];

}

//更新本局分數

[DataTool setInteger:columnNumber forKey:kCurrentScoreKey];

//更新排行榜

NSArray *ranks = (NSArray *)[DataTool objectForKey:kRankKey];

NSMutableArray *newRanksM = [NSMutableArray array];

NSInteger count = ranks.count;

BOOL isUpdate = NO;

for (NSInteger i = 0; i < count; i++) {

NSString *scoreStr = ranks[i];

NSInteger score = [scoreStr integerValue];

if (score < columnNumber && isUpdate == NO) {

scoreStr = [NSString stringWithFormat:@"%zi", columnNumber];

[newRanksM addObject:scoreStr];

isUpdate = YES;

i--;

} else {

scoreStr = [NSString stringWithFormat:@"%zi", score];

[newRanksM addObject:scoreStr];

}

}

if (newRanksM.count > count) {

[newRanksM removeLastObject];

}

[DataTool setObject:newRanksM forKey:kRankKey];

}

5、繪制GameOver提示顯示

-(void)pullGameOver {

//遊戲結束操作界面

gameOver = [[GameOverView alloc] initWithFrame:CGRectMake(20, 160, 280, 300)];

gameOver.delegate = self;

[self.view addSubview:gameOver];

}

6、遊戲停止操作

-(void)onStop {

//更新分數

[self updateScore];

//停止定時器

[timer setFireDate:[NSDate distantFuture]];

//彈出遊戲結束操作界面

[self pullGameOver];

}

小結

這款遊戲的實作還是很簡單的,主要使用UIImageView自帶的動畫實作方式,即可實作bird的動畫效果。使用NSTimer即可實作遊戲場景的柱子移動,至于柱子的高度,則可以使用随機數方式在一定範圍内實作高低變化。最後可以使用CGRectIntersectsRect來實作邊界碰撞檢測來判定遊戲是否結束。

以上是本人開發iOS版flappyBird的簡要過程介紹,其中隻包含了關鍵點的代碼實作,具體完整遊戲源代碼位址:https://github.com/CharsDavy/flappyBird