Phaser中,组与瓦片层之间的碰撞检测

前端开发 2026-07-11

在Phaser中,如何检测一个group与一个瓦片层之间的碰撞?一个可能的原因是例如要删除击中墙面的子弹。理论上很简单,只要使用collider就可以,但似乎没有任何方法奏效。我已经尝试使用overlap代替collide,把子弹设为物理组,使用world.addCollider等等。

有些瓦片通过以下这一行设置了碰撞:

this.groundLayer.setCollisionByProperty({ collides: true });

这是通过从Tiled生成的JSON文件中获取collide属性实现的。因此,玩家与瓦片之间的碰撞工作正常。

有些瓦片被设置为与以下这一行发生碰撞:

this.groundLayer.setCollisionByProperty({ collides: true });

by getting the collide property from a JSON file produced by Tiled. So collision works fine between the player and the tiles.

有问题的代码如下:

this.physics.add.collider(
  this.bullets,
  this.groundLayer,
  (bullet, tile) =>
  {
    console.log("hit");
    bullet.setActive(false);
    bullet.setVisible(false);
  });

解决方案

问题很可能出在你在 collider 函数中使用了 "wrong" 参数。在这个phaser版本中,似乎总是物理组的第一个参数作为第一个参数(见下面的示例)。你可以把这行 this.physics.add.collider(layer, this.bullets,...) 仅在 layerthis.bullets 中互换,代码仍然能工作。

看起来像是一个框架Bug (对我而言,但我还没有读文档)

Apart from that it seems to work, or am I missing something?

btw.: 我刚刚重新读了你的问题,groundLayer 听起来像地板而不是墙,并且如果都设定为碰撞,由于会立即发生碰撞,屏幕上不会显示任何内容。

document.body.style = 'margin:0;';

var config = {
    width: 536 /8,
    height: 42,
    zoom: 4.5,
    physics: {
        default: 'arcade',
        arcade: {            
            gravity:{ y: 0 },
        }
    },
    scene: { create },
}; 

function create () {
    // HELPER CODE FOR DEMO -- START
    let graphics  = this.make.graphics();
    graphics.fillStyle(0x00ff00);
    graphics.fillRect(8, 0, 8, 8);
    graphics.fillStyle(0xff0000);
    graphics.fillRect(16, 0, 8, 8);
    graphics.fillStyle(0xff0000);
    graphics.fillRect(24, 0, 8, 8);
    graphics.generateTexture('tiles', 8*4, 8);       
    graphics.fillStyle( 0xff0000 );
    graphics.fillRect(0, 0, 2, 2);
    graphics.generateTexture(`bullet`, 2, 2);
    // HELPER CODE FOR DEMO -- END

    var data = [
      [1,1,1,1,1], [1,0,0,0,1], [1,0,0,0,1], [1,0,0,0,1], [1,1,1,1,1], ]

    var map = this.make.tilemap({ data, tileWidth: 8, tileHeight: 8 });
    var tiles = map.addTilesetImage('tiles');
    var layer = map.createLayer(0, tiles, 0, 0);
    layer.setCollision(1);

    this.bullets = this.physics.add.group({
        key: 'bullet',
        repeat: 0,         
        setXY: { x: 20, y: 20, stepX: 0} 
    });

    this.bullets.setVelocityX(-10);

    // seems like first to parameters can be swapped 
    this.physics.add.collider(layer, this.bullets,  (bullet, tile) => 
    {   
       console.info(bullet, tile); 
       // destroy bullet 
       bullet.setActive(false).setVisible(false).stop();
       bullet.body.enabled = false;

       // respawn bullet for DEMO
       let newBullet = this.bullets.getFirstDead(false);
       newBullet.setActive(true).setVisible(true).setPosition(20, 20).setVelocityX(-10);
       newBullet.body.enable = true;
    });
}

new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/phaser.js"></script>
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章