逐渐提高SpriteKit对象的速度

时间:2015-09-16 09:43:23

标签: ios objective-c sprite-kit

我有一个简单的游戏,从屏幕的顶部到底部“下雨”。

我正在使用SpriteKit,我希望这些石头能够随着时间的推移而增加速度,就像1级2级3级一样。那么最大速度应该很容易实现。

我对石头的速度有一个变速“速度”。

我想我可以使用一个计时器,在5秒速度= 2之后,10秒速度= 5之后,依此类推,但我不确定如何实现它。

编辑:

我正用这个移动我的石头:

-(void) moveStones{
SKAction *actionMove = [SKAction moveByX:0 y:-5 duration:0.25];
for(SKSpriteNode *stone in self.stones)
{
    [stone runAction:actionMove];
}
}

在我的viewDidLoad中,我有计时器:

 moveStones = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(moveStones) userInfo:nil repeats:YES];

如果计时器不尊重视图,有没有办法在没有该计时器的情况下移动它们?

1 个答案:

答案 0 :(得分:2)

如果你是通过物理移动石头,那么在石头产生之后你应该施加更强的冲动/力(基于当前水平)如果你用动作移动它们,那么改变动作速度,或者降低moveDuration 。如果您通过在update:方法中更改其位置来移动石头,则更改指示精灵在每次更新调用中应移动多少点的值。

要实现基于时间的操作(如产生宝石)或决定何时更改生成节点的速度,您应该使用SKAction或update:方法及其传递的名为currentTime的参数。在SpriteKit中使用NSTimer可能会导致问题,因为NSTimer不尊重视图,场景或节点的暂停状态,因此最好避免使用它。

以下是有关如何使用SKAction执行所需操作的示例。在此示例中,您可以看到如何:

  • 跟踪传递的秒数
  • 维护有关当前级别的信息
  • 具有随机延迟的spawn节点
  • 使用操作键
  • 停止生成节点
  • 可能还有一些

<强> 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

结果如下:

spawning

现在由您决定如何设定速度。你可以玩那个。

如果你想跳过某些部分,或者你不知道在哪里看,那么所有内容的核心都是generateStones方法。这就是你如何通过使用SKActions产生时间延迟的石头。另一个重要的方法是spawnStoneWithSpeed:,您可以在其中看到如何以动作的速度进行操作。

正如我所说,另一种影响节点移动速度的方法是改变方法moveByX: duration:的持续时间参数

希望这有帮助!