如果你是通过物理移动石头,那么在石头生成后你应该施加更强的冲力/力(基于当前等级)如果你用动作移动它们,那么改变动作的速度,或者降低 moveDuration .如果您通过在 update: 方法中更改其位置来移动石头,则更改指示精灵在每次更新调用中应移动多少点的值。
要实现生成石头等基于时间的操作或决定何时更改生成节点的速度,您应该使用 SKAction 或 update: 方法及其传递的名为 currentTime 的参数。在 SpriteKit 中使用 NSTimer 可能会导致问题,因为 NSTimer 不尊重视图、场景或节点的暂停状态,因此最好避免使用它。
这是一个示例,说明如何使用SKAction 做你想做的事。在此示例中,您可以了解如何:
- 跟踪经过的秒数
- 维护当前等级信息
- 随机延迟生成节点
- 使用操作键停止生成节点
- 可能还有更多
GameScene.h
#import "GameScene.h"
@interface GameScene()
@property (nonatomic, assign) NSInteger counter;
@property (nonatomic, assign) NSInteger level;
@property (nonatomic, strong) SKLabelNode *debug;
@end
@implementation GameScene
// Here we set initial values of counter and level. Debug label is created here as well.
-(void)didMoveToView:(SKView *)view {
self.counter = 0;
self.level = 1;
self.backgroundColor = [SKColor grayColor];
self.debug = [SKLabelNode labelNodeWithFontNamed:@"ArialMT"];
self.debug.fontColor = [SKColor purpleColor];
self.debug.fontSize = 30.0f;
self.debug.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
self.debug.text = [NSString stringWithFormat:@"Counter : [ %ld ], Level [ %ld ]", (long)self.counter,(long)self.level];
[self addChild:self.debug];
}
//Method to start a timer. SKAction is used here to track a time passed and to maintain current level
-(void)startTimer{
__weak typeof (self) weakSelf = self; //make a weak reference to scene to avoid retain cycle
SKAction *block = [SKAction runBlock:^{
weakSelf.counter++;
//Maintaining level
if(weakSelf.counter < 5){
//level 1
weakSelf.level = 1;
}else if(weakSelf.counter >=5 && weakSelf.counter <10){
//level 2
weakSelf.level = 2;
}else{
//level 3
weakSelf.level = 3;
}
weakSelf.debug.text =
[NSString stringWithFormat:@"Counter : [ %ld ], Level [ %ld ]", (long)weakSelf.counter,(long)weakSelf.level];
}];
[self runAction:[SKAction repeatActionForever:[SKAction sequence:@[[SKAction waitForDuration:1], block]]] withKey:@"counting"];
}
//Method for stopping timer and reseting everything to default state.
-(void)stopTimer{
if([self actionForKey:@"counting"]){
[self removeActionForKey:@"counting"];
}
self.counter = 0.0f;
self.level = 1;
self.debug.text =
[NSString stringWithFormat:@"Counter : [ %ld ], Level [ %ld ]", (long)self.counter,(long)self.level];
}
//Get current speed based on time passed (based on counter variable)
-(CGFloat)getCurrentSpeed{
if(self.counter < 5){
//level 1
return 1.0f;
}else if(self.counter >=5 && self.counter <10){
//level 2
return 2.0f;
}else{
//level 3
return 3.0f;
}
}
//Method which stop generating stones, called in touchesBegan
-(void)stopGeneratingStones{
if([self actionForKey:@"spawning"]){
[self removeActionForKey:@"spawning"];
}
}
//You can use this useful method to generate random float between two numbers
- (CGFloat)randomFloatBetween:(CGFloat)smallNumber and:(CGFloat)bigNumber {
CGFloat diff = bigNumber - smallNumber;
return (((CGFloat) (arc4random() % ((unsigned)RAND_MAX + 1)) / RAND_MAX) * diff) + smallNumber;
}
//Method for generating stones, you run this method when you want to start spawning nodes (eg. didMoveToView or when some button is clicked)
-(void)generateStones{
SKAction *delay = [SKAction waitForDuration:2 withRange:0.5]; //randomizing delay time
__weak typeof (self) weakSelf = self; //make a weak reference to scene to avoid retain cycle
SKAction *block = [SKAction runBlock:^{
SKSpriteNode *stone = [weakSelf spawnStoneWithSpeed:[weakSelf getCurrentSpeed]];
stone.zPosition = 20;
[weakSelf addChild:stone];
}];
[self runAction:[SKAction repeatActionForever:[SKAction sequence:@[delay, block]]] withKey:@"spawning"];
}
//Returns stone with moving action added. Inside, you set standard things, like size, texture, physicsbody, name and position of a stone
-(SKSpriteNode*)spawnStoneWithSpeed:(CGFloat)stoneSpeed{
CGSize stoneSize = CGSizeMake(30,30); //you can randomize size here
CGPoint stonePosition = CGPointMake( [self randomFloatBetween:0.0f and:self.frame.size.width], CGRectGetMaxY(self.frame)); //you can randomize position here
SKSpriteNode *stone = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:stoneSize];
stone.name = @"stone"; //this helps if you want to enumerate all stones by name later on in your game
stone.position = stonePosition;
SKAction *move = [SKAction moveByX:0 y:-200 duration:3.25];
//one way to change speed
move.speed = stoneSpeed;
SKAction *moveAndRemove = [SKAction sequence:@[move, [SKAction removeFromParent]]];
[stone runAction:moveAndRemove withKey:@"moving"]; //access this key if you want to stop movement
return stone;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
//just a simple way to start and stop a game
if(![self actionForKey:@"counting"]){
[self startTimer];
[self generateStones];
}else{
[self stopTimer];
[self stopGeneratingStones];
}
}
@end
结果如下:
现在由您决定如何设置速度。你可以玩这个。
如果你想跳过某些部分,或者你不知道去哪里看,一切的核心都在名为generateStones的方法中,这就是你可以使用SKActions产生延迟石头的方法。另一个重要的方法是spawnStoneWithSpeed:,您可以在其中看到如何以动作的速度进行操作。
另一种影响节点移动速度的方法,正如我所说,是改变方法moveByX: duration:的持续时间参数
希望这会有所帮助!