cseibert Posted July 17, 2018 Share Posted July 17, 2018 Does anyone have a good example of how to create a zone which invokes a callback function when a player enters / leaves the zone? I am just trying to display some extra text when a player enters a zone, but I can't find any good examples using the Phaser3 Zone class. I found a work around using the Rectangle object manually, but I'm assuming (hoping) there is an easier way to use the Zone class to setup this same functionality using enter / leave callbacks? This is what I have done so far: // create this.zone = new Phaser.Geom.Rectangle(this.box.x - 25, this.box.y - 25, 50, 50); this.player = this.physics.add.sprite(800, 600, 'player_handgun'); this.text = this.add.text(this.box.x + 20, this.box.y, "use", { font: "18px Arial", fill: "#ff0000", align: "center", backgroundColor: "#00ffff" }); this.text.setOrigin(0.5, 0.5); this.text.setVisible(false); // update if (Phaser.Geom.Rectangle.Overlaps(this.player.getBounds(), this.zone)) { this.text.setVisible(true); } else { this.text.setVisible(false); } Again, ^ this approach works, but I rather find a way to use the Phaser's Zone class. Some issues I have with this approach is I can't set the origin(0.5, 0.5) on the rectangle, so I have to calculate the zone offset manually. Link to comment Share on other sites More sharing options...
samme Posted July 17, 2018 Share Posted July 17, 2018 Zones don't really do their own overlap checks, but you could add an Arcade Physics body to a zone and then use an overlap collider, if you prefer that. Even without a physics body, you could do Phaser.Geom.Rectangle.Overlaps(player.getBounds(), zone.getBounds()) Link to comment Share on other sites More sharing options...
cseibert Posted July 17, 2018 Author Share Posted July 17, 2018 Thanks, I guess the Zone class is for something different then? Can you explain with more examples what you mean by "add an Arcade Physics body to a zone"? Link to comment Share on other sites More sharing options...
samme Posted July 17, 2018 Share Posted July 17, 2018 https://codepen.io/samme/pen/yqJoym?editors=0010 NoxBrutalis 1 Link to comment Share on other sites More sharing options...
cseibert Posted July 18, 2018 Author Share Posted July 18, 2018 Thank you, I appreciate this example you made! Makes sense now. NoxBrutalis 1 Link to comment Share on other sites More sharing options...
Mihai Posted March 13, 2022 Share Posted March 13, 2022 Doesn't work if the objects stops in the zone. Because of this written in documentation: touching :Phaser.Types.Physics.Arcade.ArcadeBodyCollision Whether this Body is colliding with a Body or Static Body and in which direction. In a collision where both bodies have zero velocity, embedded will be set instead. And because of this, you cannot rely on wasTouching.none Link to comment Share on other sites More sharing options...
Mihai Posted March 14, 2022 Share Posted March 14, 2022 Back, I've written some code that works. I load the areas (zones) from a tilemap (.json file) created with Tiled (the rectangle in the object layer must have Type=AREA). I am pasting only the necessary code (striped the irrelevant). And it is TypeScript, Not JavaScript, but easey to change to js. mainMenuScene.ts import 'phaser'; import Grizzly from '../grizzly'; import Hero from '../hero'; export enum AreaCollision { ENTER_AREA, EXIT_AREA } export default class MainMenuScene extends Phaser.Scene { map: Phaser.Tilemaps.Tilemap; hero: Hero; heroArea: String | null = null; areaObjects: Array<Phaser.Types.Tilemaps.TiledObject>; constructor() { super({ key: 'MainMenuScene' }); } preload() { this.load.tilemapTiledJSON('map', 'assets/tilemaps/town.json'); } create() { this.map = this.make.tilemap({ key: 'map' }); this.areaObjects = this.map.filterObjects('Objects', (obj) => obj.type === 'AREA'); } update(time, delta) { for (let area of this.areaObjects) { //debug: //let rectangle = this.add.rectangle(area.x!, area.y!, area.width!, area.height!); //rectangle.setStrokeStyle(1, 0xff0000, 1); //rectangle.setOrigin(0, 0); let entities: Array<Phaser.Physics.Arcade.Body> = this.physics.overlapRect( area.x!, area.y!, area.width!, area.height!, true, false ) as Array<Phaser.Physics.Arcade.Body>; let heroesInArea = entities.filter((entity) => entity.gameObject instanceof Hero); let inArea = true; if (heroesInArea.length == 0) { inArea = false; } if (inArea == true && (this.heroArea == null || this.heroArea != area.name)) { this.hero.emit(AreaCollision[AreaCollision.ENTER_AREA], area.name); this.heroArea = area.name; } if (!inArea && this.heroArea == area.name) { this.hero.emit(AreaCollision[AreaCollision.EXIT_AREA], area.name); this.heroArea = null; } } } } and hero.ts import 'phaser'; import MainMenuScene, { AreaCollision } from './scenes/mainMenuScene'; export default class Hero extends Phaser.GameObjects.Sprite { constructor(scene, x, y) { this.on(AreaCollision[AreaCollision.ENTER_AREA], (areaName) => { console.log('Enter area ' + areaName); }); this.on(AreaCollision[AreaCollision.EXIT_AREA], (areaName) => { console.log('Exit area ' + areaName); }); } } Link to comment Share on other sites More sharing options...
Recommended Posts