Flappy bird 小游戏的实现

//3.0初速度需要60秒减少至0
const float MaxTime = 50;
//加速度,方向向下
const float VG = 0.05;
//初速度
const float MaxV = 2.5;

//初始化总路程
const float AllLength = 692;

typedef enum {

    GameNoStart,
    GamePlaying,
    GameOver

} GameState;

@interface BirdFlyViewController ()
{
    NSTimer *birdTimer;
    //开始游戏开关
    BOOL isStart;
    //游戏状态
    GameState gameState;

    //总场景
    UIView *playLayer;

    //小鸟
    UIImageView *birdImgView;
    //小鸟的壳
    UIView *birdClotherView;

    //跳跃时间
    float maxJumpTime;

    //滚动的背景
    UIView *bgView1;
    UIView *bgView2;

    //管道
    UIView *pileImgView11;
    UIView *pileImgView12;
    UIView *pileImgView21;
    UIView *pileImgView22;

    //得分
    UILabel *scoreLabel;
    NSInteger score;
}

@end

@implementation BirdFlyViewController

- (void)dealloc
{
    [birdTimer invalidate];
    playLayer = nil;
    pileImgView11 = nil;
    pileImgView12 = nil;
    pileImgView21 = nil;
    pileImgView22 = nil;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self initBirdAndOther];

    birdTimer = [NSTimer scheduledTimerWithTimeInterval:0.008
                                                 target:self
                                               selector:@selector(update)
                                               userInfo:nil
                                                repeats:YES];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark -
#pragma mark - 横竖屏幕
//只支持portait,不能旋转:
-(BOOL)shouldAutorotate
{
    return NO;
}

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

#pragma mark -
#pragma mark - 频率刷新
- (void) update
{
    //判断
    if (isStart == YES && gameState == GamePlaying)
    {
        [self updateBird];
        [self updateBg];
        [self setPiles];
        [self checkBirdRect];
    }
}

#pragma mark -
#pragma mark - 初始化
- (void) initBirdAndOther
{
    //初始化总场景
    playLayer = [[UIView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:playLayer];
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(screenTap)];
    [self.view addGestureRecognizer:tapGesture];

    //初始化障碍物
    bgView1 = [[UIView alloc] initWithFrame:self.view.bounds];
    bgView2 = [[UIView alloc] initWithFrame:CGRectMake(320, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
    [playLayer addSubview:bgView1];
    [playLayer addSubview:bgView2];

    //中间的管道
    pileImgView11 = [self addPilesAtX:0];
    [bgView1 addSubview:pileImgView11];
    pileImgView11.hidden = YES;
    pileImgView21 = [self addPilesAtX:0];
    [bgView2 addSubview:pileImgView21];

    pileImgView12 = [self addPilesAtX:160];
    [bgView1 addSubview:pileImgView12];
    pileImgView12.hidden = YES;
    pileImgView22 = [self addPilesAtX:160];
    [bgView2 addSubview:pileImgView22];

    //底部草
    UIImageView *buttomImg1 = [[UIImageView alloc] initWithFrame:CGRectMake(0, [[UIScreen mainScreen] bounds].size.height - 53, 320, 53)];
    buttomImg1.image = [UIImage imageNamed:@"ground"];
    [bgView1 addSubview:buttomImg1];
    UIImageView *buttomImg2 = [[UIImageView alloc] initWithFrame:CGRectMake(0, [[UIScreen mainScreen] bounds].size.height - 53, 320, 53)];
    buttomImg2.image = [UIImage imageNamed:@"ground"];
    [bgView2 addSubview:buttomImg2];

    //小鸟的衣服
    birdClotherView = [[UIView alloc] initWithFrame:CGRectMake(60, [[UIScreen mainScreen] bounds].size.height/2 + 80, 40, 30)];
    [playLayer addSubview:birdClotherView];

    //初始化小鸟
    birdImgView = [[UIImageView alloc] init];
    birdImgView.frame = CGRectMake(0, 0, 40, 28);
    birdImgView.image = [UIImage imageNamed:@"bird"];
    [birdClotherView addSubview:birdImgView];

    //得分
    scoreLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 40, 300, 30)];
    scoreLabel.textAlignment = NSTextAlignmentRight;
    [playLayer addSubview:scoreLabel];
    scoreLabel.text = @"score: 0";
}

