Comment accélérer un jeu Sprite Kit après chaque 50 points supplémentaires

Je fais un jeu en 2D avec Sprite Kit et j'ai besoin d'append une méthode pour accélérer le jeu après 50 points.

J'ai mis au point une méthode qui ajoute la vitesse voulue, mais je dois copyr, coller et ajuster une instruction if dans la méthode de mise à jour pour chaque 50 points supplémentaires.

Un autre problème avec ma solution est que je dois augmenter mes points juste après l'avoir accéléré, sinon le jeu accélérera complètement, bien que je ne sache pas pourquoi.

Voici ma solution jusqu'à présent:

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

Je voudrais implémenter cette fonctionnalité sans être obligé de faire tous les incréments manuellement et sans que le jeu accélère sans incréments de points.

Manière rapide

Vous pouvez utiliser l'observateur de propriétés de didSet pour modifier la vitesse de jeu en fonction du score actuel:

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

De la docs:

didSet est appelé immédiatement après le stockage de la nouvelle valeur.

Ainsi, immédiatement après la définition du nouveau score, vous devez mettre à jour la variable gameSpeed .

Voie Objective-C

En Objective-C, rien de tel ne peut fournir exactement le même comportement que les observateurs de propriété de swift, doSet et willSet. Mais il existe d'autres moyens, par exemple vous pouvez replace le setter d'une partition, comme ceci:

 #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 = [NSSsortingng ssortingngWithFormat:@"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 = [NSSsortingng ssortingngWithFormat:@"Score : %lu, Speed %f", self.score, self.gameSpeed]; } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { self.score++; } @end 

Ou, je suppose, vous pouvez faire la même chose en utilisant KVO , mais pour votre exemple en raison de la simplicité, vous pouvez simplement replace un setter. Ou peut-être pourriez-vous simplement créer une méthode personnalisée qui augmentera le score, gérer la logique de mise à jour de gameSpeed ​​et mettre à jour la vitesse si nécessaire:

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

Ainsi, vous aurez une définition de méthode supplémentaire, qui doit être appelée quand le joueur marque, en comparaison avec ceci (en supposant que le setter de la partition soit surchargé):

 self.score = someScore; 

C'est vraiment comme tu veux.

J'espère que cela a du sens et ça aide!

MODIFIER:

J'ai changé le initWithSize: en initWithCoder , car initWithSize n'est pas appelé lorsque la scène est chargée à partir de sks, ce qui est probablement la façon dont vous le faites, car la scène Xcode 7 est chargée par défaut à partir du file .sks.

Si vous voulez mettre à jour la vitesse à intervalles réguliers, vous pouvez utiliser l'opérateur de module – prenez le rest après la division par votre intervalle – si cela est égal à zéro, passez à l'action. La raison pour laquelle le jeu accélère complètement est que la prochaine fois que la fonction de mise à jour est activée, elle est toujours au bon niveau et augmente la vitesse. Vous pouvez append une autre variable à suivre si vous êtes prêt pour un incrément.

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