iOS開發(fā)實(shí)戰(zhàn)-基于SpriteKit的FlappyBird小游戲

寫在前面

最近一直在忙自己的維P恩的事情
公司項(xiàng)目也是一團(tuán)亂
于是...隨手找了個(gè)游戲項(xiàng)目改了改就上線了,就當(dāng)充數(shù)了.

SpriteKit簡介

SpriteKit是iOS 7之后蘋果推出的2D游戲框架。它支持2D游戲中各種功能,如物理引擎娄琉,地圖編輯,粒子浑玛,視頻,聲音精靈化,光照等。

SpriteKit中常用的類

  • SKSpriteNode 用于繪制精靈紋理
  • SKVideoNode 用于播放視頻
  • SKLabelNode 用于渲染文本
  • SKShapeNode 用于渲染基于Core Graphics路徑的形狀
  • SKEmitterNode 用于創(chuàng)建和渲染粒子系統(tǒng)
  • SKView 對(duì)象執(zhí)行動(dòng)畫和渲染
  • SKScene 游戲內(nèi)容組織成的場景
  • SKAction 節(jié)點(diǎn)動(dòng)畫

效果

這是一個(gè)類似于FlappyBird的小游戲
集成GameCenter

catcat.gif

分析

結(jié)構(gòu)很簡單
設(shè)計(jì)思路就是障礙物不斷的移動(dòng).當(dāng)把角色卡死時(shí)游戲結(jié)束

結(jié)構(gòu)

代碼

1.預(yù)加載游戲結(jié)束時(shí)的彈出廣告
2.加載背景
3.設(shè)置physicsBody
4.設(shè)置障礙物移動(dòng)Action
5.設(shè)置開始面板角色及初始Action
6.加載所有內(nèi)容節(jié)點(diǎn)

  • 初始化
- (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;
    //設(shè)置委托 _interstitialObj.isGpsOn = NO; //【可選】設(shè)置GPS開關(guān)
    //預(yù)加載廣告
    [_interstitialObj loadAd];
 
}
  • 加載角色,設(shè)置飛行動(dòng)作,觸摸事件
- (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];
}
  • 加載開始說明和結(jié)束說明
- (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];
}

  • 游戲開始時(shí) 不斷增加障礙物
- (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];
}
  • 實(shí)時(shí)更新內(nèi)容
- (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];
        }
    }];
}

  • 設(shè)置物體碰撞效果
- (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]];
    });
}
  • 游戲結(jié)束與重新開始
- (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];
}
  • 游戲結(jié)束可以調(diào)期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
  • 游戲結(jié)束節(jié)點(diǎn)內(nèi)容
@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

關(guān)于游戲上架Tips


蛋疼廣電粽菊要求國內(nèi)游戲必須備案...
我們只是想上個(gè)小游戲而已~難道還要再等個(gè)大半個(gè)月去備案么?
Apple也妥協(xié)了 在備注那里要求中國區(qū)上架游戲必須填寫備案號(hào)

But!!!上有政策,下有對(duì)策嘛~

  • 填寫App分類時(shí)直接選擇娛樂類型上架,就不會(huì)要求填寫備案號(hào)了~
  • 銷售范圍,不選擇中國地區(qū),這樣也不會(huì)要求填寫備案號(hào),等過審了,再將銷售范圍改回所有地區(qū),基本上是實(shí)時(shí)生效~

以上兩種方式屢試不爽哈~對(duì)于我們個(gè)人小開發(fā)來說也算是個(gè)小福利了.

Demo地址

Github地址,歡迎Star (由于集成了廣告,廣點(diǎn)通的靜態(tài)庫需要單獨(dú)下載下完直接扔到項(xiàng)目里就行)
已上架Appstore 貓爺快吃 喜歡就支持下吧~
歡迎光顧自己的小站,內(nèi)容都是同步更新的~
大家低調(diào)支持下自己的 牛牛數(shù)據(jù) Half-price~~

還沒結(jié)束


快來猜猜我放的背景音樂是啥~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末哈蝇,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子攘已,更是在濱河造成了極大的恐慌炮赦,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件样勃,死亡現(xiàn)場離奇詭異吠勘,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)峡眶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門剧防,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人辫樱,你說我怎么就攤上這事诵姜。” “怎么了搏熄?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵棚唆,是天一觀的道長。 經(jīng)常有香客問我心例,道長宵凌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任止后,我火速辦了婚禮瞎惫,結(jié)果婚禮上溜腐,老公的妹妹穿的比我還像新娘。我一直安慰自己瓜喇,他們只是感情好挺益,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著乘寒,像睡著了一般望众。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上伞辛,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天烂翰,我揣著相機(jī)與錄音,去河邊找鬼蚤氏。 笑死甘耿,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的竿滨。 我是一名探鬼主播佳恬,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼于游!你這毒婦竟也來了毁葱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤曙砂,失蹤者是張志新(化名)和其女友劉穎头谜,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸠澈,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡柱告,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了笑陈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片际度。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖涵妥,靈堂內(nèi)的尸體忽然破棺而出乖菱,到底是詐尸還是另有隱情,我是刑警寧澤蓬网,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布窒所,位于F島的核電站,受9級(jí)特大地震影響帆锋,放射性物質(zhì)發(fā)生泄漏吵取。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一锯厢、第九天 我趴在偏房一處隱蔽的房頂上張望皮官。 院中可真熱鬧脯倒,春花似錦、人聲如沸捺氢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽摄乒。三九已至悠反,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間缺狠,已是汗流浹背问慎。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工萍摊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留挤茄,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓冰木,卻偏偏與公主長得像穷劈,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子踊沸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容