提问人:Vololodymyr 提问时间:10/2/2023 最后编辑:winner_joinerVololodymyr 更新时间:10/5/2023 访问量:39
如果一个对象不在屏幕中并且它被用于其他对象的光线投射器,如何删除它?
How to delete an object if its out of screen and it was used in raycasters of other objects?
问:
在我的主游戏类中,我有一种方法,它可以动态地创建一辆汽车并遍历其他汽车,并在彼此之间映射光线投射(因此汽车可以检测彼此之间的距离):createCar
createCar(scene, x, y, angle, speed, name) {
const car = new Car(scene, x, y, angle, speed);
car.name = name; // for debug
this.carsGroup.children.iterate((c) => {
c.raycaster.mapGameObjects(car, true);
car.raycaster.mapGameObjects(c, true);
});
this.carsGroup.add(car);
}
它有效,除非我想删除一辆车:
update() {
this.carsGroup.children.iterate((car) => {
// Car is out of screen
if (!this.cameras.main.worldView.contains(car.x, car.y)) {
this.carsGroup.remove(car);
this.carsGroup.children.iterate((c) => {
c.raycaster.removeMappedObjects(car);
car.raycaster.removeMappedObjects(c);
});
car.destroy();
} else {
car.update();
car.debug();
}
});
}
然后,当它在内部尝试检索“raycasterMap”并销毁它时,它在这里失败了:
object.data.get('raycasterMap').destroy();
raycaster-core.js:396 未捕获的类型错误:无法读取未定义的属性(读取“销毁”) 在 Raycaster.removeMappedObjects (raycaster-core.js:396:48) 在游戏.js:51:23
我不知道如何正确地从场景和内存中删除汽车。
如果我只是调用其他汽车,则会引发异常,因为光线投射仍然有参考。car.destroy()
完整的 codepen 示例:https://codepen.io/vvyshko/pen/bGOxpbG
答:
1赞
winner_joiner
10/3/2023
#1
我认为问题是,清理不是最佳的。我建议,将清理放入 - 类的函数中,并在场景的函数中添加验证,检查 - 子项是否为有效对象,destroy
car
update
car
以下是改动:
class Car extends Phaser.Physics.Arcade.Sprite {
// ...
destroy(){
super.destroy();
// Cleanup data
this.ray.destroy();
this.raycaster.destroy();
}
// ...
}
class Example extends Phaser.Scene {
//...
update() {
this.carsGroup.children.iterate((car) => {
// Check if the list item is valid
if (!car) {
return;
}
if (!this.cameras.main.worldView.contains(car.x, car.y)) {
// Remove Car from Group and destroy Object
this.carsGroup.remove(car, true, true);
} else {
car.update();
car.debug();
}
});
}
}
代码复制和改编自 Codepen:
class Car extends Phaser.Physics.Arcade.Sprite {
constructor(scene, x, y, rotation, speed) {
super(scene, x, y, "car");
this.debugGraphics = scene.add.graphics();
this.speed = speed;
this.initialSpeed = speed;
this.rayLength = 100;
this.rayColor = 0xffffff;
this.rotation = rotation;
this.setDisplaySize(130, 80);
this.debugColor = new Phaser.Display.Color();
// Set the color to a random value
this.debugColor.random();
// Create a raycaster for the car
this.raycaster = scene.raycasterPlugin.createRaycaster();
// Create a ray for the car
this.ray = this.raycaster.createRay();
// Set the ray origin to the car position
this.ray.setOrigin(this.x, this.y);
// Set the ray angle to the car angle
this.ray.setAngle(this.rotation);
scene.physics.world.enable(this); // Enable physics for the car
scene.add.existing(this); // Add the car to the scene
//this.raycaster.mapGameObjects(scene.rectangle);
}
update() {
// console.log('update', this.name, this.speed);
window.lastUpdatedCar = this;
this.raycaster.update();
// Move the car forward
this.scene.physics.velocityFromRotation(
this.rotation,
this.speed,
this.body.velocity
);
// Update the ray origin and angle
this.ray.setOrigin(this.x, this.y);
this.ray.setAngle(this.rotation);
// Cast the ray and get the intersection
// console.log(this.name, 'removed=', this.removed)
let intersection ;
try {
intersection = this.ray.cast()
} catch (e) {}
this.intersection = intersection;
// If there is an intersection, reduce the speed or stop
if (intersection) {
// console.log('!!!', intersection)
}
if (this.crashed) {
this.setTint(0x555888);
this.speed = 0;
} else if (intersection && intersection.object) {
// console.log('!!!', intersection)
let distance = Phaser.Math.Distance.BetweenPoints(this, intersection);
if (distance < this.rayLength) {
// Determine a deceleration rate (you can adjust this value)
const decelerationRate = 1; // Adjust as needed
// Calculate the new speed with deceleration
this.speed -= decelerationRate;
// Ensure the speed doesn't become negative
if (this.speed < 0) {
this.speed = 0;
}
} else {
if (this.speed < this.initialSpeed) {
this.speed++;
}
}
}
}
handleCollision(o1, o2) {
console.log('CRASH', o1, o2)
o1.crashed = true;
o2.crashed = true;
}
debug() {
this.debugGraphics.clear();
this.debugGraphics.setDepth(this.depth + 1); // Set the depth
this.debugGraphics.lineStyle(1, this.debugColor.color);
this.debugGraphics.beginPath();
this.debugGraphics.moveTo(this.x, this.y);
this.debugGraphics.lineTo(
this.x + Math.cos(this.rotation) * this.rayLength,
this.y + Math.sin(this.rotation) * this.rayLength
);
this.debugGraphics.closePath();
this.debugGraphics.strokePath();
if (this.intersection) {
this.debugGraphics.fillStyle(0xff0000, 0.5);
this.debugGraphics.strokeCircle(
this.intersection.x,
this.intersection.y,
5
);
}
if (this.crashed) {
// Draw a red cross
this.debugGraphics.lineStyle(2, 0xff0000);
this.debugGraphics.beginPath();
this.debugGraphics.moveTo(this.x - 10, this.y - 10);
this.debugGraphics.lineTo(this.x + 10, this.y + 10);
this.debugGraphics.moveTo(this.x + 10, this.y - 10);
this.debugGraphics.lineTo(this.x - 10, this.y + 10);
this.debugGraphics.closePath();
this.debugGraphics.strokePath();
}
}
destroy(){
super.destroy();
// Cleanup data
//this.ray.destroy();
//this.raycaster.destroy();
}
}
class Example extends Phaser.Scene {
constructor() {
super();
}
preload() {
this.load.setBaseURL("https://labs.phaser.io");
this.load.image("bg", "assets/skies/space2.png");
this.load.image("car", "assets/sprites/car-yellow.png");
window.scene = this;
}
create() {
const bg = this.add.image(0, 0, "bg");
bg.setOrigin(0, 0); // Set the origin to the top-left corner
bg.displayWidth = this.sys.game.config.width; // Stretch width to match canvas width
bg.displayHeight = this.sys.game.config.height;
// //create game object
// this.rectangle = this.add
// .rectangle(1000, 300, 50, 200)
// .setStrokeStyle(1, 0xff0000);
this.carsGroup = this.physics.add.group();
window.carsGroup = this.carsGroup;
this.createCar(this, 100, 300, 0, 10, "A");
this.createCar(this, 600, 600, -1, 270, "B");
this.createCar(this, 400, 300, -0.44, 10, "C");
this.createCar(this, 600, 700, 0, 170, "D");
// this.createCar(this, 700, 600, -1.44, 120);
}
createCar(scene, x, y, angle, speed, name) {
const car = new Car(scene, x, y, angle, speed);
car.name = name; // for debug
this.carsGroup.children.iterate((c) => {
c.raycaster.mapGameObjects(car, true);
car.raycaster.mapGameObjects(c, true);
c.scene.physics.add.collider(c, car, c.handleCollision);
car.scene.physics.add.collider(car, c, car.handleCollision);
});
this.carsGroup.add(car);
}
update() {
this.carsGroup.children.iterate((car) => {
// Check if the list item is valid
if (!car) {
return;
}
if (!this.cameras.main.worldView.contains(car.x, car.y)) {
// Remove Car from Group and destroy Object
this.carsGroup.remove(car, true, true);
} else {
car.update();
car.debug();
}
});
}
}
const config = {
type: Phaser.WEBGL,
width: 1280,
height: 1024,
parent: "phaser-example",
physics: {
default: "arcade",
},
plugins: {
scene: [
{
key: "PhaserRaycaster",
plugin: PhaserRaycaster,
mapping: "raycasterPlugin",
},
],
},
scene: Example,
};
const game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/phaser-arcade-physics.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/phaser-raycaster.js"></script>
评论
cast.js:72 Uncaught TypeError: Cannot read properties of undefined (reading 'get') at Ray.cast (cast.js:72:31) at Car.update (car.js:47:33)
destroy
destroy