diff --git a/site/docs/09-math/07-ray.mdx b/site/docs/09-math/07-ray.mdx index d6966beb5..271178494 100644 --- a/site/docs/09-math/07-ray.mdx +++ b/site/docs/09-math/07-ray.mdx @@ -6,6 +6,112 @@ section: Math [[Ray]]'s are a useful tool for testing if geometry intersects a line of sight with [[Collider.rayCast]]. You can think of them as a point in space with a direction. +Examples where ray casting can be useful +* Custom physics implementations (platformers, slopes, etc) +* Line of sight AI +* Proximity detection + +:::warning + +If you start a raycast from inside an [[Actor]] it will hit that Actor first unless you explicitly exclude it. See Raycast Options below. + +::: + +## Scene Testing + +It is possible to test against all actors in a [[Scene]] at once. + +```typescript + +// given a scene reference +const game = new ex.Engine({...}); +game.start(); + + +const ray = new ex.Ray(ex.vec(100, 100), ex.Vector.Right); +game.currentScene.physics.rayCast(ray, {...}); + +// or in a custom scene +class MyScene extends ex.Scene { + + someRayTestMethod() { + + const ray = new ex.Ray(ex.vec(100, 100), ex.Vector.Right); + this.physics.rayCast(ray, {...}); + } +} + +``` + +## Scene Raycast Options + +Excalibur's raycast can be optionally configured in a variety of ways. By default if no options are provided to the `rayCast(ray, ...)` the options will be + +```typescript +const hits = scene.physics.rayCast(ray, { + searchAllColliders: true, + collisionGroup: CollisionGroup.All, + collisionMask: CollisionGroup.All.mask, + ignoreCollisionGroupAll: false, + maxDistance: Infinity, + filter: null, +}) +``` + +### Search All Colliders + +By default the raycast will not stop after the first hit is found, if you'd like to only get the first hit set `searchAllColliders: false` + +### Max Distance + +Distance is in terms of pixels, this is the maximum length along the ray to search for colliders. + +### Hit Filtering + +Using the `filter` option you can do complex filtering logic to reject or accept potential hits. + +```typescript +scene.physics.rayCast(ray, { + filter: (potentialHit: RayCastHit) => { + // return true to accept the hit + // return false to reject the hit + return true; + } +}) +``` + +### Collision Mask + +The collision mask it a bit mask with a 1 in the place for each collision group category you'd like to consider in the raycast. For example this is useful if all your enemies share a collision group category. See [collision group documentation](/docs/collisiongroups/) for more information. + +You may want to pair this with `ignoreCollisionGroupAll: true` to avoid default actors which collide with everything including specific rayCast masks. + +```typescript +const playerGroup = new ex.CollisionGroup('player', 0b0001, ~0b0001); +const enemyGroup = new ex.CollisionGroup('enemy', 0b0010, ~0b0010); +... + +// this raycast will only actors with the 1 in the second place, so enemyGroup +const enemyHits = scene.physics.rayCast(ray, { + collisionMask: 0b0010; +}); + +// this raycast will only actors with the 1 in the first and second place, so playerGroup and enemyGroup +const playerAndEnemyHits = scene.physics.rayCast(ray, { + collisionMask: 0b0011; +}); +``` + +### Collision Group + +The `collisionGroup` searches for actors that match a specific collision group. + +You may want to pair this with `ignoreCollisionGroupAll: true` to avoid default actors which collide with everything including specific rayCast groups. + +## Specific Actor Geometry Testing + +If you have a specific actor or geometry that you know you will test against, all [[Collider]] types implement `rayCast(ray, [maxDistance])`. + ```typescript const actor = new ex.Actor({ pos: ex.vec(200, 100),