private void TargetClosestNode(Vector3 pos) { OpponentPathNode curNode = _targetNode; TargetNode(OpponentController.GetClosestNode(pos)); _currentPath = null; if (curNode == _targetNode) //if the closest node is the one we've failed to get to { // if we've failed to get to the target twice we're really stuck, teleport straight to node :) Teleport(_targetNode); return; } GameConsole.WriteEvent("ClosestNode"); _nbrFails++; }
//public static OpponentPathNode GetClosestRaceNode(Vector3 currentPosition) //{ // float leastDistance = int.MaxValue; // OpponentPathNode leastDistantNode = null; // foreach (OpponentPathNode node in Nodes) // { // float thisDistance = Vector3.Distance(currentPosition, node.Position); // if (thisDistance < leastDistance) // { // if (node.Paths.Exists(a => a.Type == PathType.Race)) // { // leastDistance = thisDistance; // leastDistantNode = node; // } // } // } // return leastDistantNode; //} public static OpponentPath GetClosestPath(Vector3 point) { float closestDist = float.MaxValue; OpponentPath closestPath = null; foreach (OpponentPathNode node in Nodes) { foreach (OpponentPath path in node.Paths) { Vector3 closestPoint = Helpers.GetClosestPointOnLine(path.Start.Position, path.End.Position, point); float dist = Vector3.Distance(point, closestPoint); if (dist < closestDist) { closestPath = path; closestDist = dist; } } } return(closestPath); }
public virtual void Update() { if (!_raceStarted) return; Vector3 pos = Vehicle.Position; bool isBraking = false; if (IsDead || _state == CpuDriverState.Sleeping) { Vehicle.Chassis.Brake(0); Vehicle.Chassis.Steer(0); return; } if (DistanceFromPlayer > _catchupDistance) { _catchupDistance = Engine.Random.Next(MIN_CATCHUP_DISTANCE, MAX_CATCHUP_DISTANCE); Teleport(OpponentController.GetNodeCloseToPlayer()); } // check position if (Helpers.HasTimePassed(1.5f, _lastPositionTime)) { float distFromLastPosition = Vector3.Distance(_lastPosition, pos); if (distFromLastPosition < 2 && Vehicle.Chassis.Speed < 3) { Escape(); //were stuck, try and escape } LogPosition(pos); } if (Vehicle.Chassis.Actor.GlobalPose.Up.Y < 0.002f && Vehicle.Chassis.Speed < 5 && !InPlayersView) { Vehicle.Chassis.Reset(); return; } // check for state change if (_nextDirectionChangeTime < Engine.TotalSeconds) { if (_isReversing) { _isReversing = false; LogPosition(pos); } } float distanceFromNode=0; if (_state == CpuDriverState.Racing) distanceFromNode = Vector3.Distance(pos, _targetNode.Position); else if (_state == CpuDriverState.ReturningToTrack) distanceFromNode = Vector3.Distance(pos, _closestPointOnPath); // if we've been trying to get to the same target for 20 seconds, get a new one if (_state != CpuDriverState.Attacking && Helpers.HasTimePassed(20, _lastTargetChangeTime)) { if (_lastDistance <= distanceFromNode) //only get another node if were not getting closer { TargetClosestNode(pos); return; } } if (_state == CpuDriverState.Racing) { //if (_currentPath != null) //{ // GameConsole.WriteLine("Limits " + _currentPath.Number + ", " + _currentPath.MinSpeedAtEnd + ", " + _maxSpeedAtEndOfPath); //} if (_currentPath != null && Vehicle.Chassis.Speed > _maxSpeedAtEndOfPath) { float distToBrake = Vehicle.Chassis.Speed * 0.45f + ((Vehicle.Chassis.Speed - _maxSpeedAtEndOfPath) * 1.4f); //GameConsole.WriteLine("brake: " + (int)distToBrake + ", " + (int)distanceFromNode); //Matrix mat = Matrix.CreateTranslation(0, 0, distToBrake) * Vehicle.Chassis.Actor.GlobalPose; if (distToBrake >= distanceFromNode) { Vehicle.Chassis.Brake(1); isBraking = true; } } if (_currentPath != null) { _closestPointOnPath = Helpers.GetClosestPointOnLine(_currentPath.Start.Position, _currentPath.End.Position, pos); _closestPointOnPath.Y = pos.Y; //ignore Y if (Vector3.Distance(_closestPointOnPath, pos) > _currentPath.Width) { SetState(CpuDriverState.ReturningToTrack); } } // now see if we're at the target ignoring height (if we jump over it for example) distanceFromNode = Vector2.Distance(new Vector2(pos.X, pos.Z), new Vector2(_targetNode.Position.X, _targetNode.Position.Z)); if (distanceFromNode < 11 && pos.Y >= _targetNode.Position.Y) { _nbrFails = 0; //reset fail counter if (_currentPath != null) { if (Vehicle.Chassis.Speed < _currentPath.MinSpeedAtEnd) { Vehicle.Chassis.Boost(); } } _currentPath = _nextPath; if (_currentPath != null && _currentPath.Type == PathType.Cheat) { Teleport(_currentPath.End); SetState(CpuDriverState.Racing); return; } if (_nextPath == null) // the node didnt have any start paths { TargetClosestNode(pos); } else { TargetNode(_currentPath.End); } if (_currentPath == null && _nextPath == null) { Teleport(); //if the node we've just got to doesnt have any outgoing paths, teleport randomly } } } else if (_state == CpuDriverState.ReturningToTrack) { _closestPointOnPath = Helpers.GetClosestPointOnLine(_currentPath.Start.Position, _currentPath.End.Position, pos); GameConsole.WriteLine("dist from track", Vector3.Distance(_closestPointOnPath, pos)); if (Vector3.Distance(_closestPointOnPath, pos) > GIVEUP_DISTANCE_FROM_TRACK) { TargetClosestNode(pos); return; } _closestPointOnPath.Y = pos.Y; //ignore Y float dist = Vector3.Distance(_closestPointOnPath, pos); if (dist < _currentPath.Width) { _state = CpuDriverState.Racing; } else if (dist < _currentPath.Width * 1.5f) { _closestPointOnPath = Vector3.Lerp(_currentPath.End.Position, _closestPointOnPath, dist / (_currentPath.Width * 1.5f)); } //Engine.DebugRenderer.AddCube(Matrix.CreateTranslation(_closestPointOnPath), Color.Blue); } else if (_state == CpuDriverState.Attacking) { if (DistanceFromPlayer > GIVEUP_ATTACK_DISTANCE) TargetClosestNode(pos); } Vector3 towardsNode = Vector3.Zero; if (_state == CpuDriverState.Racing) { towardsNode = _targetNode.Position - pos; } else if (_state == CpuDriverState.Attacking) { towardsNode = Race.Current.PlayerVehicle.Position - pos; } else if (_state == CpuDriverState.ReturningToTrack) { towardsNode = _closestPointOnPath - pos; } GameConsole.WriteLine("state: " + _state); float angle = Helpers.GetSignedAngleBetweenVectors(Vehicle.Chassis.Actor.GlobalOrientation.Forward, towardsNode, true); angle *= 1.5f; if (angle > 1) angle = 1; else if (angle < -1) angle = -1; if (Math.Abs(angle) > 0.003f) Vehicle.Chassis.Steer(angle); if (!isBraking) { if (_state == CpuDriverState.ReturningToTrack) { if (Math.Abs(angle) > 0.3f) { float speed = 20; // 20 + ((1 - Math.Abs(angle)) * 30); if (Vehicle.Chassis.Speed > speed) Vehicle.Chassis.Brake(1); else Vehicle.Chassis.Accelerate(0.4f); GameConsole.WriteLine("rtt", angle); GameConsole.WriteLine("rttspeed", speed); } else Vehicle.Chassis.Accelerate(0.5f); } else { if (Math.Abs(angle) > 0.7f) Vehicle.Chassis.Accelerate(0.5f); //if were turning hard, go easy on the gas pedal else Vehicle.Chassis.Accelerate(1.0f); } } _lastDistance = distanceFromNode; if (_isReversing) { Vehicle.Chassis.Brake(0.3f); Vehicle.Chassis.Steer(_reverseTurning); } if (Vehicle.Chassis.Motor.Gearbox.CurrentGear == 0) Vehicle.Chassis.Motor.Gearbox.CurrentGear = 1; //Engine.DebugRenderer.AddWireframeCube(Matrix.CreateScale(2) * Matrix.CreateTranslation(_targetNode.Position), Color.Green); }
public virtual void Update() { if (!_raceStarted) { return; } Vector3 pos = Vehicle.Position; bool isBraking = false; if (IsDead || _state == CpuDriverState.Sleeping) { Vehicle.Chassis.Brake(0); Vehicle.Chassis.Steer(0); return; } if (DistanceFromPlayer > _catchupDistance) { _catchupDistance = GameEngine.Random.Next(MIN_CATCHUP_DISTANCE, MAX_CATCHUP_DISTANCE); Teleport(OpponentController.GetNodeCloseToPlayer()); } // check position if (Helpers.HasTimePassed(1.5f, _lastPositionTime)) { float distFromLastPosition = Vector3.Distance(_lastPosition, pos); if (distFromLastPosition < 2 && Vehicle.Chassis.Speed < 3) { Escape(); //were stuck, try and escape } LogPosition(pos); } if (Vehicle.Chassis.Actor.GlobalPose.Up.Y < 0.002f && Vehicle.Chassis.Speed < 5 && !InPlayersView) { Vehicle.Chassis.Reset(); return; } // check for state change if (_nextDirectionChangeTime < GameEngine.TotalSeconds) { if (_isReversing) { _isReversing = false; LogPosition(pos); } } float distanceFromNode = 0; if (_state == CpuDriverState.Racing) { distanceFromNode = Vector3.Distance(pos, _targetNode.Position); } else if (_state == CpuDriverState.ReturningToTrack) { distanceFromNode = Vector3.Distance(pos, _closestPointOnPath); } // if we've been trying to get to the same target for 20 seconds, get a new one if (_state != CpuDriverState.Attacking && Helpers.HasTimePassed(20, _lastTargetChangeTime)) { if (_lastDistance <= distanceFromNode) //only get another node if were not getting closer { TargetClosestNode(pos); return; } } if (_state == CpuDriverState.Racing) { //if (_currentPath != null) //{ // GameConsole.WriteLine("Limits " + _currentPath.Number + ", " + _currentPath.MinSpeedAtEnd + ", " + _maxSpeedAtEndOfPath); //} if (_currentPath != null && Vehicle.Chassis.Speed > _maxSpeedAtEndOfPath) { float distToBrake = Vehicle.Chassis.Speed * 0.45f + ((Vehicle.Chassis.Speed - _maxSpeedAtEndOfPath) * 1.4f); //GameConsole.WriteLine("brake: " + (int)distToBrake + ", " + (int)distanceFromNode); //Matrix mat = Matrix.CreateTranslation(0, 0, distToBrake) * Vehicle.Chassis.Actor.GlobalPose; if (distToBrake >= distanceFromNode) { Vehicle.Chassis.Brake(1); isBraking = true; } } if (_currentPath != null) { _closestPointOnPath = Helpers.GetClosestPointOnLine(_currentPath.Start.Position, _currentPath.End.Position, pos); _closestPointOnPath.Y = pos.Y; //ignore Y if (Vector3.Distance(_closestPointOnPath, pos) > _currentPath.Width) { SetState(CpuDriverState.ReturningToTrack); } } // now see if we're at the target ignoring height (if we jump over it for example) distanceFromNode = Vector2.Distance(new Vector2(pos.X, pos.Z), new Vector2(_targetNode.Position.X, _targetNode.Position.Z)); if (distanceFromNode < 11 && pos.Y >= _targetNode.Position.Y) { _nbrFails = 0; //reset fail counter if (_currentPath != null) { if (Vehicle.Chassis.Speed < _currentPath.MinSpeedAtEnd) { Vehicle.Chassis.Boost(); } } _currentPath = _nextPath; if (_currentPath != null && _currentPath.Type == PathType.Cheat) { Teleport(_currentPath.End); SetState(CpuDriverState.Racing); return; } if (_nextPath == null) // the node didnt have any start paths { TargetClosestNode(pos); } else { TargetNode(_currentPath.End); } if (_currentPath == null && _nextPath == null) { Teleport(); //if the node we've just got to doesnt have any outgoing paths, teleport randomly } } } else if (_state == CpuDriverState.ReturningToTrack) { _closestPointOnPath = Helpers.GetClosestPointOnLine(_currentPath.Start.Position, _currentPath.End.Position, pos); GameConsole.WriteLine("dist from track", Vector3.Distance(_closestPointOnPath, pos)); if (Vector3.Distance(_closestPointOnPath, pos) > GIVEUP_DISTANCE_FROM_TRACK) { TargetClosestNode(pos); return; } _closestPointOnPath.Y = pos.Y; //ignore Y float dist = Vector3.Distance(_closestPointOnPath, pos); if (dist < _currentPath.Width) { _state = CpuDriverState.Racing; } else if (dist < _currentPath.Width * 1.5f) { _closestPointOnPath = Vector3.Lerp(_currentPath.End.Position, _closestPointOnPath, dist / (_currentPath.Width * 1.5f)); } //GameEngine.DebugRenderer.AddCube(Matrix.CreateTranslation(_closestPointOnPath), Color.Blue); } else if (_state == CpuDriverState.Attacking) { if (DistanceFromPlayer > GIVEUP_ATTACK_DISTANCE) { TargetClosestNode(pos); } } Vector3 towardsNode = Vector3.Zero; if (_state == CpuDriverState.Racing) { towardsNode = _targetNode.Position - pos; } else if (_state == CpuDriverState.Attacking) { towardsNode = Race.Current.PlayerVehicle.Position - pos; } else if (_state == CpuDriverState.ReturningToTrack) { towardsNode = _closestPointOnPath - pos; } GameConsole.WriteLine("state: " + _state); float angle = Helpers.GetSignedAngleBetweenVectors(Vehicle.Chassis.Actor.GlobalOrientation.Forward, towardsNode, true); angle *= 1.5f; if (angle > 1) { angle = 1; } else if (angle < -1) { angle = -1; } if (Math.Abs(angle) > 0.003f) { Vehicle.Chassis.Steer(angle); } if (!isBraking) { if (_state == CpuDriverState.ReturningToTrack) { if (Math.Abs(angle) > 0.3f) { float speed = 20; // 20 + ((1 - Math.Abs(angle)) * 30); if (Vehicle.Chassis.Speed > speed) { Vehicle.Chassis.Brake(1); } else { Vehicle.Chassis.Accelerate(0.4f); } GameConsole.WriteLine("rtt", angle); GameConsole.WriteLine("rttspeed", speed); } else { Vehicle.Chassis.Accelerate(0.5f); } } else { if (Math.Abs(angle) > 0.7f) { Vehicle.Chassis.Accelerate(0.5f); //if were turning hard, go easy on the gas pedal } else { Vehicle.Chassis.Accelerate(1.0f); } } } _lastDistance = distanceFromNode; if (_isReversing) { Vehicle.Chassis.Brake(0.3f); Vehicle.Chassis.Steer(_reverseTurning); } if (Vehicle.Chassis.Motor.Gearbox.CurrentGear == 0) { Vehicle.Chassis.Motor.Gearbox.CurrentGear = 1; } //GameEngine.DebugRenderer.AddWireframeCube(Matrix.CreateScale(2) * Matrix.CreateTranslation(_targetNode.Position), Color.Green); }