public override void Run(float deltaTime) { float angle = 0.0f; // NOTE: since MonoAGS has Y axis pointing up, we need to invert the lookup array's Y index float x = _veh.Position.X; float y = _veh.Position.Y; y = _regionMask.Height - y; Color color = _regionMask.GetPixel((int)Math.Round(x), (int)Math.Round(y)); _regionAngles.TryGetValue(color, out angle); // Steering _targetAngle = angle; float dirAngle = _veh.Direction.Angle(); float angleBetween = MathEx.AnglePiFast(_targetAngle - MathEx.Angle2Pi(dirAngle)); // HACK: reduce "jittering" when AI is trying to follow strict direction: // if the necessary angle is very close to the angle car will turn in one tick, then just adjust yourself float steeringDT = SteeringAngle * deltaTime * 1.1f; if (Math.Abs(angleBetween) <= Math.Abs(steeringDT)) { _veh.SteeringWheelAngle = 0.0f; _veh.Direction = Vectors.Rotate(new Vector2(1.0f, 0.0f), _targetAngle); } // ...otherwise turn properly, without cheating else if (angleBetween > 0.0f) { _veh.SteeringWheelAngle = SteeringAngle; } else if (angleBetween < 0.0f) { _veh.SteeringWheelAngle = -SteeringAngle; } else { _veh.SteeringWheelAngle = 0.0f; } // Always accelerating _veh.Accelerator = 1.0f; _veh.Brakes = 0.0f; }
private bool testShouldChooseNewTarget() { if (!_targetValid) { return(true); } // Choose next path node if inside the check radius for current one, or closer to next one. if (_currentNode != null) { AIPathNode prevNode = _currentNode.prev; AIPathNode nextNode = _currentNode.next; if (nextNode != null && (prevNode == null || Vectors.Distance(_veh.Position, prevNode.pt) > Vectors.Distance(_currentNode.pt, prevNode.pt)) && Vectors.Distance(_veh.Position, nextNode.pt) < Vectors.Distance(_currentNode.pt, nextNode.pt)) { return(true); } } return(Vectors.Distance(_veh.Position, _targetPos) <= _targetCheckRadius); }