Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

phaser-raycaster

wiserim785ISC0.10.11TypeScript support: included

Raycasting plugin for Phaser 3.

phaser, phaser3, phaser-plugin, plugin, raycast

readme

Phaser Raycaster

Raycasting plugin for Phaser 3.

GitHub release npm GitHub Github file size

Phaser Raycaster is a Phaser 3 plugin which provide raycasting for geometric game objects, sprites, Arcade Physics and Matter.js bodies.

Documentation: https://wiserim.github.io/phaser-raycaster/

Code examples are available on CodePen: LINK

Features:

  • compatible with arcade and matter physics,
  • raycasting in a single direction, 360 degrees circle or in a cone,
  • visibility detection (collision detection with game objects),
  • test rays on mapped game objects (containers, lines, rectangles, polygons, circles, sprites, tilemaps and matter bodies),
  • provides closest intersection points between rays and tested objects,
  • tests can be made on all mapped objects, selected ones or only ones within detection range,
  • static and dynamic mapping for individual objects,
  • mapped objects intersections detection,
  • debug mode.

NPM

npm install phaser-raycaster

CDN

https://www.jsdelivr.com/package/npm/phaser-raycaster

Getting started

1. Include plugin in your project:

<!--CDN-->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/phaser-raycaster@0.10.11/dist/phaser-raycaster.min.js"></script>
# NPM
npm install phaser-raycaster

2. Enable plugin in your Game config:

import PhaserRaycaster from 'phaser-raycaster'

let config = {
    type: Phaser.Auto,
    parent: 'game',
    width: 800,
    height: 600,
    backgroundColor: "black",
    scene: [
        Scene1
    ],
    plugins: {
        scene: [
            {
                key: 'PhaserRaycaster',
                plugin: PhaserRaycaster,
                mapping: 'raycasterPlugin'
            }
        ]
    }
}

new Phaser.Game(config);

3. Create new raycaster in your scene:

create() {
  this.raycaster = this.raycasterPlugin.createRaycaster(options);

  // additional code
}

If you're using TypeScript, you need to add to scene plugin class:

import PhaserRaycaster from 'phaser-raycaster'

export default class MyScene extends Phaser.Scene {
  raycasterPlugin: PhaserRaycaster

  // aditional code
}

4. Create new ray

create() {
  // additional code

  this.ray = this.raycaster.createRay();

  // additional code
}

5. Map game objects which will be tested by rays

//create game object
this.rectangle = this.add.rectangle(100, 100, 50, 50)
  .setStrokeStyle(1, 0xff0000);

//map game object
this.raycaster.mapGameObjects(this.rectangle);

//create group
this.group = this.add.group();

//map game objects actually in group
this.raycaster.mapGameObjects(this.group.getChildren());

//map tilemap layer
this.map = this.make.tilemap();
this.tilemap = this.map.createStaticLayer();

this.raycaster.mapGameObjects(this.tilemap, false, {
  collisionTiles: [1,2,3] //array of tiles types which can collide with ray
});

6. Cast ray

//set ray position
this.ray.setOrigin(400, 300);
//set ray direction (in radians)
this.ray.setAngle(2);
//set ray direction (in degrees)
this.ray.setAngleDeg(90);
//cast single ray and get closets intersection, hit mapped object and hit segment
let intersection = this.ray.cast();
let hitObject = intersection.object;
let hitSegment = intersection.segment;

//cast rays in all directions (toward all mapped objects vertices / points)
let intersections = this.ray.castCircle();

//set ray's cone angle (in radians)
this.ray.setCone(1);
//set ray's cone angle (in degrees)
this.ray.setConeDeg(90);

//cast rays in a cone
let intersections = this.ray.castCone();

7. Raycaster bounding box

By default Raycaster is setting it's bounding box based on Arcade Physics / Matter physics world bounds. If world size will change after creation of Raycaster, bounding box needs to be updated.

//define bounds
var bounds = new Phaser.Geom.Rectangle(x, y, width, height);

//get world bounds (arcade physics)
bounds = this.worldLayer.getBounds();

//get bounds (matter physics)
let walls = this.matter.world;
bounds = new Phaser.Geom.Rectangle(
  walls.top.vertices[3].x, //x
  walls.top.vertices[3].y, //y
  walls.bottom.vertices[1].x - walls.top.vertices[3].x, //width
  walls.bottom.vertices[1].y - walls.top.vertices[3].y //height
)

//set bounding box on raycaster creation
var raycaster = this.raycasterPlugin.createRaycaster({
  boundingBox: bounds
});

//set bounding box after creation
raycaster.setBoundingBox(x, y, width, height);

8. Collisions (arcade physics)

