Reputation: 621
I need to create a shooting delay for the hero. So as the user touches the screen and moves their fingers, the hero will begin shooting but there will be a continual delay between each shot fired.
So to be quite explicit:
user touches screen
timer begins
timer reached
hero fires
timer resets
timer reached hero fires
My first thoughts were to use a performSelector/dispatch. But after using dispatch I realised it queues up the block calls and fires them off after the delay has been reached. (i'm new to dispatch)
So now my thoughts are to create some timer variables and call the "fire" function when the timer has been reached. The timer starts when the user touches the screen.
I'm just looking for the best approach for this, as using timer variables can get quite messy. What are your thoughts?
Upvotes: 0
Views: 76
Reputation: 3397
It seems like this would be solved well with a finite state machine (FSM). You have several states, conditions for entering/exiting them, and well defined behaviors while in them.
I put together the diagram below to show you the model I am thinking about:
Notes:
Some Example Code:
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);
}
Upvotes: 1