#pragma mark -
#pragma mark - 点击屏幕开始和跳跃
- (void) screenTap
{
    //没点击一次
    maxJumpTime = MaxTime;

    if (isStart == NO)
    {
        isStart = YES;
        gameState = GamePlaying;

        for (UIView *tmpView in self.view.subviews)
        {
            [tmpView removeFromSuperview];
        }

        [self initBirdAndOther];
    }

    //仰角30度旋转
    CGAffineTransform transform = CGAffineTransformIdentity;
    birdImgView.transform = CGAffineTransformRotate(transform,  -30 * M_PI / 180 );
}

#pragma mark -
#pragma mark - 设置管道
- (void) setPiles
{
    NSInteger tmpY = rand()%120;

    if (bgView1.frame.origin.x == -53)
    {
        //设置第一个管道
        CGRect rect = pileImgView11.frame;
        rect.origin.y = tmpY - 120;
        pileImgView11.frame = rect;
        if (pileImgView11.hidden == YES)
        {
            pileImgView11.hidden = NO;
        }
    }
    else if (bgView1.frame.origin.x == -213)
    {
        //设置第二个管道
        CGRect rect = pileImgView12.frame;
        rect.origin.y = tmpY - 120;
        pileImgView12.frame = rect;
        if (pileImgView12.hidden == YES)
        {
            pileImgView12.hidden = NO;
        }
    }
    else if (bgView2.frame.origin.x == -53)
    {
        //设置第三个管道
        CGRect rect = pileImgView21.frame;
        rect.origin.y = tmpY - 120;
        pileImgView21.frame = rect;
    }
    else if (bgView2.frame.origin.x == -213)
    {
        //设置第四个管道
        CGRect rect = pileImgView22.frame;
        rect.origin.y = tmpY - 120;
        pileImgView22.frame = rect;
    }
}

#pragma mark -
#pragma mark - 碰撞检测
- (void) checkBirdRect
{
    //碰撞检测
    float birdRightX = birdClotherView.frame.origin.x + 34;
    float birdButtomY = birdClotherView.frame.origin.y + 24;
    float birdUpY = birdClotherView.frame.origin.y;

    //计算障碍物
    //下面的柱子和上面的柱子检测
    if ((birdRightX - 0 == bgView1.frame.origin.x && birdUpY >= 319 + (pileImgView11.frame.origin.y + 120)))
    {
        if (pileImgView11.hidden == NO)
        {
            [self gameOver];
        }
    }
    else  if(birdRightX - 0 == bgView1.frame.origin.x && birdButtomY <= 199 + (pileImgView11.frame.origin.y + 120))
    {
        if (pileImgView11.hidden == NO)
        {
            [self gameOver];
        }
    }

    if ((birdRightX - 160 == bgView1.frame.origin.x && birdUpY >= 319 + (pileImgView12.frame.origin.y + 120)))
    {
        if (pileImgView12.hidden == NO)
        {
            [self gameOver];
        }
    }
    else  if(birdRightX - 160 == bgView1.frame.origin.x && birdButtomY <= 199 + (pileImgView12.frame.origin.y + 120))
    {
        if (pileImgView12.hidden == NO)
        {
            [self gameOver];
        }
    }

    if ((birdRightX - 0 == bgView2.frame.origin.x && birdUpY >= 319 + (pileImgView21.frame.origin.y + 120)))
    {
        [self gameOver];
    }
    else  if(birdRightX - 0 == bgView2.frame.origin.x && birdButtomY <= 199 + (pileImgView21.frame.origin.y + 120))
    {
        [self gameOver];
    }

    if ((birdRightX - 160 == bgView2.frame.origin.x && birdUpY >= 319 + (pileImgView22.frame.origin.y + 120)))
    {
        [self gameOver];
    }
    else  if(birdRightX - 160 == bgView2.frame.origin.x && birdButtomY <= 199 + (pileImgView22.frame.origin.y + 120))
    {
        [self gameOver];
    }

    //上下柱子横截面检测
    if (birdRightX - 0 > bgView1.frame.origin.x && bgView1.frame.origin.x >= birdRightX - 0 - 52 - 34 && (birdUpY <= 199 + (pileImgView11.frame.origin.y + 120) || birdButtomY >= 319 + (pileImgView11.frame.origin.y + 120)))
    {
        if (pileImgView11.hidden == NO)
        {
            [self gameOver];
        }
    }

    if (birdRightX - 160 > bgView1.frame.origin.x && bgView1.frame.origin.x >= birdRightX - 160 - 52 - 34 && (birdUpY <= 199 + (pileImgView12.frame.origin.y + 120) || birdButtomY >= 319 + (pileImgView12.frame.origin.y + 120)))
    {
        if (pileImgView12.hidden == NO)
        {
            [self gameOver];
        }
    }

    if (birdRightX - 0 > bgView2.frame.origin.x && bgView2.frame.origin.x >= birdRightX - 0 - 52 - 34 && (birdUpY <= 199 + (pileImgView21.frame.origin.y + 120) || birdButtomY >= 319 + (pileImgView21.frame.origin.y + 120)))
    {
        if (pileImgView12.hidden == NO)
        {
            [self gameOver];
        }
    }

    if (birdRightX - 160 > bgView2.frame.origin.x && bgView2.frame.origin.x >= birdRightX - 160 - 52 - 34 && (birdUpY <= 199 + (pileImgView22.frame.origin.y + 120) || birdButtomY >= 319 + (pileImgView22.frame.origin.y + 120)))
    {
        [self gameOver];
    }

    //判断地平线
    if (birdButtomY >= [[UIScreen mainScreen] bounds].size.height - 53)
    {
        [self gameOver];
    }
}

