import Vector from '../../math/Vector'; import RayConfiguration from '../utils/RayConfiguration'; import RaycastCollisionDetector from '../../utils/RaycastCollisionDetector'; import Limiter from '../Limiter'; import Steerable from '../Steerable'; import SteeringAcceleration from '../SteeringAcceleration'; import SteeringBehavior from '../SteeringBehavior'; /** * With the {@code RaycastObstacleAvoidance} the moving agent (the owner) casts one or more rays out in the direction of its * motion. If these rays collide with an obstacle, then a target is created that will avoid the collision, and the owner does a * basic seek on this target. Typically, the rays extend a short distance ahead of the character (usually a distance corresponding * to a few seconds of movement). *

* This behavior is especially suitable for large-scale obstacles like walls. *

* You should use the {@link RayConfiguration} more suitable for your game environment. Some basic ray configurations are provided * by the framework: {@link SingleRayConfiguration}, {@link ParallelSideRayConfiguration} and * {@link CentralRayWithWhiskersConfiguration}. There are no hard and fast rules as to which configuration is better. Each has its * own particular idiosyncrasies. A single ray with short whiskers is often the best initial configuration to try but can make it * impossible for the character to move down tight passages. The single ray configuration is useful in concave environments but * grazes convex obstacles. The parallel configuration works well in areas where corners are highly obtuse but is very susceptible * to the corner trap. *

* *

The corner trap

All the basic configurations for multi-ray obstacle avoidance can suffer from a crippling problem * with acute angled corners (any convex corner, in fact, but it is more prevalent with acute angles). Consider a character with * two parallel rays that is going towards a corner. As soon as its left ray is colliding with the wall near the corner, the * steering behavior will turn it to the left to avoid the collision. Immediately, the right ray will then be colliding the other * side of the corner, and the steering behavior will turn the character to the right. The character will repeatedly collide both * sides of the corner in rapid succession. It will appear to home into the corner directly, until it slams into the wall. It will * be unable to free itself from the trap. *

* The fan structure, with a wide enough fan angle, alleviates this problem. Often, there is a trade-off, however, between * avoiding the corner trap with a large fan angle and keeping the angle small to allow the character to access small passages. At * worst, with a fan angle near PI radians, the character will not be able to respond quickly enough to collisions detected on its * side rays and will still graze against walls. There are two approaches that work well and represent the most practical * solutions to the problem: *

* It seems that the most practical solution is to use adaptive fan angles, with one long ray cast and two shorter whiskers. * * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface * * @author davebaol */ declare class RaycastObstacleAvoidance> extends SteeringBehavior { /** The inputRay configuration */ protected rayConfiguration: RayConfiguration; /** The collision detector */ protected raycastCollisionDetector: RaycastCollisionDetector; /** The minimum distance to a wall, i.e. how far to avoid collision. */ protected distanceFromBoundary: number; private outputCollision; private minOutputCollision; /** * Creates a {@code RaycastObstacleAvoidance} behavior. * @param owner the owner of this behavior * @param rayConfiguration the ray configuration * @param raycastCollisionDetector the collision detector * @param distanceFromBoundary the minimum distance to a wall (i.e., how far to avoid collision). */ constructor(owner: Steerable, rayConfiguration?: RayConfiguration, raycastCollisionDetector?: RaycastCollisionDetector, distanceFromBoundary?: number); /** Returns the ray configuration of this behavior. */ getRayConfiguration(): RayConfiguration; /** * Sets the ray configuration of this behavior. * @param rayConfiguration the ray configuration to set * @return this behavior for chaining. */ setRayConfiguration(rayConfiguration: RayConfiguration): RaycastObstacleAvoidance; /** Returns the raycast collision detector of this behavior. */ getRaycastCollisionDetector(): RaycastCollisionDetector; /** * Sets the raycast collision detector of this behavior. * @param raycastCollisionDetector the raycast collision detector to set * @return this behavior for chaining. */ setRaycastCollisionDetector(raycastCollisionDetector: RaycastCollisionDetector): RaycastObstacleAvoidance; /** Returns the distance from boundary, i.e. the minimum distance to an obstacle. */ getDistanceFromBoundary(): number; /** * Sets the distance from boundary, i.e. the minimum distance to an obstacle. * @param distanceFromBoundary the distanceFromBoundary to set * @return this behavior for chaining. */ setDistanceFromBoundary(distanceFromBoundary: number): RaycastObstacleAvoidance; setOwner(owner: Steerable): RaycastObstacleAvoidance; setEnabled(enabled: boolean): RaycastObstacleAvoidance; /** * Sets the limiter of this steering behavior. The given limiter must at least take care of the maximum linear acceleration. * @return this behavior for chaining. */ setLimiter(limiter: Limiter): RaycastObstacleAvoidance; protected calculateRealSteering(steering: SteeringAcceleration): SteeringAcceleration; } export default RaycastObstacleAvoidance;