Objective-c:在再次调用函数之前设置超时/延迟

时间:2014-08-19 06:02:00

标签: objective-c cocos2d-iphone timeout delay wait

我试图制作一个cocos2D游戏,每次玩家触摸屏幕时,背景向左滚动,从而模拟向前移动。

"背景"由2个非常长的矩形面板组成,称为pane1和pane2链接在一起。触摸屏幕时,我使用CCActionMoveTo将两个窗格向左移动,当一个窗格完全离开屏幕时,我将其向后移动到另一侧以创建无限循环。

问题是背景滚动动画需要0.2秒,如果播放器只是屏蔽了很多屏幕,它就会弄乱一切。并且,有时这两个窗格经历不同的滞后量,以便它们不同步。

如何在函数上设置延迟,以便每个指定时间段只能调用一次?换句话说,我想添加一个"冷却时间"处理玩家触摸的功能。

每次触摸场景时都会调用此函数:

- (void)playerMove {

    CCActionMoveTo * actionMove1 =  [CCActionEaseOut actionWithAction:
                                    [CCActionMoveTo actionWithDuration:.2
                                                   position:ccp(pane1.position.x - 150, 0)]
                                                   rate: 1.5];


    CCActionMoveTo * actionMove2 =  [CCActionEaseOut actionWithAction:
                                    [CCActionMoveTo actionWithDuration:.2
                                                    position:ccp(pane2.position.x - 150, 0)]
                                                    rate: 1.5];

    CCActionCallFunc * actionCallGenerateTerrain = [CCActionCallFunc actionWithTarget: self selector:@selector(generateTerrain)];

    counter++;

    if(pane1InUse){
        [pane1 runAction: [CCActionSequence actionWithArray:@[actionMove1, actionCallGenerateTerrain]]];
        [pane2 runAction: actionMove2];
    }
    else
    {
        [pane1 runAction: actionMove1];
        [pane2 runAction: [CCActionSequence actionWithArray:@[actionMove2, actionCallGenerateTerrain]]];
    }
}

-(void) generateTerrain {
    if (counter%8 == 0){

        pane1InUse ^= YES;

        CCLOG(@"%@", pane1InUse ? @"YES" : @"NO");

        if (pane1InUse){
            CCLOG(@"Generating Terrain 2 ...");
            pane2.position = ccp(pane1.position.x+pane1.boundingBox.size.width, 0);
        }
        else{
            CCLOG(@"Generating Terrain 1 ...");
            pane1.position = ccp(pane2.position.x+pane2.boundingBox.size.width, 0);
        }
    }

}

你也可能已经注意到我使用了这个奇怪的代码块,因为理想情况下我希望同时执行actionMove1和actionMove2,一旦完成它们,然后执行actionCallGenerateTerrain,但我不会知道如何实现:

if(pane1InUse){
    [pane1 runAction: [CCActionSequence actionWithArray:@[actionMove1, actionCallGenerateTerrain]]];
    [pane2 runAction: actionMove2];
}
else
{
    [pane1 runAction: actionMove1];
    [pane2 runAction: [CCActionSequence actionWithArray:@[actionMove2, actionCallGenerateTerrain]]];
}

}

2 个答案:

答案 0 :(得分:1)

您可能希望将pane1和pane2放在ccNode中,将其称为combinedPanes(这将使pane1和pane2始终同步移动)。然后对combinedPane执行单个操作。还要添加一个布尔状态属性,将其命名为moveEnabled;

id movePane = [CCActionMoveTo ... ]; // whatever you have for pane1 or pane2
id moveComplete = [CCActionBlock actionWithBlock:^{
    [self generateTerrain];
    self.moveEnabled = YES;
}];

self.moveEnabled = NO;
[movePane runAction:[CCActionSequence actions:movePane,moveComplete,nil]];

并使用moveEnabled来允许/拒绝检测到触摸并触发此移动代码的触摸处理。在移动过程中,这会触动并有效地阻止你的歇斯底里用户像坚果一样敲击。

-(void) playerMove {
    if (self.moveEnabled){
        //
        // the rest of your logic
        //        ...
    }
}

并在init中(或者如果您已经检测到这种情况,请将其放在那里)。

self.moveEnabled =  YES;    

答案 1 :(得分:0)

防止函数在一段时间内被调用两次的一种简单方法是将其包装在if语句中,如:

if ([[NSDate date] timeIntervalSinceDate:lastUpdated] > minDelay)
{
    // call function here    

    lastUpdated = [NSDate date];
}

其中lastUpdated使用[NSDate date]初始化,minDelay是所需的最小延迟(以秒为单位)。