Currently my general logic for anything from turrets to fully mobile units is to do the movement as pay of the logic so can act of it. E.g. a simple form of the turret logic might be:
update_turret ()
{
if (!_target || ! can_hit_target ())
select_target();
if (!_target) // give up
{
turn_towards(_idle_dir); //actually move
}
else
{
auto wanted_dir = direction(_pos, _target->pos());
turn_towards(wanted_dir);
if (_dir == wanted_dir) // move
shoot();
}
}
Where `turn_towards` considers the current and desired direction, max turn rate, etc.
For fully mobile units there are a bunch of methods mostly calling a `move_speed(speed, direction)` to try and turn and accelerate to a desired speed and direction.
This seems to work OK, but it scatters the actual movement around generally between some kind of pick target or destination logic, and deciding on shooting or other actions. And I had a few bugs because of that scattering, call the move function multiple times and break the speed limits, not call it at all on some path and it will instantly stop, both while still having a velocity value that now doesn't match. A `has_moved` flag fixes this.
So is this a good approach or am I just don't a hole with it?
I did consider having the AI just set a “desired speed” and “desired direction” and let a physics loop actually do that. But then not sure how to handle the second part of the logic. Loop over all such entities another time? But then all units including the target have moved, so things like `dir == wanted_dir` need some tolerance to account for that, and at close range change of angle due to movement could be fast higher than at longer distances.