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

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

我制定了一个方法来增加速度,但是我必须复制,粘贴和调整更新方法中的if语句每增加50点。

我的解决scheme的另一个问题是,我必须在加速之后立刻给我的分数加分,因为如果不是这样,游戏速度就会完全加快,但我不知道为什么。

到目前为止,我的解决scheme是:

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

我想实现这个function,而不是被迫手动做所有的增量,没有点增量没有游戏加速。

迅速的方式

您可以使用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。

所以,在新的分数被设置之后,你应该更新gameSpeedvariables。

Objective-C的方式

在Objective-C中,没有这样的事情可以提供像Swift的didSet和willSet属性观察者一样的行为。 但是还有另一种方法,例如,你可以重写一个分数的setter,像这样:

 #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]; 

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

 self.score = someScore; 

这真的取决于你。

希望这是有道理的,它有帮助!

编辑:

我把initWithSize:改成了initWithSize: ,因为在从sks加载场景时不调用initWithSize ,这可能是你如何做的,因为在Xcode 7场景中默认从.sks文件加载。

如果要定期更新速度,则可以使用模数运算符 – 除以间隔后的余数 – 如果等于零,则采取行动。 你发现游戏加速完全的原因是,下一次通过更新function,它仍然是在正确的点级别,它只是增加速度 – 你可以添加另一个variables跟踪,如果你准备增加

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