美文网首页程序员iOS Developer游戏开发
iOS开发实战-基于SpriteKit的FlappyBird小游

iOS开发实战-基于SpriteKit的FlappyBird小游

作者: gwk_iOS | 来源:发表于2017-07-27 21:50 被阅读355次

    写在前面

    最近一直在忙自己的维P恩的事情
    公司项目也是一团乱
    于是...随手找了个游戏项目改了改就上线了,就当充数了.

    SpriteKit简介

    SpriteKit是iOS 7之后苹果推出的2D游戏框架。它支持2D游戏中各种功能,如物理引擎,地图编辑,粒子,视频,声音精灵化,光照等。

    SpriteKit中常用的类

    • SKSpriteNode 用于绘制精灵纹理
    • SKVideoNode 用于播放视频
    • SKLabelNode 用于渲染文本
    • SKShapeNode 用于渲染基于Core Graphics路径的形状
    • SKEmitterNode 用于创建和渲染粒子系统
    • SKView 对象执行动画和渲染
    • SKScene 游戏内容组织成的场景
    • SKAction 节点动画

    效果

    这是一个类似于FlappyBird的小游戏
    集成GameCenter

    catcat.gif

    分析

    结构很简单
    设计思路就是障碍物不断的移动.当把角色卡死时游戏结束

    结构

    代码

    1.预加载游戏结束时的弹出广告
    2.加载背景
    3.设置physicsBody
    4.设置障碍物移动Action
    5.设置开始面板角色及初始Action
    6.加载所有内容节点

    • 初始化
    - (void)initalize
    {
        [super initalize];
        SKSpriteNode* background=[SKSpriteNode spriteNodeWithImageNamed:@"sky.png"];
        background.size = self.view.frame.size;
        background.position=CGPointMake(background.size.width/2, background.size.height/2);
        [self addChild:background];
        self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
        self.physicsBody.categoryBitMask = edgeCategory;
        self.physicsWorld.contactDelegate = self;
        self.moveWallAction = [SKAction sequence:@[[SKAction moveToX:-WALL_WIDTH duration:TIMEINTERVAL_MOVEWALL],[SKAction removeFromParent]]];
        SKAction *upHeadAction = [SKAction rotateToAngle:M_PI / 6 duration:0.2f];
        upHeadAction.timingMode = SKActionTimingEaseOut;
        SKAction *downHeadAction = [SKAction rotateToAngle:-M_PI / 2 duration:0.8f];
        downHeadAction.timingMode = SKActionTimingEaseOut;
        self.moveHeadAction = [SKAction sequence:@[upHeadAction, downHeadAction,]];
        [self addGroundNode];
        [self addCeiling];
        [self addHeroNode];
        [self addResultLabelNode];
        [self addInstruction];
        [self runAction:[SKAction repeatActionForever:[SKAction sequence:@[
                                                                           [SKAction performSelector:@selector(addFish) onTarget:self],
                                                                           [SKAction waitForDuration:0.3f],
                                                                           ]]] withKey:ACTIONKEY_ADDFISH];
        
        _interstitialObj = [[GDTMobInterstitial alloc]
                            initWithAppkey:@"1106301022"
                            placementId:@"2080622474511184"];
        _interstitialObj.delegate = self;
        //设置委托 _interstitialObj.isGpsOn = NO; //【可选】设置GPS开关
        //预加载广告
        [_interstitialObj loadAd];
     
    }
    
    • 加载角色,设置飞行动作,触摸事件
    - (void)addHeroNode
    {
        self.hero=[SKSpriteNode spriteNodeWithImageNamed:@"player"];
        SKTexture* texture=[SKTexture textureWithImageNamed:@"player"];
        _hero.physicsBody=[SKPhysicsBody bodyWithTexture:texture size:_hero.size];
        _hero.anchorPoint = CGPointMake(0.5, 0.5);
        _hero.position = CGPointMake(self.frame.size.width / 2, CGRectGetMidY(self.frame));
        _hero.name = NODENAME_HERO;
        _hero.physicsBody.categoryBitMask = heroCategory;
        _hero.physicsBody.collisionBitMask = wallCategory | groundCategory|edgeCategory;
        _hero.physicsBody.contactTestBitMask = holeCategory | wallCategory | groundCategory|fishCategory;
        _hero.physicsBody.dynamic = YES;
        _hero.physicsBody.affectedByGravity = NO;
        _hero.physicsBody.allowsRotation = NO;
        _hero.physicsBody.restitution = 0.4;
        _hero.physicsBody.usesPreciseCollisionDetection = NO;
        [self addChild:_hero];
    //    SKTexture* texture1=[SKTexture textureWithImageNamed:@"player"];
    //    SKTexture* texture2=[SKTexture textureWithImageNamed:@"player3"];
    //
    //    SKAction *animate = [SKAction animateWithTextures:@[texture1,texture2] timePerFrame:0.1];
    //    [_hero runAction:[SKAction repeatActionForever:animate]];
        [_hero runAction:[SKAction repeatActionForever:[self getFlyAction]]
                 withKey:ACTIONKEY_FLY];
    }
    
    
    - (SKAction *)getFlyAction
    {
        SKAction *flyUp = [SKAction moveToY:_hero.position.y + 10 duration:0.3f];
        flyUp.timingMode = SKActionTimingEaseOut;
        SKAction *flyDown = [SKAction moveToY:_hero.position.y - 10 duration:0.3f];
        flyDown.timingMode = SKActionTimingEaseOut;
        SKAction *fly = [SKAction sequence:@[flyUp, flyDown]];
        return fly;
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        if (_isGameOver) {
            return;
        }
        if (!_isGameStart) {
            [self startGame];
        }
        _hero.physicsBody.velocity = CGVectorMake(100, 500);
        [_hero runAction:_moveHeadAction withKey:ACTIONKEY_MOVEHEAD];
    }
    
    • 加载开始说明和结束说明
    - (void)addResultLabelNode
    {
        self.labelNode = [SKLabelNode labelNodeWithFontNamed:@"PingFangSC-Regular"];
        _labelNode.fontSize = 30.0f;
        _labelNode.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeLeft;
        _labelNode.verticalAlignmentMode = SKLabelVerticalAlignmentModeTop;
        _labelNode.position = CGPointMake(10, self.frame.size.height - 20);
        _labelNode.fontColor = COLOR_LABEL;
        _labelNode.zPosition=100;
        [self addChild:_labelNode];
    }
    - (void)addInstruction{
        self.hitSakuraToScore = [SKLabelNode labelNodeWithFontNamed:@"AmericanTypewriter"];
        _hitSakuraToScore.fontSize = 20.0f;
        _hitSakuraToScore.position = CGPointMake(self.frame.size.width / 2, CGRectGetMidY(self.frame)-60);
        _hitSakuraToScore.fontColor = COLOR_LABEL;
        _hitSakuraToScore.zPosition=100;
        _hitSakuraToScore.text=@"Hit fish to Score";
    //    _hitSakuraToScore.text=NSLocalizedString(@"Hit Sakura to Score", nil);
        [self addChild:_hitSakuraToScore];
        self.tapToStart = [SKLabelNode labelNodeWithFontNamed:@"PingFangSC-Regular"];
        _tapToStart.fontSize = 20.0f;
        _tapToStart.position = CGPointMake(self.frame.size.width / 2, CGRectGetMidY(self.frame)-100);
        _tapToStart.fontColor = COLOR_LABEL;
        _tapToStart.zPosition=100;
        _tapToStart.text=@"Tap to Jump";
        [self addChild:_tapToStart];
    }
    
    • 加载障碍物
    - (void)addWall
    {
        CGFloat spaceHeigh = self.frame.size.height - GROUND_HEIGHT;
        float random= arc4random() % 4;
        CGFloat holeLength = HERO_SIZE.height * (2.0+random*0.1);
        int holePosition = arc4random() % (int)((spaceHeigh - holeLength) / HERO_SIZE.height);
        CGFloat x = self.frame.size.width;
        CGFloat upHeight = holePosition * HERO_SIZE.height;
        if (upHeight > 0) {
            SKSpriteNode *upWall = [SKSpriteNode spriteNodeWithColor:COLOR_WALL size:CGSizeMake(WALL_WIDTH, upHeight)];
            upWall.anchorPoint = CGPointMake(0, 0);
            upWall.position = CGPointMake(x, self.frame.size.height - upHeight);
            upWall.name = NODENAME_WALL;
            upWall.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:upWall.size center:CGPointMake(upWall.size.width / 2.0f, upWall.size.height / 2.0f)];
            upWall.physicsBody.categoryBitMask = wallCategory;
            upWall.physicsBody.dynamic = NO;
            upWall.physicsBody.friction = 0;
            [upWall runAction:_moveWallAction withKey:ACTIONKEY_MOVEWALL];
            [self addChild:upWall];
        }
        CGFloat downHeight = spaceHeigh - upHeight - holeLength;
        if (downHeight > 0) {
            SKSpriteNode *downWall = [SKSpriteNode spriteNodeWithColor:COLOR_WALL size:CGSizeMake(WALL_WIDTH, downHeight)];
            downWall.anchorPoint = CGPointMake(0, 0);
            downWall.position = CGPointMake(x, GROUND_HEIGHT);
            downWall.name = NODENAME_WALL;
            downWall.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:downWall.size center:CGPointMake(downWall.size.width / 2.0f, downWall.size.height / 2.0f)];
            downWall.physicsBody.categoryBitMask = wallCategory;
            downWall.physicsBody.dynamic = NO;
            downWall.physicsBody.friction = 0;
            [downWall runAction:_moveWallAction withKey:ACTIONKEY_MOVEWALL];
            [self addChild:downWall];
        }
        
        SKSpriteNode *hole = [SKSpriteNode spriteNodeWithColor:[UIColor clearColor] size:CGSizeMake(WALL_WIDTH, holeLength)];
        hole.anchorPoint = CGPointMake(0, 0);
        hole.position = CGPointMake(x, self.frame.size.height - upHeight - holeLength);
        hole.name = NODENAME_HOLE;
        hole.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:hole.size center:CGPointMake(hole.size.width / 2.0f, hole.size.height / 2.0f)];
        hole.physicsBody.categoryBitMask = holeCategory;
        hole.physicsBody.dynamic = NO;
        [hole runAction:_moveWallAction withKey:ACTIONKEY_MOVEWALL];
        [self addChild:hole];
    }
    
    
    • 游戏开始时 不断增加障碍物
    - (void)startGame
    {
        self.isGameStart = YES;
        _hero.physicsBody.affectedByGravity = YES;
        [_hero removeActionForKey:ACTIONKEY_FLY];
        [_tapToStart removeFromParent];
        [_hitSakuraToScore removeFromParent];
        [self addResultLabelNode];
        SKAction *addWall = [SKAction sequence:@[
                                                 [SKAction performSelector:@selector(addWall) onTarget:self],
                                                 [SKAction waitForDuration:TIMEINTERVAL_ADDWALL],
                                                 ]];
        [self runAction:[SKAction repeatActionForever:addWall] withKey:ACTIONKEY_ADDWALL];
    }
    
    • 实时更新内容
    - (void)update:(NSTimeInterval)currentTime
    {
        if(self.hero&&!_isGameOver){
            if ( self.hero.position.x<10) {
                [self gameOver];
            }else if(self.hero.position.x>self.frame.size.width){
                self.hero.position =CGPointMake(self.hero.position.x-20, self.hero.position.y);
            }
        }
        __block int wallCount = 0;
        [self enumerateChildNodesWithName:NODENAME_WALL usingBlock:^(SKNode *node, BOOL *stop) {
            if (wallCount >= 2) {
                *stop = YES;
                return;
            }
            if (node.position.x <= -WALL_WIDTH) {
                wallCount++;
                [node removeFromParent];
            }
        }];
        [self enumerateChildNodesWithName:NODENAME_HOLE usingBlock:^(SKNode *node, BOOL *stop) {
            if (node.position.x <= -WALL_WIDTH) {
                [node removeFromParent];
                *stop = YES;
            }
        }];
        [self enumerateChildNodesWithName:NODENAME_FISH usingBlock:^(SKNode *node, BOOL *stop) {
            if (node.position.x <= -node.frame.size.width) {
                [node removeFromParent];
            }
        }];
    }
    
    
    • 设置物体碰撞效果
    - (void)didBeginContact:(SKPhysicsContact *)contact
    {
        if (_isGameOver) {
            return;
        }
        SKPhysicsBody *firstBody, *secondBody;
        
        if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) {
            firstBody = contact.bodyA;
            secondBody = contact.bodyB;
        } else {
            firstBody = contact.bodyB;
            secondBody = contact.bodyA;
        }
        if ((firstBody.categoryBitMask & heroCategory) && (secondBody.categoryBitMask & fishCategory)) {
            if(secondBody.node.parent&&self.isGameStart){
                int currentPoint = [_labelNode.text intValue];
                _labelNode.text = [NSString stringWithFormat:@"%d", currentPoint + 1];
                [self playSoundWithName:@"sfx_wing.caf"];
                NSString *burstPath =
                [[NSBundle mainBundle]
                 pathForResource:@"MyParticle" ofType:@"sks"];
                SKEmitterNode *burstNode =
                [NSKeyedUnarchiver unarchiveObjectWithFile:burstPath];
                burstNode.position = secondBody.node.position;
                [secondBody.node removeFromParent];
                [self addChild:burstNode];
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    [burstNode runAction:[SKAction removeFromParent]];
                });
            }
        }
    }
    - (void) didEndContact:(SKPhysicsContact *)contact{
        if (_isGameOver) {
            return;
        }
        SKPhysicsBody *firstBody, *secondBody;
        if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) {
            firstBody = contact.bodyA;
            secondBody = contact.bodyB;
        } else {
            firstBody = contact.bodyB;
            secondBody = contact.bodyA;
        }
        return;
    
    }
    
    - (void)playSoundWithName:(NSString *)fileName
    {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self runAction:[SKAction playSoundFileNamed:fileName waitForCompletion:YES]];
        });
    }
    
    • 游戏结束与重新开始
    - (void)gameOver
    {
        self.isGameOver = YES;
        self.isGameStart=NO;
        [_hero removeActionForKey:ACTIONKEY_MOVEHEAD];
        [self removeActionForKey:ACTIONKEY_ADDWALL];
        [self enumerateChildNodesWithName:NODENAME_WALL usingBlock:^(SKNode *node, BOOL *stop) {
            [node removeActionForKey:ACTIONKEY_MOVEWALL];
        }];
        [self enumerateChildNodesWithName:NODENAME_HOLE usingBlock:^(SKNode *node, BOOL *stop) {
            [node removeActionForKey:ACTIONKEY_MOVEWALL];
        }];
        if([_labelNode.text isEqualToString:@""])
            _labelNode.text=@"0";
        NSString *result=_labelNode.text;
        RestartLabel *restartView = [RestartLabel getInstanceWithSize:self.size Point:result];
        restartView.delegate = self;
        [restartView showInScene:self];
        _labelNode.text=@"";
        
        if (_interstitialObj.isReady) {
            UIViewController *vc = [[[UIApplication sharedApplication] keyWindow] rootViewController];
            //vc = [self navigationController];
            [_interstitialObj presentFromRootViewController:vc];
        }
        
        
    }
    
    - (void)restart
    {
        [self addInstruction];
        self.labelNode.text = @"";
        [self enumerateChildNodesWithName:NODENAME_HOLE usingBlock:^(SKNode *node, BOOL *stop) {
            [node removeFromParent];
        }];
        [self enumerateChildNodesWithName:NODENAME_WALL usingBlock:^(SKNode *node, BOOL *stop) {
            [node removeFromParent];
        }];
        [_hero removeFromParent];
        self.hero = nil;
        [self addHeroNode];
        [self runAction:[SKAction repeatActionForever:[SKAction sequence:@[
                                                                           [SKAction performSelector:@selector(addFish) onTarget:self],
                                                                           [SKAction waitForDuration:0.3f],
                                                                           ]]] withKey:ACTIONKEY_ADDFISH];
        self.isGameStart = NO;
        self.isGameOver = NO;
    }
    
    
    - (void)restartView:(RestartLabel *)restartView didPressRestartButton:(SKSpriteNode *)restartButton
    {
        [restartView dismiss];
        [self restart];
    
    }
    - (void)restartView:(RestartLabel *)restartView didPressLeaderboardButton:(SKSpriteNode *)restartButton{
        [self showLeaderboard];
    }
    
    • 游戏结束可以调期GameCenter排行榜
    -(void)showLeaderboard{
        GKGameCenterViewController *gcViewController = [[GKGameCenterViewController alloc] init];
        gcViewController.gameCenterDelegate = self;
        gcViewController.viewState = GKGameCenterViewControllerStateLeaderboards;
        gcViewController.leaderboardIdentifier = @"MyFirstLeaderboard";
        [self.view.window.rootViewController presentViewController:gcViewController animated:YES completion:nil];
        
    }
    -(void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController
    {
        [gameCenterViewController dismissViewControllerAnimated:YES completion:nil];
    }
    
    
    • 积分框
    @interface ScoreLabel : SKSpriteNode
    
    @property(nonatomic, copy) NSString* finalPoint;
    
    @end
    
    #import "ScoreLabel.h"
    
    @implementation ScoreLabel
    
    - (id)initWithColor:(UIColor *)color size:(CGSize)size
    {
        if (self = [super initWithColor:color size:size]) {
            SKLabelNode* scoreLabelNode = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
            scoreLabelNode.text=_finalPoint;
            scoreLabelNode.fontSize = 20.0f;
            scoreLabelNode.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter;
            scoreLabelNode.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
            scoreLabelNode.position = CGPointMake(size.width / 2.0f, size.height - 300);
            scoreLabelNode.fontColor = [UIColor whiteColor];
            [self addChild:scoreLabelNode];    }
        return self;
    }
    
    @end
    
    • 游戏结束节点内容
    @class RestartLabel;
    @protocol RestartViewDelegate <NSObject>
    
    - (void)restartView:(RestartLabel *)restartView didPressRestartButton:(SKSpriteNode *)restartButton;
    - (void)restartView:(RestartLabel *)restartView didPressLeaderboardButton:(SKSpriteNode *)restartButton;
    @end
    
    @interface RestartLabel : SKSpriteNode
    
    @property (weak, nonatomic) id <RestartViewDelegate> delegate;
    @property (copy, nonatomic) NSString* finalPoint;
    + (RestartLabel *)getInstanceWithSize:(CGSize)size Point:(NSString *)point;
    - (void)dismiss;
    - (void)showInScene:(SKScene *)scene;
    
    @end
    
    #define NODENAME_BUTTON @"button"
    #import "RestartLabel.h"
    #import "MainViewController.h"
    
    @import GameKit;
    @interface RestartLabel()
    @property (strong, nonatomic) SKSpriteNode *button;
    @property (strong, nonatomic) SKLabelNode *labelNode;
    @property (strong, nonatomic) SKLabelNode *scoreLabelNode;
    @property (strong, nonatomic) SKLabelNode *highestLabelNode;
    @property (strong, nonatomic) SKSpriteNode *gameCenterNode;
    @property (strong, nonatomic) SKLabelNode *gameCenterLabel;
    @end
    
    @implementation RestartLabel
    
    - (id)initWithColor:(UIColor *)color size:(CGSize)size
    {
        if (self = [super initWithColor:color size:size]) {
            self.userInteractionEnabled = YES;
            self.button = [SKSpriteNode spriteNodeWithColor:[UIColor colorWithRed:0.608 green:0.349 blue:0.714 alpha:1] size:CGSizeMake(100, 50)];
            _button.position = CGPointMake(size.width / 2.0f, size.height - 350);
            _button.name = NODENAME_BUTTON;
            [self addChild:_button];
            self.labelNode = [SKLabelNode labelNodeWithFontNamed:@"PingFangSC-Regular"];
            _labelNode.text = @"Restart";
            _labelNode.fontSize = 20.0f;
            _labelNode.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter;
            _labelNode.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
            _labelNode.position = CGPointMake(0, 0);
            _labelNode.fontColor = [UIColor whiteColor];
            [_button addChild:_labelNode];
            self.gameCenterNode = [SKSpriteNode spriteNodeWithColor:[UIColor colorWithRed:0.608 green:0.349 blue:0.714 alpha:1]size:CGSizeMake(150, 50)];
            _gameCenterNode.position = CGPointMake(size.width / 2.0f, size.height - 280);
            [self addChild:_gameCenterNode];
            self. gameCenterLabel=[SKLabelNode labelNodeWithFontNamed:@"PingFangSC-Regular"];
            _gameCenterLabel.text = @"Leaderboard";
            _gameCenterLabel.fontSize = 20.0f;
            _gameCenterLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter;
            _gameCenterLabel.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
            _gameCenterLabel.position = CGPointMake(0, 0);
            _gameCenterLabel.fontColor = [UIColor whiteColor];
            [_gameCenterNode addChild:_gameCenterLabel];
            
        }
        return self;
    }
    -(void)addScoreLabelSize:(CGSize)size{
        _scoreLabelNode = [SKLabelNode labelNodeWithFontNamed:@"PingFangSC-Regular"];
        _scoreLabelNode.text=[NSString stringWithFormat:@"Your Score: \r%@",_finalPoint? _finalPoint: @"0"];
        _scoreLabelNode.fontSize = 20.0f;
        _scoreLabelNode.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter;
        _scoreLabelNode.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
        _scoreLabelNode.position = CGPointMake(size.width / 2.0f, size.height - 170);
        _scoreLabelNode.fontColor = [UIColor colorWithRed:0.173 green:0.243 blue:0.314 alpha:1];
        [self addChild:_scoreLabelNode];
    }
    
    -(void)addHighestLabelSize:(CGSize)size{
        _highestLabelNode = [SKLabelNode labelNodeWithFontNamed:@"PingFangSC-Regular"];
         _highestLabelNode.fontColor = [UIColor colorWithRed:0.173 green:0.243 blue:0.314 alpha:1];
        NSString* showText;
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        NSNumber* highestScore=[defaults objectForKey:@"HighScore"];
        NSNumber* currentPoint= [NSNumber numberWithInt: [_finalPoint intValue]];
        if(highestScore==nil||[currentPoint integerValue]>[highestScore integerValue]){
            [defaults setObject:currentPoint forKey:@"HighScore"];
            highestScore=currentPoint;
            showText=@"New Record!";
            _highestLabelNode.fontColor=[UIColor colorWithRed:0.753 green:0.224 blue:0.169 alpha:1];
            [defaults synchronize];
        }else{
            showText=[NSString stringWithFormat:@"High Score: \r%lu",(long)[highestScore integerValue]];
        }
        if(highestScore!=nil){
         [self reportScore:[highestScore integerValue]];
        }
        _highestLabelNode.text=showText;
        _highestLabelNode.fontSize = 20.0f;
        _highestLabelNode.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeCenter;
        _highestLabelNode.verticalAlignmentMode = SKLabelVerticalAlignmentModeCenter;
        _highestLabelNode.position = CGPointMake(size.width / 2.0f, size.height - 220);
        [self addChild:_highestLabelNode];
    }
    
    
    + (RestartLabel *)getInstanceWithSize:(CGSize)size Point:(NSString *)point
    {
        RestartLabel *restartView = [RestartLabel spriteNodeWithColor:color(255, 255, 255, 0.6) size:size];
        restartView.anchorPoint = CGPointMake(0, 0);
        restartView.finalPoint=point;
        [restartView addScoreLabelSize:size];
        [restartView addHighestLabelSize:size];
        return restartView;
    }
    
    - (void)showInScene:(SKScene *)scene
    {
        self.alpha = 0.0f;
        [scene addChild:self];
        [self runAction:[SKAction fadeInWithDuration:0.3f]];
    }
    
    - (void)dismiss
    {
        [self runAction:[SKAction fadeOutWithDuration:0.3f] completion:^{
            [self removeFromParent];
        }];
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        UITouch *touch = [touches anyObject];
        CGPoint location = [touch locationInNode:self];
        SKNode *touchNode = [self nodeAtPoint:location];
        if (touchNode == _button || touchNode == _labelNode) {
            if ([_delegate respondsToSelector:@selector(restartView:didPressRestartButton:)]) {
                [_delegate restartView:self didPressRestartButton:_button];
            }
        }else if(touchNode==_gameCenterNode || touchNode==_gameCenterLabel){
            if ([_delegate respondsToSelector:@selector(restartView:didPressLeaderboardButton:)]) {
                [_delegate restartView:self didPressLeaderboardButton:_button];
        }
    }
    }
    -(void)reportScore:(NSInteger)inputScore{
        GKScore *score = [[GKScore alloc] initWithLeaderboardIdentifier:@"MyFirstLeaderboard"];
        score.value = inputScore;
        [GKScore reportScores:@[score] withCompletionHandler:^(NSError *error) {
            if (error != nil) {
                NSLog(@"%@", [error localizedDescription]);
            }
        }];
    }
    
    
    @end
    
    

    关于游戏上架Tips


    蛋疼广电粽菊要求国内游戏必须备案...
    我们只是想上个小游戏而已~难道还要再等个大半个月去备案么?
    Apple也妥协了 在备注那里要求中国区上架游戏必须填写备案号

    But!!!上有政策,下有对策嘛~

    • 填写App分类时直接选择娱乐类型上架,就不会要求填写备案号了~
    • 销售范围,不选择中国地区,这样也不会要求填写备案号,等过审了,再将销售范围改回所有地区,基本上是实时生效~

    以上两种方式屡试不爽哈~对于我们个人小开发来说也算是个小福利了.

    Demo地址

    Github地址,欢迎Star (由于集成了广告,广点通的静态库需要单独下载下完直接扔到项目里就行)
    已上架Appstore 猫爷快吃 喜欢就支持下吧~
    欢迎光顾自己的小站,内容都是同步更新的~
    大家低调支持下自己的 牛牛数据 Half-price~~

    还没结束


    快来猜猜我放的背景音乐是啥~

    相关文章

      网友评论

        本文标题:iOS开发实战-基于SpriteKit的FlappyBird小游

        本文链接:https://www.haomeiwen.com/subject/gorbkxtx.html