【问题标题】:Objective-c : Set timeout / delay before function can be called againObjective-c:在函数可以再次调用之前设置超时/延迟
【发布时间】:2014-08-19 19:04:08
【问题描述】:

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

“背景”由两个非常长的矩形面板组成,称为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]]];
}

}

【问题讨论】:

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


    【解决方案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;    
    

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-23
        • 2020-10-21
        • 2018-11-24
        • 1970-01-01
        • 1970-01-01
        • 2014-01-03
        • 1970-01-01
        相关资源
        最近更新 更多