//enable auto slicing field of view
this.ray.autoSlice = true;
//enable arcade physics body
this.ray.enablePhysics();
//set collision (field of view) range
this.ray.setCollisionRange(200);
//cast ray
this.ray.castCircle();

//get all game objects in field of view (which bodies overlap ray's field of view)
let visibleObjects = this.ray.overlap();

//get objects in field of view
visibleObjects = this.ray.overlap(group.getChildren());

//check if object is in field of view
visibleObjects = this.ray.overlap(gameObject);

//add overlap collider (require passing ray.processOverlap as process callback)
this.physics.add.overlap(this.ray, targets, function(rayFoVCircle, target){
  /*
  * What to do with game objects in line of sight.
  */
}, this.ray.processOverlap.bind(this.ray));

9. Collisions (matter physics)

//enable auto slicing field of view
this.ray.autoSlice = true;
//enable matter physics body
this.ray.enablePhysics('matter');
//cast ray
this.ray.castCircle();

//get all game objects and bodies in field of view (which bodies overlap ray's field of view)
let visibleObjects = this.ray.overlap();

//get objects and bodies in field of view
visibleObjects = this.ray.overlap([gameObject1, gameObject2, body1, body2]);

//check if object or body is in field of view
visibleObjects = this.ray.overlap(gameObject);

//add onCollide event
this.ray.setOnCollide(function(collisionInfo){
  //get body
  let body = collisionInfo.bodyA.label === 'phaser-raycaster-ray-body' ? collisionInfo.bodyB : collisionInfo.bodyA;
    /*
    * What to do with game object which enters line of sight .
    */
  }
});

//add onCollideWith event
this.ray.setOnCollideWith(body, function(body, collisionInfo){
    /*
    * What to do with game object which enters line of sight.
    */
  }
});

//add onCollideEnd event
this.ray.setOnCollideEnd(function(collisionInfo){
  //get body
  let body = collisionInfo.bodyA.label === 'phaser-raycaster-ray-body' ? collisionInfo.bodyB : collisionInfo.bodyA;
    /*
    * What to do with game object which leaves line of sight.
    */
  }
});

//add onCollideActive event
this.ray.setOnCollide(function(collisionInfo){
  //get body
  let body = collisionInfo.bodyA.label === 'phaser-raycaster-ray-body' ? collisionInfo.bodyB : collisionInfo.bodyA;
    /*
    * What to do with game object while it's in line of sight.
    */
  }
});

10. Destroy objects

//remove mapped objects
this.raycaster.removeMappedObjects(object);
this.raycaster.removeMappedObjects(arrayOfObjects);

//destroy ray
this.ray.destroy();

//destroy raycaster
this.raycaster.destroy();

11. Statistics

//get raycaster statistics
let statistics = this.raycaster.getStats();
/*
  statistics = {
    mappedObjects: {
      total - mapped objects total
      static - static maps
      dynamic - dynamic maps
      rectangleMaps - rectangle maps
      polygonMaps - polygon maps
      circleMaps - circle maps
      lineMaps - line maps
      containerMaps - container maps
      tilemapMaps - tilemap maps
      matterMaps - matter body maps
    }
  }
*/

//get ray statistics
let rayStatistics = this.ray.getStats();
/*
  rayStatistics = {
    method - used casting method (cast, castCircle, castCone)
    rays - casted rays
    testedMappedObjects - tested mapped objects
    hitMappedObjects - hit mapped objects
    segments - tested segments
    time - casting time
  }
*/

12. Debug mode

  //enable debug mode
  this.raycaster = this.raycasterPlugin.createRaycaster({
    debug: true
  });

  //advanced debug mode options
  this.raycaster = this.raycasterPlugin.createRaycaster({
    debug: {
      enabled: false, //enable debug mode
      maps: true, //enable maps debug
      rays: true, //enable rays debug
      graphics: {
          ray: 0x00ff00, //debug ray color; set false to disable
          rayPoint: 0xff00ff, //debug ray point color; set false to disable
          mapPoint: 0x00ffff, //debug map point color; set false to disable
          mapSegment: 0x0000ff, //debug map segment color; set false to disable
          mapBoundingBox: 0xff0000 //debug map bounding box color; set false to disable
      }
    }
  });

  //change debug options after initialization
  this.raycaster.debugOptions.enabled = true;

  this.raycaster.setOptions({
    debug: true
  });

changelog

Change Log

Version 0.10.11 - 2024.11.28

Updates

  • Updated dev dependencies.

Bug fixes


Version 0.10.10 - 2023.12.27

Updates

  • npm run build-typings command now add module declaration to types.d.ts file automatically.

Bug fixes

  • Map.updateMap method for containers doesn't check if child object's points array is empty while assigning neighbour points to last point.

Version 0.10.9 - 2023.08.15

