Search code examples
javascriptphaser-frameworkjstilemap

Phaser3 overlap to once tile


I want to select 1 object in my tilemap and check whether my player hits it or not, and I can give collision in this object propslayer, there is no problem with specific objects, but I cannot get it into condition.

All I want is for example: When I hit the object with id 36, I want to print text on the consola.

import { Scene } from "phaser";

import Scenes from "./";
import { Player } from "../objects";

import GameManager from "../managers/gameManager";
import Level1Scene from "./level1scene";

export default class GameScene extends Scene {
  //actors
  private declare player: Player;
  private declare currentScene: Scene;
  // tilemap
  private declare map: Phaser.Tilemaps.Tilemap;

  // tilesets
  private declare propsTileSet: Phaser.Tilemaps.Tileset;
  private declare wallTileset: Phaser.Tilemaps.Tileset;
  private declare bgTileset: Phaser.Tilemaps.Tileset;
  // tilemap layers
  private declare propsLayer: Phaser.Tilemaps.TilemapLayer;
  private declare bgLayer: Phaser.Tilemaps.TilemapLayer;
  private declare wallsLayer: Phaser.Tilemaps.TilemapLayer;

  private declare currentMap: string;

  constructor() {
    super({
      key: Scenes.GameScene.key,
    });
    this.currentMap = "level-1";
  }

  init() {
    this.game.events.emit("react__onGameStart");
  }

  create() {
    console.log(this.currentMap);
    this.createTiles();
    this.createLayers();
    this.map.setCollision([1025, 1026]);
    this.createPlayer();
    this.createFullscreenButton();
    this.cameras.main.startFollow(this.player);
    this.cameras.main.setZoom(2);
  }

  private createFullscreenButton() {
    const fullscreenButton = this.add
      .sprite(this.cameras.main.width, this.cameras.main.height, "fullScreen")
      .setInteractive();

    fullscreenButton.on("pointerup", () => {
      this.toggleFullscreen();
    });
  }

  private toggleFullscreen() {
    if (this.scale.isFullscreen) {
      this.scale.stopFullscreen();
    } else {
      this.scale.startFullscreen();
    }
  }

  update(time: number, delta: number): void {
    this.player.update();
    this.physics.collide(this.player, this.wallsLayer);
    this.physics.collide(this.player, this.propsLayer);
    this.propsLayer.setCollisionBetween(36, 40);
  }
  private createTiles(): void {
    this.map = this.make.tilemap({
      key: this.currentMap,
    });
    this.propsTileSet = this.map.addTilesetImage("props")!;
    this.wallTileset = this.map.addTilesetImage("ground")!;
  }

  private createLayers() {
    this.add.image(0, 0, "bg").setOrigin(0, 0);
    this.propsLayer = this.map.createLayer("props", this.propsTileSet, 0, 0)!;
    this.wallsLayer = this.map.createLayer("ground", this.wallTileset, 0, 0)!;
  }
  private createPlayer(): void {
    this.player = new Player({
      key: "player",
      scale: 1,
      scene: this,
      tag: "player",
      texture: "atlas",
      x: 50,
      y: 0,
      afterCreate: () => {
        console.log("Player is created");
      },
    });
  }
}


Solution

  • Well first I saw a mistake in the update function, that might cause problems in the future. You should move these following three lines from the update to the create function. (and change the collide to the collider function call link to the documentation, or the overlap function)

    this.physics.add.collider(this.player, this.wallsLayer);
    this.physics.add.collider(this.player, this.propsLayer);
    this.propsLayer.setCollisionBetween(36, 40);
    

    For adding a callback just add a callback function to the specific collider function call, like this:

    this.physics.add.collider(this.propsLayer, this.player, function(player, tile){
        if(tile.index == 36 ){
          console.info('Collision with tile index 36');
        }
    });