collision-detection - 如何使用物质物理在 Phaser 3 中设置平台和精灵之间的约束
问题描述
我正在创建一个使用一些绳索摆动机制的移相器游戏。单击鼠标时,精灵会触发一个矩形,然后在精灵和该矩形碰撞的任何对象之间创建一个约束。现在,由于某种原因,矩形只会与世界的边界发生碰撞。我的平台有碰撞箱,但矩形直接穿过它们。如何获得被触发以与平台而不是世界边界碰撞的矩形?
代码:
let game;
let gameOptions = {
gravity: 2,
constraintSpeed: 50,
hookSpeed: 50,
ropeTolerance: 15
};
const BOX = 0;
const HERO = 1;
const HOOK = 2;
window.onload = function() {
let gameConfig = {
type: Phaser.AUTO,
scale: {
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH,
parent: "thegame",
width: 1200,
height: 750
},
scene: playGame,
physics: {
default: "matter",
matter: {
gravity: {
y: gameOptions.gravity
},
debug: true
}
}
}
game = new Phaser.Game(gameConfig);
window.focus();
};
//Hero size to do calculations
var heroSize;
class playGame extends Phaser.Scene{
constructor(){
super("PlayGame");
}
preload() {
//Load background image
this.load.image('background', 'images/background.png');
//Load stationary textures for when Spider-Man is not moving
this.load.image('left', 'images/spiderman/run_left/0009.png');
this.load.image('right', 'images/spiderman/run_right/0013.png');
//Load hitboxes and the image sheet from TP and PE
this.load.atlas('sheet', 'assets/spiderTP.png', 'assets/spiderTP.json');
this.load.json('shapes', 'assets/spritesPE.json');
//Load level one
this.load.image('tiles', 'assets/tilesheet1.png');
this.load.tilemapTiledJSON('map', 'assets/level1.json');
}
create() {
//Place background image
let background = this.add.image(600, 375, 'background');
//Set boundaries for physics
this.matter.world.setBounds(0, 0, game.config.width, game.config.height);
//Create tilemap
const map = this.make.tilemap({key: 'map'});
//Load in the tileset used on the tilemap
const tileset = map.addTilesetImage('Assets_City', 'tiles');
//Load in the layer named 'Ground' from the tilemap
this.platforms = map.createDynamicLayer('Ground', tileset, 0, 0);
//Make the tiles collide
this.platforms.setCollisionBetween(1, 750);
//Convert the layer of platforms to bodies in phaser
this.matter.world.convertTilemapLayer(this.platforms);
//Make sure they collide
this.platforms.setCollisionByProperty({ collides: true});
//Label these for rope collisions
this.platforms.label = BOX;
this.platforms.isStatic
//Update the game at 30Hz
this.matter.world.update30Hz();
//Get hitboxes
this.shapes = this.cache.json.get('shapes');
//Player
this.hero = this.matter.add.sprite(600, 500, 'sheet', 'run_right/0013', {shape: this.shapes.s0009});
//Scale him down so he fits with terrain
this.hero.setScale(0.5, 0.5);
//Label the body for collisions
this.hero.label = HERO;
//Don't want him rotating in the air
this.hero.setFixedRotation();
//Set our variable to do calculations
heroSize = this.hero.width;
//No hook (start of the hook) to start off with
this.hook = null;
//Fire the hook on click
this.input.on("pointerdown", this.fireHook, this);
//No rope to start of with
this.rope = null;
//Listen for collisions with the hook
this.matter.world.on("collisionstart", function(e, b1, b2){
if((b1.label == HOOK || b2.label == HOOK) && !this.rope) {
Phaser.Physics.Matter.Matter.Body.setStatic(this.hook, true);
let distance = Phaser.Math.Distance.Between(this.hero.body.position.x, this.hero.body.position.y, this.hook.position.x, this.hook.position.y);
if (distance > heroSize * 2) { //Offset so that the hook comes from his hand {pointA: {x: 27.5, y: 10}}
this.rope = this.matter.add.constraint(this.hero, this.hook, distance, 0.5, {pointA: {x: 27.5, y: 5}});
}
}
}, this);
}
//Method for firing the hook
fireHook(e) {
if(this.hook) {
this.releaseHook();
}
else {
let angle = Phaser.Math.Angle.Between(this.hero.body.position.x, this.hero.body.position.y, e.position.x, e.position.y);
this.hook = this.matter.add.rectangle(this.hero.body.position.x + (heroSize * 2) * Math.cos(angle), this.hero.body.position.y + (heroSize * 2) * Math.sin(angle), 20, 20, '#ffffff');
this.hook.label = HOOK;
Phaser.Physics.Matter.Matter.Body.setVelocity(this.hook, {
x: gameOptions.hookSpeed * Math.cos(angle),
y: gameOptions.hookSpeed * Math.sin(angle)
});
}
}
releaseHook() {
if(this.rope) {
this.matter.world.removeConstraint(this.rope);
this.rope = null;
}
if(this.hook){
this.matter.world.remove(this.hook);
this.hook = null;
};
}
update() {
if(this.rope){
this.rope.length -= gameOptions.constraintSpeed;
let hookPosition = this.hook.position;
let distance = Phaser.Math.Distance.Between(hookPosition.x, hookPosition.y, this.hero.body.position.x, this.hero.body.position.y);
this.rope.length = Math.max(this.rope.length, (heroSize*2));
}
}
}
我试图复制的代码是https://www.emanueleferonato.com/2019/03/08/fling-unity-game-built-in-html5-with-phaser-and-matter-js-updated-with- the-latest-constraints-tweaks-fly-through-the-screen-with-your-ninja-rope/在这里,但我无法弄清楚哪个部分检测到钩子和另一个对象之间的碰撞。
解决方案
推荐阅读
- r - Broom::tidy 函数对 glm2 对象不起作用?
- python - 部署 python 烧瓶应用时 Heroku 错误代码=H10 状态=503
- .net - 有没有在 Heroku 中托管 Discord .Net Bot 的简单方法?
- python - Python函数不返回变量
- python - 由于多处理导致脚本之间的范围问题
- conditional-statements - Verilog:使用三元运算符的更有效方式
- python-3.x - 在类中创建和检查可逆矩阵
- python - 如何在 python 中向多个组发送 smtplib 电子邮件?
- java - Jersey HTTP Delete,Put 响应状态:405(不允许的方法)
- python - 使用 Python 读取 CSV 并根据列条件随时间绘制 5 个系列