如何设置一个T形的雨伞碰撞框?

huangapple go评论61阅读模式
英文:

how can I set up a T-shaped hitbox for an umbrella?

问题

我已经开始学习Phaser 3.60,不幸的是,我陷入了困境。我找不到设置碰撞框的方法。我想要的是让雨滴从顶部落下,有一个伞,当雨滴落在伞上时,它会取消雨滴并生成一个新的雨滴。这些机制已经写好,但我无法重新编写碰撞框。我希望你能帮助我。我将发送给你一些我的代码。

伞:

export class Umbrella extends Phaser.Physics.Arcade.Sprite {
    private raindrops: Phaser.Physics.Arcade.Group;
    private debugGraphic: Phaser.GameObjects.Graphics;

    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);

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

        (this.body as Phaser.Physics.Arcade.Body).allowGravity = false;

        const hitboxWidth = 100;
        const hitboxHeight = 100;

        const topHeight = hitboxHeight * 0.25;
        const bottomHeight = hitboxHeight - topHeight;

        this.raindrops = raindrops;
    }

    public mouseMove(input: Phaser.Input.InputPlugin): void {
        var pointer = input.activePointer;
        if (pointer.isDown) {
            this.x = pointer.x;
            this.y = pointer.y;
        }

        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;
        this.debugGraphic.clear();
        this.debugGraphic.lineStyle(2, 0xff0000);
        this.debugGraphic.strokeRect(
            x - hitbox.width / 2,
            y - hitbox.height / 2,
            hitbox.width,
            hitbox.height
        );
    }
}

MainGame Scene:

碰撞事件:

// 检测雨滴和伞的碰撞
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 {
    // 从组中移除雨滴
    this.raindrops.remove(drop, true, true);

    // 生成一个新的雨滴
    const newDrop = new Raindrop(
        this,
        Math.floor(Math.random() * Number(this.game.config.width)),
        -100
    );
    this.raindrops.add(newDrop);
}

希望这对你有所帮助。

英文:

I have started learning Phaser 3.60 and unfortunately I am stuck. I can't find a way to set up the hitbox. Exactly what I would like is to have the raindrop falling from the top down and have an umbrella that when the raindrop falls on it, it cancels the raindrop and generates a new one. The mechanics are written but I can't rewrite the hitbox. I would like your help with this. I will send you a few lines of my code.

Umbrella:

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 Scene:

collision event:

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

Collision detection:

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);
}

答案1

得分: 0

如@zenly提到的,细长条足够了。要创建它,你可以使用物理体的setSizesetOffset函数,如下演示所示(文档链接)。

顺便说一下: 你实际上不需要创建一个调试图形对象,因为Phaser提供了一个名为config的属性debug,只需将其设置为true即可。

这里是一个简短的演示:

document.body.style = 'margin:0;';
class Umbrella extends Phaser.Physics.Arcade.Sprite {
    constructor( scene, x, y, raindrops ) {
        super(scene, x, y, "umbrella");

        scene.add.existing(this);
        this.scene.physics.world.enable(this); 

        this.body.allowGravity = false;

        // 碰撞箱的大小
        this.setSize(80, 5);
        // 碰撞箱的偏移
        this.setOffset(-25, -20);

        const hitboxWidth = 100;
        const hitboxHeight = 100;

        const topHeight = hitboxHeight * 0.25;
        const bottomHeight = hitboxHeight - topHeight;

        this.raindrops = raindrops;
    }
    
    //...
}

var config = {
    type: Phaser.AUTO,
    width: 536,
    height: 183,
    physics: {
        default: 'arcade',
        arcade: {
            // 显示调试碰撞箱
            debug: true
        }
    },
    scene: { create }
}; 

function create () {    
    let i = new Umbrella(this, 100, 100, []);
}

new Phaser.Game(config);
<script src="//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js"></script>

如果你想创建一个T形碰撞箱。我可以创建一个自定义的Phaser容器,并添加两个物理对象/物体,然后使用上述提到的函数来定位它们。

英文:

As @zenly mentioned thin-bar is enough. To create this you can use the functions setSize and setOffset of the physics body, shown in the following demo (link to the documentation).

> btw.: you don't really need, to create a debug graphics object, since phaser offers it out-of-the-box, with the config property debug, just set it to true.

Here a short demo:

<!-- begin snippet: js hide: false console: false babel: false -->

<!-- language: lang-js -->

document.body.style = &#39;margin:0;&#39;;
class Umbrella extends Phaser.Physics.Arcade.Sprite {
constructor( scene, x, y, raindrops ) {
super(scene, x, y, &quot;umbrella&quot;);
scene.add.existing(this);
this.scene.physics.world.enable(this); 
this.body.allowGravity = false;
// size of hitbox
this.setSize(80, 5);
// offset of hitbox
this.setOffset(-25, -20);
const hitboxWidth = 100;
const hitboxHeight = 100;
const topHeight = hitboxHeight * 0.25;
const bottomHeight = hitboxHeight - topHeight;
this.raindrops = raindrops;
}
//...
}
var config = {
type: Phaser.AUTO,
width: 536,
height: 183,
physics: {
default: &#39;arcade&#39;,
arcade: {
// shows debug hitbox
debug: true
}
},
scene: { create }
}; 
function create () {    
let i = new Umbrella(this, 100, 100, []);
}
new Phaser.Game(config);

<!-- language: lang-html -->

&lt;script src=&quot;//cdn.jsdelivr.net/npm/phaser/dist/phaser.min.js&quot;&gt;&lt;/script&gt;

<!-- end snippet -->

> If you want the create a T-shaped hitbox. I could create a custom Phaser Container and add two physics objects/bodies, and position the with the above mentioned functions.

huangapple
  • 本文由 发表于 2023年5月24日 21:53:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76324291.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定