源代码:https://github.com/manguoge/game_Ranking
一、游戏设计简介
“打仙人掌”游戏是个简单的“打狗熊”类游戏。在手机画面的沙丘里,不断有仙人掌跳出来,玩家必须尽量快得去拍打跳出来的仙人掌,每拍打一个仙人掌得分加1,如果在限制的时间内没有把跳出来的仙人掌拍打回去,玩家的生命数将减1,生命数为0时游戏结束。随着玩家的分数的增加,游戏的难度会不断的增加,即跳出来的仙人掌的频率越来越快。
二、游戏规则设计
1.每拍打一个仙人掌分数加1;
2.每次游戏的玩家生命数是5,每没有拍打一个仙人掌生命数减1,至0游戏结束;
3.仙人掌的位置随机生成,其中水平位置可在屏幕任意位置,竖直位置为三种随机位置;
4.当分数到达30分时,玩家没拍打5株仙人掌,同时出现的仙人掌数加1;
5.游戏支持暂停、接着玩及退出功能。
三、游戏开发逻辑
1.默认采用横屏,游戏由两个控制器页面组成,采用导航控制器层级结构,点击首页play按钮进入游戏页面;
2.游戏状态分为正在游戏,暂停游戏和结束游戏三种,初始化游戏的相关参数;
- (void)viewDidLoad
{
//初始化基本参数
gameOver=NO;
pause=NO;
life=5;
score=0;
[super viewDidLoad];
[self.pauseBtn setImage:[UIImage imageNamed:@"PausePressed"] forState:UIControlStateHighlighted];
UILabel* tipLabel=[[UILabel alloc] initWithFrame:CGRectMake((SCREENWIDTH-300)*0.5, (SCREENHEIGHT-100)*0.5, 300, 100)];
//进入游戏,提示游戏将开始
tipLabel.text=@"Game Will Start After 3s!";
[tipLabel setFont:[UIFont systemFontOfSize:20]];
[tipLabel setTextAlignment:NSTextAlignmentCenter];
tipLabel.layer.borderWidth=5;
tipLabel.layer.cornerRadius=15;
tipLabel.layer.masksToBounds=YES;
tipLabel.alpha=1;
tipLabel.backgroundColor=[UIColor redColor];
[self.view addSubview:tipLabel];
[UIView animateWithDuration:3 animations:^
{
tipLabel.alpha=0;
tipLabel.backgroundColor=[UIColor grayColor];
} completion:^(BOOL finished)
{
[tipLabel removeFromSuperview];
//初始化两个仙人掌
[self spawnCactus];
[self performSelector:@selector(spawnCactus) withObject:nil afterDelay:2.0];
}];
}
2.随机生成仙人掌,x轴位置随机,Y轴位置有三种情况,仙人掌的大小有三种随机大小;
-(void)spawnCactus
{
if (gameOver)
{
return;
}
if (pause)
{
//暂停状态时,每隔1秒检查一次状态,若变为非暂停状态时,继续生成一个仙人掌
[self performSelector:@selector(spawnCactus) withObject:nil afterDelay:1];
return;
}
//根据随机生成数字0、1或者2确定生成的不同大小的仙人掌图片
int cactusSize=arc4random()%3;
UIImage* cactusImage=nil;
switch (cactusSize)
{
case 0:
cactusImage=[UIImage imageNamed:@"CactusLarge"];
break;
case 1:
cactusImage=[UIImage imageNamed:@"CactusMed"];
break;
case 2:
cactusImage=[UIImage imageNamed:@"CactusSmall"];
break;
default:
break;
}
//随机生成仙人掌的X、Y轴坐标
int horizontalLocationX=arc4random()%(int)SCREENWIDTH;
int VerticalLocation=arc4random()%3;
//由于随机生成的水平位置的最长部分是屏幕边缘,所以应该将其水平位置向内移动仙人掌宽度的大小,、避免超出屏幕
float cactusImageWidth=cactusImage.size.width;
float cactusImageHeight=cactusImage.size.height;
if (horizontalLocationX+cactusImageWidth>SCREENWIDTH)
{
horizontalLocationX=SCREENWIDTH-cactusImageWidth;
}
UIImageView* duneToSpawnBehind=nil;
switch (VerticalLocation)
{
case 0:
duneToSpawnBehind=dune1;
break;
case 1:
duneToSpawnBehind=dune2;
break;
case 2:
duneToSpawnBehind=dune3;
break;
default:
break;
}
int verticalLocationY=duneToSpawnBehind.frame.origin.y;
UIButton* cactusBtn=[[UIButton alloc] initWithFrame:CGRectMake(horizontalLocationX, verticalLocationY, cactusImageWidth, cactusImageHeight)];
[cactusBtn setImage:cactusImage forState:UIControlStateNormal];
[cactusBtn addTarget:self action:@selector(cactusHit:) forControlEvents:UIControlEventTouchUpInside];
[self.view insertSubview:cactusBtn belowSubview:duneToSpawnBehind];
//生成的仙人掌添加到沙丘的后面之后,就可以运用动画将其跳出来显示
[UIView beginAnimations:@"slideCactus" context:nil];
[UIView setAnimationDuration:0.2];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
cactusBtn.frame=CGRectMake(horizontalLocationX, verticalLocationY-cactusImageHeight*0.5, cactusImageWidth, cactusImageHeight);
[UIView commitAnimations];
[self performSelector:@selector(cactusMissed:) withObject:cactusBtn afterDelay:2.0];
}
3.玩家与仙人掌的交互,仙人掌出来之后两秒内可以被玩家点击,玩家的分数加1,如果两秒内没有被点击,则玩家的生命数减1,玩家生命总共5条,耗完则游戏结束;
-(void)cactusHit:(UIButton*)cactusBtn
{
[UIView animateWithDuration:0.1 animations:^
{
cactusBtn.alpha=0;
} completion:^(BOOL finished)
{
[cactusBtn removeFromSuperview];
}];
score++;
[self updateScore];
[self performSelector:@selector(spawnCactus) withObject:nil afterDelay:arc4random()%3+0.2];
}
-(void)cactusMissed:(UIButton*)cactusBtn
{
CGRect frame=cactusBtn.frame;
frame.origin.y+=cactusBtn.frame.size.height;
[UIView animateWithDuration:0.1 delay:0.0 options:UIViewAnimationOptionCurveLinear|UIViewAnimationOptionBeginFromCurrentState animations:^
{
cactusBtn.frame=frame;
} completion:^(BOOL finished)
{
[cactusBtn removeFromSuperview];
[self performSelector:@selector(spawnCactus) withObject:nil afterDelay:arc4random()%3+0.5];
}];
life--;
[self updateLife];
}
- (IBAction)pause:(id)pauseBtn
{
pause=YES;
UIAlertView* alert=[[UIAlertView alloc] initWithTitle:@"Pause Now" message:nil delegate:self cancelButtonTitle:@"Continue" otherButtonTitles:@"Quit", nil];
alert.tag=kPauseAlert;
[alert show];
}
4.玩家得分与生命数的更新;
-(void)updateLife
{
UIImage* lifeImage=[UIImage imageNamed:@"heart"];
for (UIView* view in [self.view subviews])
{
if (view.tag==kLifeImageViewTag)
{
[view removeFromSuperview];
}
}
for (int i=0; i<life; i++)
{
UIImageView* lifeImageView=[[UIImageView alloc] initWithImage:lifeImage];
CGRect frame=lifeImageView.frame;
frame.origin.x=SCREENWIDTH-(i+1)*30;
frame.origin.y=20;
lifeImageView.frame=frame;
lifeImageView.tag=kLifeImageViewTag;
[self.view addSubview:lifeImageView];
}
if (life==0)
{
gameOver=YES;
UIAlertView* alert=[[UIAlertView alloc] initWithTitle:@"Game Over!" message:[NSString stringWithFormat:@"You Total Score are %d points",score] delegate:self cancelButtonTitle:@"Dismiss" otherButtonTitles:nil, nil];
alert.tag=kGameOver;
[alert show];
}
}
-(void)updateScore
{
//当得分超过30并且5的倍数时,都将再生成一株仙人掌,从而增加游戏难度
if (score>=30&&score%5==0)
{
[self spawnCactus];
}
self.scoreLabel.text=[NSString stringWithFormat:@"Score:%d",score];
}
-(void)cactusMissed:(UIButton*)cactusBtn
{
CGRect frame=cactusBtn.frame;
frame.origin.y+=cactusBtn.frame.size.height;
[UIView animateWithDuration:0.1 delay:0.0 options:UIViewAnimationOptionCurveLinear|UIViewAnimationOptionBeginFromCurrentState animations:^
{
cactusBtn.frame=frame;
} completion:^(BOOL finished)
{
[cactusBtn removeFromSuperview];
[self performSelector:@selector(spawnCactus) withObject:nil afterDelay:arc4random()%3+0.5];
}];
life--;
[self updateLife];
}
5.在游戏期间可以暂停游戏,选择继续或者退出;
- (IBAction)pause:(id)pauseBtn
{
pause=YES;
UIAlertView* alert=[[UIAlertView alloc] initWithTitle:@"Pause Now" message:nil delegate:self cancelButtonTitle:@"Continue" otherButtonTitles:@"Quit", nil];
alert.tag=kPauseAlert;
[alert show];
}
#pragma --mark UIAlertViewDelegate
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (alertView.tag==kPauseAlert)
{
if (buttonIndex==0)
{
pause=NO;
}
else
{
[self.navigationController popViewControllerAnimated:YES];
}
}
else if (alertView.tag==kGameOver)
{
[self.navigationController popViewControllerAnimated:YES];
}
}