#pragma mark -
#pragma mark - 碰撞处理
- (void) gameOver
{
    isStart = NO;
    gameState = GameOver;
    score = 0;
}

#pragma mark -
#pragma mark - 更新小鸟的坐标位置
- (void) updateBird
{
    maxJumpTime --;
    CGRect rect = birdClotherView.frame;
    if (maxJumpTime >= 0)
    {
        rect.origin.y = rect.origin.y - (MaxV - (MaxTime - maxJumpTime)*VG);
    }
    else
    {
        //俯角30度旋转
        CGAffineTransform transform = CGAffineTransformIdentity;
        birdImgView.transform = CGAffineTransformRotate(transform,  30 * M_PI / 180 );
        rect.origin.y = rect.origin.y - (maxJumpTime*VG);
    }
    birdClotherView.frame = rect;
}

- (void) updateBg
{
    CGRect rect1 = bgView1.frame;
    CGRect rect2 = bgView2.frame;

    if (rect1.origin.x <= -320)
    {
        rect1.origin.x = 320;
    }

    if (rect2.origin.x <= -320)
    {
        rect2.origin.x = 320;
    }

    rect1.origin.x = rect1.origin.x - 1;
    rect2.origin.x = rect2.origin.x - 1;

    bgView1.frame = rect1;
    bgView2.frame = rect2;

    if (rect1.origin.x == 0 || rect1.origin.x == -160 || rect2.origin.x == 0 || rect2.origin.x == -160)
    {
        if (pileImgView11.hidden == YES || pileImgView12.hidden == YES)
        {
            return;
        }

        score += 1;
        scoreLabel.text = [NSString stringWithFormat:@"score: %ld",(long)score];
    }
}

#pragma mark -
#pragma mark - 产生障碍物
- (UIView *) addPilesAtX:(float) originX
{
    NSInteger tmpY = rand()%120;
    //0位置和160的未知 山下间隔120px
    UIView *pileView = [[UIView alloc] initWithFrame:CGRectMake(originX, tmpY - 120, 52, 758)];

    UIImageView *pileImg1 = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 52, 319)];
    pileImg1.image = [UIImage imageNamed:@"up_bar"];
    [pileView addSubview:pileImg1];
    UIImageView *pileImg2 = [[UIImageView alloc] initWithFrame:CGRectMake(0, 439, 52, 319)];
    pileImg2.image = [UIImage imageNamed:@"down_bar"];
    [pileView addSubview:pileImg2];

    return pileView;

}

通过以上代码,就能实现一个小游戏了.

时间: 2024-10-05 21:48:25

Flappy bird 小游戏的实现的相关文章

flappy pig小游戏源码分析(2)——解剖option

