• Flappy Bird 源码走读


    参考:https://github.com/kirualex/SprityBird

    该项目基于spritekit,代码的结构很清楚,感觉用来学习spritekit非常不错。

    1、项目只有一个viewController,包含:

    @property (weak,nonatomic) IBOutlet SKView * gameView;
    @property (weak,nonatomic) IBOutlet UIView * getReadyView;
    
    @property (weak,nonatomic) IBOutlet UIView * gameOverView;
    @property (weak,nonatomic) IBOutlet UIImageView * medalImageView;
    @property (weak,nonatomic) IBOutlet UILabel * currentScore;
    @property (weak,nonatomic) IBOutlet UILabel * bestScoreLabel;

    初始时gameOverView均不可见。

    2、在viewController的viewDidLoad中加载场景:

    [self.gameView presentScene:scene];

    3、这里做的比较好的是,利用协议完成viewController和Scene的交互,viewController处理游戏中反馈的事件,实现对上述游戏完成、游戏开始等顶层view的操作。

    @protocol SceneDelegate <NSObject>
    - (void) eventStart;
    - (void) eventPlay;
    - (void) eventWasted;
    @end

    4、在Scene的初始化中对场景中的障碍和鸟进行绘制:

    - (void) startGame
    {
        // Reinit
        wasted = NO;
        
        [self removeAllChildren];
        
        [self createBackground];
        [self createFloor];
        [self createScore];
        [self createObstacles];
        [self createBird];
        
        // Floor needs to be in front of tubes
        floor.zPosition = bird.zPosition + 1;
        
        if([self.delegate respondsToSelector:@selector(eventStart)]){
            [self.delegate eventStart];
        }
    }

    5、在项目里,只定义了两类node,一个是用来表述移动背景如地板、障碍、背景图等,另外一个就是绘制小鸟;

    这里初始化的node对象包括鸟、障碍都会被保存在全局数据组里,在后续刷新。以障碍物的移动为例:

    - (void) updateObstacles:(NSTimeInterval)currentTime
    {
        if(!bird.physicsBody){
            return;
        }
        
        for(int i=0;i<nbObstacles;i++){
            
            // Get pipes bby pairs
            SKSpriteNode * topPipe = (SKSpriteNode *) topPipes[i];
            SKSpriteNode * bottomPipe = (SKSpriteNode *) bottomPipes[i];
            
            // Check if pair has exited screen, and place them upfront again
            if (X(topPipe) < -WIDTH(topPipe)){
                SKSpriteNode * mostRightPipe = (SKSpriteNode *) topPipes[(i+(nbObstacles-1))%nbObstacles];
                [self place:bottomPipe and:topPipe atX:X(mostRightPipe)+WIDTH(topPipe)+OBSTACLE_INTERVAL_SPACE];
            }
            
            // Move according to the scrolling speed
            topPipe.position = CGPointMake(X(topPipe) - FLOOR_SCROLLING_SPEED, Y(topPipe));
            bottomPipe.position = CGPointMake(X(bottomPipe) - FLOOR_SCROLLING_SPEED, Y(bottomPipe));
        }
    }

    6、在scene中主要继承处理两个方法:

    //该函数被Scene重绘每一帧调用
    - (void)update:(NSTimeInterval)currentTime
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    7、通过sprite的物理引擎实现碰撞操作:

      bottomPipe.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectMake(0,0, WIDTH(bottomPipe) , HEIGHT(bottomPipe))]

    topPipe.physicsBody.categoryBitMask = blockBitMask;
    topPipe.physicsBody.contactTestBitMask = birdBitMask;
    - (void)didBeginContact:(SKPhysicsContact *)contact
    {
        if(wasted){ return; }
    
        wasted = true;
        [Score registerScore:self.score];
        
        if([self.delegate respondsToSelector:@selector(eventWasted)]){
            [self.delegate eventWasted];
        }
    }
  • 相关阅读:
    eclipse中切换jdk版本
    201704 创建财务凭证函数
    201704 F-47创建预付款申请a
    201704 F-02创建财务凭证
    20170413 F110学习
    20170411 F110初始界面-建议清单
    20170411 供应商保证金维护视图
    20170411 F-02创建财务凭证
    ABAP 断点篇-001
    20170411 debug窗口执行文件
  • 原文地址:https://www.cnblogs.com/Fredric-2013/p/5442063.html
Copyright © 2020-2023  润新知