如何在每增加50点之后加速Sprite Kit游戏

时间:2016-01-17 15:38:13

标签: ios objective-c sprite-kit 2d-games

我正在使用Sprite Kit制作2D游戏,我需要添加一种方法来在每50分后加速游戏。

我制定了一个方法来增加所需的速度,但我必须在更新方法中复制,粘贴和调整if语句,每增加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++;
}

我希望实现此功能,而不必手动执行所有增量,并且不会在没有分数增量的情况下加速游戏。

2 个答案:

答案 0 :(得分:1)

迅捷

您可以使用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中没有这样的东西可以提供与Swift的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做同样的事情,但是为了你的例子,因为简单,你可以覆盖一个setter。或者也许您可以制作一个自定义方法来提高分数,处理gameSpeed的更新逻辑,并在必要时更新速度:

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

所以,你将有一个额外的方法定义,当玩家得分时必须调用,与此相比(假设得分的设定者被覆盖):

self.score = someScore; 

这完全取决于你。

希望这有意义,这有帮助!

修改

我已将initWithSize:更改为initWithCoder,因为当从sks加载场景时未调用initWithSize,这可能就是你在做的事情,因为事实是在Xcode 7中,场景默认从.sks文件中加载。

答案 1 :(得分:0)

如果要定期更新速度,可以使用模数运算符 - 除以间隔后取余数 - 如果等于零,则采取措施。 你发现游戏完全加速的原因是,下次通过更新功能,它仍然在正确的积分水平,它只是增加速度 - 你可以添加另一个变量来跟踪你是否&#39;为增量做好准备

// 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
    }
}