You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:如何在Phaser 3.60中为雨伞设置T型Hitbox

Phaser 3.60 T型碰撞盒配置问题解决方案

问题说明

我正在学习Phaser 3.60,已实现雨滴下落碰到雨伞后消失并生成新雨滴的逻辑,但无法设置T型Hitbox。相关代码如下:

雨伞类代码

export class Umbrella extends Phaser.Physics.Arcade.Sprite {
    private raindrops: Phaser.Physics.Arcade.Group;
    private debugGraphic: Phaser.GameObjects.Graphics; // debugGraphic tulajdonság hozzáadása

    constructor(
        scene: Phaser.Scene,
        x: number,
        y: number,
        raindrops: Phaser.Physics.Arcade.Group
    ) {
        super(scene, x, y, "umbrella");

        scene.add.existing(this);
        this.scene.physics.world.enable(this); // Engedélyezzük a fizikai testet az esernyő Sprite-hoz

        // Inicializáljuk a debugGraphic-t
        this.debugGraphic = scene.add.graphics();

        (this.body as Phaser.Physics.Arcade.Body).allowGravity = false; // Kikapcsoljuk a gravitációt

        const hitboxWidth = 100; // A hitbox szélessége
        const hitboxHeight = 100; // A hitbox magassága

        const topHeight = hitboxHeight * 0.25; // A felső téglalap magassága (25%)
        const bottomHeight = hitboxHeight - topHeight; // Az alsó téglalap magassága

        this.raindrops = raindrops;
    }

    public mouseMove(input: Phaser.Input.InputPlugin): void {
        // Itt mozgatjuk az egérrel az esernyőt ha kattintunk
        var pointer = input.activePointer;
        if (pointer.isDown) {
            this.x = pointer.x;
            this.y = pointer.y;
        }

        // Itt mozgatjuk az egérrel az esernyőt ha simán mozgatjuk.
        input.on("pointermove", (pointer) => {
            this.x = pointer.x;
            this.y = pointer.y;

            this.drawHitbox(this.x, this.y);
        });
    }

    private drawHitbox(x: number, y: number): void {
        const hitbox = this.body as Phaser.Physics.Arcade.Body;
        // Rajzolás a debugGraphic segítségével
        this.debugGraphic.clear();
        this.debugGraphic.lineStyle(2, 0xff0000); // Vonalstílus beállítása (2 pixel vastag, piros szín)
        this.debugGraphic.strokeRect(
            x - hitbox.width / 2,
            y - hitbox.height / 2,
            hitbox.width,
            hitbox.height
        );
    }
}

MainGame场景代码

碰撞事件

//Az esőcsepp és az esernyő detektálása.
    this.physics.add.overlap(
        this.umbrella,
        this.raindrops,
        this.collectDrop,
        null,
        this
    );
}

碰撞处理函数

private collectDrop(
    umbrella: Phaser.Physics.Arcade.Sprite,
    drop: Phaser.Physics.Arcade.Sprite
): void {

    // // Eltávolítjuk a cseppet a csoportból
    this.raindrops.remove(drop, true, true);

    // Generálunk egy új esőcseppet
    const newDrop = new Raindrop(
        this,
        Math.floor(Math.random() * Number(this.game.config.width)),
        -100
    );
    this.raindrops.add(newDrop);
}

解决方案:实现T型复合碰撞体

Phaser Arcade Physics默认单个Sprite仅支持矩形/圆形碰撞体,要实现T型Hitbox,需使用复合碰撞体(Composite Collider),通过多个碰撞体组合成T形。

1. 修改雨伞类构造函数,创建复合碰撞体

替换原构造函数中碰撞体相关代码,改用CompositeBody:

constructor(
    scene: Phaser.Scene,
    x: number,
    y: number,
    raindrops: Phaser.Physics.Arcade.Group
) {
    super(scene, x, y, "umbrella");

    scene.add.existing(this);
    // 启用复合碰撞体,禁用默认单个碰撞体
    const body = this.scene.physics.add.existing(this, false) as Phaser.Physics.Arcade.CompositeBody;
    body.setAllowGravity(false);

    // 定义T型碰撞盒尺寸
    const topWidth = 100;   // T型顶部宽度
    const topHeight = 25;   // T型顶部高度
    const bottomWidth = 40; // T型底部宽度
    const bottomHeight = 75;// T型底部高度

    // 添加顶部矩形碰撞体(偏移量基于Sprite中心计算)
    body.addRectangle(0, -bottomHeight/2 - topHeight/2, topWidth, topHeight);
    // 添加底部矩形碰撞体
    body.addRectangle(0, 0, bottomWidth, bottomHeight);

    this.raindrops = raindrops;
    this.debugGraphic = scene.add.graphics();
}

2. 更新Debug绘制函数,显示T型碰撞盒

原函数仅绘制单个矩形,现在遍历复合碰撞体的所有形状进行绘制:

private drawHitbox(x: number, y: number): void {
    this.debugGraphic.clear();
    this.debugGraphic.lineStyle(2, 0xff0000);

    const body = this.body as Phaser.Physics.Arcade.CompositeBody;
    // 遍历所有碰撞形状并绘制
    body.shapes.forEach(shape => {
        if (shape instanceof Phaser.Geom.Rectangle) {
            const rectX = x + shape.x - shape.width/2;
            const rectY = y + shape.y - shape.height/2;
            this.debugGraphic.strokeRect(rectX, rectY, shape.width, shape.height);
        }
    });
}

3. 修复鼠标移动逻辑(避免重复绑定事件)

原mouseMove函数每次调用都会重复绑定pointermove事件,修改为仅初始化一次:

public initMouseControl(input: Phaser.Input.InputPlugin): void {
    // 绑定鼠标移动事件
    input.on("pointermove", (pointer) => {
        this.x = pointer.x;
        this.y = pointer.y;
        this.drawHitbox(this.x, this.y);
    });

    // 可选:保留点击拖动逻辑
    input.on("pointerdown", (pointer) => {
        this.x = pointer.x;
        this.y = pointer.y;
        this.drawHitbox(this.x, this.y);
    });
}

4. 在MainGame中初始化鼠标控制

替换原调用mouseMove的代码:

// 初始化雨伞后调用
this.umbrella.initMouseControl(this.input);

关键说明

  • 复合碰撞体支持为单个Sprite添加多个碰撞形状,组合成任意复杂区域
  • addRectangle的前两个参数是碰撞体相对于Sprite中心的偏移量,需根据实际需求调整
  • 原碰撞检测逻辑无需修改,physics.add.overlap会自动识别复合碰撞体的所有形状

内容的提问来源于stack exchange,提问作者Drelaky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 19:12:00