斯威夫特方式
可以使用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;
這真的取決於你。
希望這是有道理的,它有幫助!
編輯:
我已經改變了initWithSize:
到initWithCoder
,因爲當場景從SKS加載,這可能是你是如何做的,由於事實上initWithSize
不叫,在Xcode中7場景默認從.sks文件加載。
您可以向我提供目標c的didSet語法嗎? – ccdev
@codev哦,對不起,我沒有注意到Obj-C標籤。在Obj-C中,默認情況下沒有這樣的方法提供與willSet和didSet屬性觀察者完全相同的行爲......但還有其他方法可以實現類似的行爲。很快會更新我的答案。 – Whirlwind