2016-01-17 5 views
2

Я делаю 2D-игру с комплектом спрайтов, и мне нужно добавить способ ускорить игру после каждых 50 очков.Как ускорить игру Sprite Kit после каждого дополнительного 50 очков

Я разработал метод, который добавляет скорость по мере необходимости, но мне нужно скопировать, вставить и настроить if-statement в методе обновления на каждые дополнительные 50 пунктов.

Еще одна проблема с моим решением заключается в том, что я должен дать свои баллы приращение сразу после его ускорения, потому что, если игра не ускорится, хотя я не знаю почему.

Вот мое решение до сих пор:

// inside the update method 
// points are added when an enemy is destroyed 
// pointSpeed is the float variable that is used to change positions 

if (points == 4) { 
    pointSpeed++; 
    points++; 
} 
if (points == 8) { 
    pointSpeed++; 
    points++; 
} 
if (points == 12) { 
    pointSpeed++; 
    points++; 
} 

Я хотел бы реализовать эту функцию, не будучи вынуждены делать все приращения вручную и без игры форсирование без приращений точек.

ответ

1

Swift путь

Вы можете использовать didSet свойство наблюдателя, чтобы изменить скорость игры на основе текущего счета:

import SpriteKit 

class GameScene: SKScene { 

    var score:Int = 0 { 

     didSet{ 

      if score % 10 == 0 { 
       gameSpeed += 0.5 
      } 

      label.text = "Score : \(score), Speed : \(gameSpeed)" 
     } 

    } 

    var gameSpeed:Double = 1.0 

    var label:SKLabelNode = SKLabelNode(fontNamed: "ArialMT") 

    override func didMoveToView(view: SKView) { 
     /* Setup your scene here */ 

     label.text = "Score : \(score), Speed : \(gameSpeed)" 
     label.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidX(frame)) 
     label.fontSize = 18 

     addChild(label) 

    } 

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { 

     score++ 
    } 

} 

из документов:

didSet вызывается сразу после сохранения нового значения.

Итак, сразу после установки новой оценки вы должны обновить переменную gameSpeed.

Objective-C путь

В Objective-C не такая вещь, которая может обеспечить точно такое же поведение, как наблюдателей собственности didSet и willSet Свифта. Но есть еще способы, например, вы можете переопределить сеттер счётом, как и это:

#import "GameScene.h" 

@interface GameScene() 

@property(nonatomic, strong) SKLabelNode *label; 

@property(nonatomic, assign) NSUInteger score; 

@property(nonatomic, assign) double gameSpeed; 

@end 

@implementation GameScene 

-(instancetype)initWithCoder:(NSCoder *)aDecoder{ 

NSLog(@"Scene's initWithSize: called"); 

if(self = [super initWithCoder:aDecoder]){ 

     /* 

     Instance variables in Obj-C should be used only while initialization, deallocation or when overriding accessor methods. 
     Otherwise, you should use accessor methods (eg. through properties). 

     */ 

     _gameSpeed = 1; 
     _score  = 0; 

     NSLog(@"Variables initialized successfully"); 
    } 

    return self; 
} 

-(void)didMoveToView:(SKView *)view { 

    self.label  = [SKLabelNode labelNodeWithFontNamed:@"ArialMT"]; 
    self.label.fontSize = 18; 
    self.label.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)); 
    self.label.text = [NSString stringWithFormat:@"Score : %lu, Speed %f", self.score, self.gameSpeed]; 
    [self addChild:self.label]; 

} 

//Overriding an actual setter, so when score is changed, the game speed will change accordingly 
-(void)setScore:(NSUInteger)score{ 

    /* 

    Make sure that you don't do assigment like this, self.score = score, but rather _score = score 
    because self.score = somevalue, is an actual setter call - [self setScore:score]; and it will create an infinite recursive call. 

    */ 
    _score   = score; 


    if(_score % 10 == 0){ 
     self.gameSpeed += 0.5; 
    } 

    // Here, it is safe to to write something like self.score, because you call the getter. 

    self.label.text = [NSString stringWithFormat:@"Score : %lu, Speed %f", self.score, self.gameSpeed]; 

} 

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 

    self.score++; 
} 

@end 

Или, я думаю, вы можете сделать то же самое с помощью KVO, но для примера из-за простоты, вы можете просто переопределить сеттер. Или может быть, вы могли бы просто сделать пользовательский метод, который позволит увеличить разрыв в счете, обрабатывать обновления логику gameSpeed, и обновить скорость, если необходимо:

//Whenever the player scores, you will do this 
[self updateScore: score]; 

Таким образом, вы будете иметь дополнительное определение метода, который должен быть вызван при игрок забивает, в сравнении с этим (при условии, что показатель сеттер в переопределяется):

self.score = someScore; 

это действительно до вас.

Надеюсь, что это имеет смысл, и это помогает!

EDIT:

Я изменил initWithSize: к initWithCoder, потому что initWithSize не вызывается, когда сцена загружается из SKS, который, вероятно, как вы делаете это, из-за того, что в Xcode 7 сцена загружается по умолчанию из файла .sks.

+0

Можете ли вы дать мне синтаксис didSet для объектного c? – ccdev

+0

@codev О, извините, я не заметил тег Obj-C. В Obj-C по умолчанию таких методов нет, которые обеспечивают то же поведение, что и наблюдатели свойств willSet и didSet ... Но есть и другие способы достижения подобного поведения. В ближайшее время обновит мой ответ. – Whirlwind

0

Если вы хотите обновить скорость через равные промежутки времени, вы можете использовать оператор модуля - взять остаток после деления на ваш интервал - если это равно нулю, принять меры. Причина, по которой вы находите, что игра ускоряется полностью, заключается в том, что в следующий раз через функцию обновления она все еще находится на правом уровне, и она просто увеличивает скорость - вы можете добавить другую переменную для отслеживания, если вы готовы к приращению

// as part of class declaration 
var bReadyForIncrement : Bool = true 
let pointIncrement : Int = 4 // or whatever you need 


// inside the update method 
// points are added when an enemy is destroyed 
// pointSpeed is the float variable that is used to change positions 

if (points % 4) 
{ 
    if bReadyForIncrement 
    { 
     pointSpeed++; 
     bReadyForIncrement = false // set this to true wherever you add points 
    } 
} 
+2

Если скорость игры зависит только от оценки, то вам не нужно проверять это в методе обновления, который запускается 60 раз в секунду. Вы должны сделать эту проверку и изменить скорость, каждый раз, когда оценка изменяется. – Whirlwind

+0

Как я могу проверить bReadyForIncrement? Или лучше, как я могу снова установить его на True? – ccdev

+0

Всякий раз, когда враг уничтожается и вы увеличиваете счет - просто установите bReadyForIncrement true – Russell