今天继续分析flappy bird的源码.重温一下源码的目录结构. 在本系列第一篇中我们分析了game.js文件,也就是整个程序的架构.这一篇我们来看看option.js文件,这个文件的内容很简单,主要是配置一些游戏中各类元素的参数. 我们还是按照惯例先上源代码: var flappy = (function (self) { 'use strict'; //设置 self.option = { //重力加速度,屏幕像素和实际物理上的米有差别,所以存在换算 g: 400, //跳跃的初速度,控制

flappy pig小游戏源码分析(4)——核心pig模块(未完待续)

热身之后,我们要动点真格的了,游戏叫flappy pig,我们的pig终于要出场了. 老规矩,看看目录结构,读者对着目录结构好好回想我们已经讲解的几个模块: 其中game.js是游戏主程序,option.js是游戏配置文件,util是我们的通用工具库函数. 那么pig是什么呢,我们先上源码: var flappy = (function (self) { 'use strict';//开启严格模式 var option = self.option,//把前面添加好的option拿出来 $ = s

Flappy bird需求规格说明书

1.引言     1.1.编写目的 该需求分析为说明书通过对<flappy bird>游戏软件的客户需求分析,明确了所要开发的游戏软件的功能以及界面等的处理,从而使小组成员更清楚的了解用户的需求,在此基础上完成后续的设计及编程工作.      1.2.开发背景 <flappy bird>是之前爆红的一款手游,此款游戏虽然形式简易难度却极高,不仅挑战手指的灵活度,而且锻炼玩家的心理素质,因此受到了许多玩家的青睐,曾经在短时间内占据了80%欧美手机用户.基于此,我们开发了pc版的<

飞翔的圆(Flappy Bird)游戏源码完整版

这个源码是一个不错的休闲类的游戏源码,飞翔的圆(Flappy Bird)游戏源码V1.0,本项目是一个仿Flappy Bird的小游戏,只不过是把Flappy Bird里面的鸟替换成了简单的圆.感兴趣的朋友可以研究一下.本项目默认编码GBK. 源码下载:http://code.662p.com/view/9013.html public class LoadingActivity extends Activity { @Override public void onCreate(Bundle s

自己动手写游戏:Flappy Bird

START:最近闲来无事,看了看一下<C#开发Flappy Bird游戏>的教程,自己也试着做了一下,实现了一个超级简单版(十分简陋)的Flappy Bird,使用的语言是C#,技术采用了快速简单的WindowsForm,图像上主要是采用了GDI+,游戏对象的创建控制上使用了单例模式,现在我就来简单地总结一下. 一.关于Flappy Bird <Flappy Bird>是由来自越南的独立游戏开发者Dong Nguyen所开发的作品,游戏中玩家必须控制一只小鸟,跨越由各种不同长度水管

C语言版flappy bird黑白框游戏

在此记录下本人在大一暑假,2014.6~8这段时间复习C语言,随手编的一个模仿之前很火热的小游戏----flappy bird.代码bug基本被我找光了,如果有哪位兄弟找到其他的就帮我留言下吧,谢谢了! 代码的完美度肯定是不够的,随手编的嘛,找完bug后就没再去想怎样优化它了,毕竟时间有限. 先说下它的设计思路吧,算法方面,基本是纯靠for if 语句加上纯粹的坐标x,y运算实现的,在下面的代码里,将会看到很多阿拉伯数字的加加减减.没有用到链表什么的,当然,我相信,如果用到链表的话,会更简单,代

用Phaser来制作一个html5游戏——flappy bird (一)

Phaser是一个简单易用且功能强大的html5游戏框架,利用它可以很轻松的开发出一个html5游戏.在这篇文章中我就教大家如何用Phaser来制作一个前段时间很火爆的游戏:Flappy Bird,希望大家看后也能做出自己的html5游戏.大家可以先点击这里来试玩一下我已经做好的这个游戏,感受一下Phaser的游戏效果,游戏的完整代码我已经放到github上了.支持的浏览器:IE9+.Firefox.Chrome.Opera.Safari以及移动端的能支持html5的浏览器,推荐使用谷歌浏览器,

cocos2dx-html5 实现网页版flappy bird游戏

我也是第一次使用cocos2d_html5,对js和html5也不熟,看引擎自带的例子和引擎源码,边学边做,如果使用过cocos2d-x的话,完成这个游戏还是十分简单的.游戏体验地址: http://zhoujianghai.github.io/games/flappybird/ 1. 首先去cocos2d-x官网下载Cocos2d-html5-v2.2.2(目前最新版本)压缩包 2. 下载安装WampServer(http://www.wampserver.com/en/),后期在浏览器运行程

用Phaser实现Flappy Bird 游戏

How to Make a Flappy Bird in HTML5 With Phaser - Part 1 Flappy Bird is a nice little game with easy to understand mechanics, and I thought it would be a perfect fit for an HTML5 game tutorial for beginners. We are going to make a simplified version o