Updates

  • Rework of Map.updateMap method for matter objects.
  • Map.updateMap method for matter objects now ignores internal segments in concave bodies.

Bug fixes

  • Ray.cast method won't test mapped object when ray is inside of mapped object and hit another mapped object within / overlap the first one.
  • Map.updateMap method for matter objects don't map properly non enclosed concave bodies.

Version 0.10.8 - 2023.08.08

Bug fixes

  • Typo in Map.updateMap method for polygons.
  • Typo in Map.updateMap method for containers.
  • Fixed code changes caused by faulty linter.

Version 0.10.7 - 2023.08.06

Updates

  • Map.updateMap method now add array of neighbours to points in Map.points.
  • Optimisation of Map.updateMap method for tilemaps.
  • Ray.castCircle and Ray.castCone methods now checks if ray is "glancing" mapped objects.
  • Ray.cast method now won't test mapped object if current closest intersection is closer to ray than it's bounding box.

Bug fixes

  • Raycaster.removeMappedObjects method isn't checking if passed objects are mapped.
  • Map.destroy method doesn't work properly for Arcade and Matter bodies (fixed by @dreasgrech Andreas Grech).
  • Fixed docs typos

Version 0.10.6 - 2023.01.30

Updates

  • Added Raycaster.dynamicMappedObjects to store dynamic maps.
  • Raycaster.update method now traverse through Raycaster.dynamicMappedObjects to update maps.
  • Setting Raycaster.Map.dynamic now updates Raycaster.dynamicMappedObjects and Ratcaster._stats.

Bug fixes

  • Raycaster.drawDebug method isn't checking if mapped object has defined data property.
  • Raycaster.destroy method isn't destroying Raycaster.graphics object used for debug.
  • Raycaster.destroy method isn't removing scene's update event listener.
  • Ray.destroy method isn't destroying Ray.graphics object used for debug.

Version 0.10.5 - 2022.11.04

Features

  • Added TypeScript typings.

Updates

  • Updated PhaserRaycaster plugin class.

Bug fixes

  • Fixed docs typos

Version 0.10.4 - 2022.06.28

Updates

  • Raycaster.mapGameObjects method now checks if mapped object is supported.
  • Map.updateMap method for container objects now checks if mapped children objects are supported.

Version 0.10.3 - 2022.06.27

New features

  • Added Ray.destroy method.
  • Added Map.destroy method.
  • Added Raycaster.destroy method.
  • Added mapChild option to Map.config parameters.

Updates

  • Raycaster.removeMappedObjects method now also destroys Map objects.
  • Container's Map now allows to choose single child element which will be mapped, by passing it as mapChild option to Map.config parameters.
  • Container's Map now allows to use circle map children with Map.segmentCount set to 0. Transformed children circles are stored in Map._circles property.
  • Updated NPM dev dependencies.

Version 0.10.2 - 2021.12.20

Bug fixes

  • Ray.overlap - method is using deprecated method Ray.testOverlap instead of Ray.testArcadeOverlap to test Arcade body.

Version 0.10.1 - 2021.11.16

Bug fixes

  • Raycaster.update - typo in code.
  • Ray.cast, Ray.castCircle and Ray.castCone methods after optimization in fringe cases when ray "glanced" object's border box corner didn't detect hit properly.

Version 0.10.0 - 2021.11.13

New features

  • Added debug mode.
  • Added statistics.
  • Added additional intersection data. Each point contains reference to hit mapped object and it's segment if available.

Updates

  • Ray.cast, Ray.castCircle and Ray.castCone methods optimization.

Version 0.9.4 - 2021.08.20

Bug fixes

  • Map.config doesn't add Map.getBoundingBox method to containers map.
  • Raycaster.mapGameObjects doesn't add map to data attribute if it's already enabled.

Updates

  • Ray.cast, Ray.castCircle and Ray.castCone methods return additionally hit mapped objects and segments.

Version 0.9.3 - 2021.03.07

Updates

  • Ray.cast, Ray.castCircle and Ray.castCone methods return additionally hit mapped objects and segments.

Version 0.9.2 - 2020.02.13

Bug fixes

  • Raycaster.mapGameObjects doesn't map Phaser.Tilemaps.TilemapLayer which replaced Phaser.Tilemaps.StaticTilemapLayer and Phaser.Tilemaps.DynamicTilemapLayer in Phaser 3.50.0.

Version 0.9.1 - 2020.12.13

