延迟拍摄,同时触摸移动"

时间:2014-03-28 02:59:50

标签: ios timer cocos2d-iphone delay

我需要为英雄制造射击延迟。因此,当用户触摸屏幕并移动他们的手指时,英雄将开始射击,但每次射击之间将持续延迟。

所以要明确:

user touches screen 
timer begins 
timer reached 
hero fires 
timer resets
timer reached hero fires

我的第一个想法是使用performSelector / dispatch。但在使用调度后,我意识到它会阻塞块调用,并在达到延迟后将其关闭。 (我是新来的派遣人员)

所以现在我的想法是创建一些计时器变量并调用" fire"到达计时器时起作用。当用户触摸屏幕时,计时器启动。

我只是在寻找最佳方法,因为使用计时器变量可能会非常混乱。你有什么想法?

1 个答案:

答案 0 :(得分:1)

似乎可以通过有限状态机(FSM)很好地解决这个问题。您有几种状态,进入/退出它们的条件,以及明确定义的行为。

我将下面的图表放在一起,向您展示我正在考虑的模型:

enter image description here

注意:

  1. 每个州都有一个" Enter"和"执行"操作
  2. " ticks"变量是一个整数计数器。将其设置为"更新"当您进入需要它的状态时,您想要等待在Enter功能中触发子弹(例如60刻度= 1秒)的周期("点火开始延迟"和" Inter Fire Delay&#34你根据你对该状态的需要为状态设置不同的东西。然后在Execute函数中为它使用它的状态减去它。
  3. 或者,您可以使用机器时间(如秒表)并将其与进入状态的时间进行比较。这会让你摆脱FPS与#34;时间"。
  4. 的关系
  5. 有四种基本方法可以实现简单的FSM(无需进入异乎寻常的预构建解决方案或宏)。在这种情况下,我会使用switch语句(见下文)。
  6. 在场景更新调用中调用ExecuteState(...)函数(或以其他方式安排)。
  7. 一些示例代码:

    typedef enum
    {
       IDLE,
       FINGER_DOWN,
       FIRING_START_DELAY,
       FIRE_BULLET,
       INTER_FIRE_DELAY,
    } FIRING_STATE;
    
    
    // Class Variables:
    FIRING_STATE _firingState = IDLE;
    int _ticks = 0;
    bool _fingerDown = false;
    
    const int FRAMES_PER_SECOND = 60;
    const float FIRING_START_DELAY_SECONDS = 1.5f;
    const float INTER_FIRE_DELAY_SECONDS = 0.5;
    
    void EnterState(FIRING_STATE firingState);
    void ExecuteState(FIRING_STATE firingState);
    void ChangeState(FIRING_STATE firingState);
    
    void EnterState(FIRING_STATE firingState)
    {
       switch(firingState)
       {
          case IDLE:
             break;
          case FINGER_DOWN:
             break;
          case FIRING_START_DELAY:
             // NOTE: You may change/start an animation or
             // play a sound here to give some feedback
             // to the player.
             _ticks = FIRING_START_DELAY_SECONDS*FRAMES_PER_SECOND;
             break;
          case FIRE_BULLET:
             break;
          case INTER_FIRE_DELAY:
             _ticks = INTER_FIRE_DELAY_SECONDS*FRAMES_PER_SECOND;
             break;
       }
    }
    
    void ExecuteState(FIRING_STATE firingState)
    {
       // If the counter is running, decrement it.
       if(_ticks > 0)
       {
          _ticks--;
       }
       switch(firingState)
       {
          case IDLE:
             if(_fingerDown)
             {
                ChangeState(FINGER_DOWN);
             }
             break;
          case FINGER_DOWN:
             if(!_fingerDown)
             {
                ChangeState(IDLE);
             }
             else
             {
    
                ChangeState(FIRING_START_DELAY);
             }
             break;
          case FIRING_START_DELAY:
             if(_ticks == 0)
             {  //  Move on to next state
                ChangeState(FIRE_BULLET);
             }
             if(!_fingerDown)
             {
                ChangeState(IDLE);
             }
             break;
          case FIRE_BULLET:
             if(!_fingerDown)
             {
                ChangeState(IDLE);
             }
             ChangeState(INTER_FIRE_DELAY);
             break;
          case INTER_FIRE_DELAY:
             if(_ticks == 0)
             {  //  Move on to next state
                ChangeState(FIRE_BULLET);
             }
             if(!_fingerDown)
             {
                ChangeState(IDLE);
             }
             break;
       }
    }
    
    void ChangeState(FIRING_STATE firingState)
    {
       EnterState(firingState);
       _firingState = firingState;
       ExecuteState(firingState);
    }