New features

  • Added matter physics game objects collision methods to Ray.
  • Ray.setCollisionCategory is new method that sets the collision category of Ray matter body.
  • Ray.setCollisionGroup is new method that sets the collision category of Ray matter body.
  • Ray.setCollidesWith is new method that sets the collision mask for Ray matter body.
  • Ray.setOnCollide is new method that sets onCollide event's calback for Ray matter body.
  • Ray.setOnCollideEnd is new method that sets onCollideEnd event's calback for Ray matter body.
  • Ray.setOnCollideActive is new method that sets onCollideActive event's calback for Ray matter body.
  • Ray.setOnCollideWith is new method that sets onCollide event's calback for Ray matter body when it collides with the given body or bodies.

Bug fixes

  • Ray.processOverlap method return false for all arcade bodies.

Version 0.9.0 - 2020.11.26

New features

  • Added matter physics support.
  • Raycaster.mapGameObjects now accepts matter bodies.
  • Map can now map matter bodies.
  • Map.getBoundingBox is new method that allows to get map bounding box.
  • Map.forceConvex is new property that force using matter body's convex body (hull) for mapping.
  • Map.forceVerticesMapping is new property that force using circle matter body's vertices for mapping.
  • Ray.enablePhysics is new method that creates arcade / matter physics body for ray.
  • Ray.bodyType is new property which define if ray's body use arcade or matter physics.

Updates

  • Ray.enableArcadeBody was replaced by Ray.enablePhysics.
  • Ray.processOverlap now also accepts matter bodies and matter CollisionInfo objects.
  • Map contains now reference to Raycaster object.

Version 0.8.1 - 2020.09.08

New features

  • Ray.round is new property that determines if ray's hit point will be rounded.

Updates

  • Slight ray casting optimisation: raycaster will cast ray at each angle only once.

Version 0.8.0 - 2020.05.22

New features

  • Ray.intersections is new property that stores intersections calculated by last casting.
  • Ray.slicedIntersections is new property that stores intersections calculated by last casting sliced into array of Phaser.Geom.Triangle objects.
  • Ray.autoSlice is new property that determine if after casting, intesections should be sliced.
  • Ray.slice is new method that allows to slice array of intersections into array of Phaser.Geom.Triangle objects.
  • Ray.enableArcadeBody is new method that creates arcade physics body for ray.
  • Ray.overlap is new method that allows to if game objects wih physics bodies overlap ray's field of view.
  • Ray can be added to arcade physics collider / overlap.

Updates

  • Ray.range was renamed to Ray.rayRange.
  • Ray.setRange was renamed to Ray.setRayRange.

Version 0.7.3 - 2020.04.21

New features

  • Map can now map Phaser.Tilemaps.StaticTilemapLayer and Phaser.Tilemaps.DynamicTilemapLayer objects.

Version 0.7.2 - 2020.03.29

New features

  • Map can be enabled / disabled with Map.active option. Disabled map return empty arrays instead of its points and segments and won't be updated.
  • Raycaster.enableMaps is new methods that allows to enable objects maps by passing game object / game objects array as an argument.
  • Raycaster.disableMaps is new methods that allows to disable objects maps by passing game object / game objects array as an argument.

Version 0.7.1 - 2020.03.25

New features

  • Map can now map Phaser.GameObjects.Container objects and its children. At this moment circle maps of container's children are tested by Ray objects properly only when Raycaster.mapSegmentCount or Map.segmentCount is set above 0 (when circle map consists of segments which number is defined by Map.segmentCount).

Updates

  • Automatic map updates on update event can be now disabled, by passing autoUpdate option to raycaster constructor.

Bug fixes

  • Typo in Ray.setDetectionRange method.
  • In Ray.cast method, when ray's range is set below Phaser.Math.MAX_SAFE_INTEGER and theres no available intersections within detection range, method was trying to calculate ray's target distance to ray origin, even if target was not passed.

Version 0.7.0 - 2020.03.06

New features

  • Ray.castCone is new method that allows to cast rays in a cone. cone direction is defined by Ray.angle and cone angle is defined by Ray.cone.
  • Ray.setCone is new method that allows to set Ray.cone (Ray.castCone method's cone angle).
  • Ray.setConeDeg is new method that allows to set Ray.cone (Ray.castCone method's cone angle) in degrees.

Version 0.6.4 - 2020.02.23

Updates

  • Ray.angle is now normalized (between 0 - 2π).

Version 0.6.3 - 2020.02.23

Bug fixes

  • Not defining Raycaster.boundingBox when physics was not defined caused error.

Version 0.6.2 - 2020.02.23

Bug fixes

  • Not defining Raycaster.boundingBox when physics was not defined caused error.

Version 0.6.1 - 2020.02.22

New features

  • Ray.setAngleDeg is new method that allows to set Ray.angle in degrees.

Updates

  • Raycaster: bounds will be set to the world bounds by default.
  • Ray.castAll: method renamed to Ray.castCircle.

Bug fixes

  • Not passing argument to Raycaster.createRay method caused error.