[ts][phaser-v3][phaser-v4] Fixed gameobject position when it is rotated.

This commit is contained in:
Davide Tantillo 2025-04-23 17:00:21 +02:00
parent 878a658ea9
commit 15766e8ef2
4 changed files with 130 additions and 14 deletions

View File

@ -13,12 +13,15 @@
<body class="p-4 flex flex-col items-center">
<h1>Move origin</h1>
<h2>Demonstrate moving origin of Spine Gameobject, behaves like a sprite</h2>
<h2>When you use matter physics, origin is reset, because the body always stays around the game object.
Change game object size only after the object has been added to matter.</h2>
</body>
<script>
let cursors;
let spineboy;
const levelWidth = 800;
const levelHeight = 600;
const gameobjects = []
class BasicExample extends Phaser.Scene {
preload() {
@ -51,6 +54,7 @@
}
}
const physicsCells = cells.splice(cells.length - 2, 2);
let animations = undefined;
let prevWidth = 0;
@ -80,6 +84,8 @@
prevHeight = gameobject.displayHeight;
}
gameobjects.push(gameobject)
// moving origin at the center of the cell, we're still able to align spineboy and keep gameobject bounds align with the drawn skeleton
const origin = 1 / (cells.length / 2 - 1) * Math.floor(i / 2)
@ -122,17 +128,69 @@
gameobject.on("pointerout", () => defaultGraphicsElements());
})
const [physicsCell1, physicsCell2] = physicsCells;
const spineboy = this.add.spine(0, 0, "spineboy-data", "spineboy-atlas");
this.matter.add.gameObject(spineboy);
spineboy.displayWidth = (spineboy.width / spineboy.height) * height * .5;
spineboy.displayHeight = height * .5;
spineboy.x = physicsCell1.x + spineboy.displayWidth;
spineboy.y = physicsCell1.y + spineboy.displayHeight;
spineboy.setInteractive();
this.input.enableDebug(spineboy, 0xff00ff);
spineboy.on("pointerover", () => {
spineboy.y -= 50;
spineboy.x += 10;
});
const block = this.add.image(0, 0, "block");
this.matter.add.gameObject(block);
block.displayWidth = (block.width / block.height) * height * .5;
block.displayHeight = height * .5;
block.x = physicsCell2.x + block.displayWidth;
block.y = physicsCell2.y + block.displayHeight;
block.setInteractive();
this.input.enableDebug(block, 0xff00ff);
block.on("pointerover", () => {
block.y -= 50;
block.x += 10;
});
this.matter.add.rectangle(levelWidth - width, levelHeight - height, levelWidth, 1, { isStatic: true });
this.matter.add.rectangle(levelWidth - width, levelHeight - 2 * height, levelWidth, 1, { isStatic: true });
this.matter.add.rectangle(levelWidth - width, levelHeight, levelWidth, 1, { isStatic: true });
this.matter.add.rectangle(levelWidth - width, levelHeight - 2 * height, 1, height * 4, { isStatic: true });
this.matter.add.rectangle(levelWidth, levelHeight - 2 * height, 1, height * 4, { isStatic: true });
}
update(params) {
gameobjects.forEach((go) => {
go.angle += 0.05;
})
}
}
new Phaser.Game({
type: Phaser.AUTO,
width: levelWidth,
height: levelHeight,
type: Phaser.WEBGL,
scene: [BasicExample],
physics: {
default: 'matter',
matter: {
debug: true,
gravity: { y: .15 },
},
},
plugins: {
scene: [
{

View File

@ -369,8 +369,8 @@ export class SpineGameObject extends DepthMixin(
tx = transform.tx,
ty = transform.ty;
let offsetX = (src.offsetX - src.displayOriginX) * src.scaleX;
let offsetY = (src.offsetY - src.displayOriginY) * src.scaleY;
let offsetX = src.offsetX - src.displayOriginX;
let offsetY = src.offsetY - src.displayOriginY;
sceneRenderer.drawSkeleton(
src.skeleton,
@ -379,10 +379,10 @@ export class SpineGameObject extends DepthMixin(
-1,
(vertices, numVertices, stride) => {
for (let i = 0; i < numVertices; i += stride) {
let vx = vertices[i];
let vy = vertices[i + 1];
vertices[i] = vx * a + vy * c + tx + offsetX;
vertices[i + 1] = vx * b + vy * d + ty + offsetY;
let vx = vertices[i] + offsetX;
let vy = vertices[i + 1] + offsetY;
vertices[i] = vx * a + vy * c + tx;
vertices[i + 1] = vx * b + vy * d + ty;
}
}
);

View File

@ -13,12 +13,15 @@
<body class="p-4 flex flex-col items-center">
<h1>Move origin</h1>
<h2>Demonstrate moving origin of Spine Gameobject, behaves like a sprite</h2>
<h2>When you use matter physics, origin is reset, because the body always stays around the game object.
Change game object size only after the object has been added to matter.</h2>
</body>
<script>
let cursors;
let spineboy;
const levelWidth = 800;
const levelHeight = 600;
const gameobjects = []
class BasicExample extends Phaser.Scene {
preload() {
@ -51,6 +54,7 @@
}
}
const physicsCells = cells.splice(cells.length - 2, 2);
let animations = undefined;
let prevWidth = 0;
@ -80,6 +84,8 @@
prevHeight = gameobject.displayHeight;
}
gameobjects.push(gameobject)
// moving origin at the center of the cell, we're still able to align spineboy and keep gameobject bounds align with the drawn skeleton
const origin = 1 / (cells.length / 2 - 1) * Math.floor(i / 2)
@ -122,17 +128,69 @@
gameobject.on("pointerout", () => defaultGraphicsElements());
})
const [physicsCell1, physicsCell2] = physicsCells;
const spineboy = this.add.spine(0, 0, "spineboy-data", "spineboy-atlas");
this.matter.add.gameObject(spineboy);
spineboy.displayWidth = (spineboy.width / spineboy.height) * height * .5;
spineboy.displayHeight = height * .5;
spineboy.x = physicsCell1.x + spineboy.displayWidth;
spineboy.y = physicsCell1.y + spineboy.displayHeight;
spineboy.setInteractive();
this.input.enableDebug(spineboy, 0xff00ff);
spineboy.on("pointerover", () => {
spineboy.y -= 50;
spineboy.x += 10;
});
const block = this.add.image(0, 0, "block");
this.matter.add.gameObject(block);
block.displayWidth = (block.width / block.height) * height * .5;
block.displayHeight = height * .5;
block.x = physicsCell2.x + block.displayWidth;
block.y = physicsCell2.y + block.displayHeight;
block.setInteractive();
this.input.enableDebug(block, 0xff00ff);
block.on("pointerover", () => {
block.y -= 50;
block.x += 10;
});
this.matter.add.rectangle(levelWidth - width, levelHeight - height, levelWidth, 1, { isStatic: true });
this.matter.add.rectangle(levelWidth - width, levelHeight - 2 * height, levelWidth, 1, { isStatic: true });
this.matter.add.rectangle(levelWidth - width, levelHeight, levelWidth, 1, { isStatic: true });
this.matter.add.rectangle(levelWidth - width, levelHeight - 2 * height, 1, height * 4, { isStatic: true });
this.matter.add.rectangle(levelWidth, levelHeight - 2 * height, 1, height * 4, { isStatic: true });
}
update(params) {
gameobjects.forEach((go) => {
go.angle += 0.05;
})
}
}
new Phaser.Game({
type: Phaser.AUTO,
width: levelWidth,
height: levelHeight,
type: Phaser.WEBGL,
scene: [BasicExample],
physics: {
default: 'matter',
matter: {
debug: true,
gravity: { y: .15 },
},
},
plugins: {
scene: [
{

View File

@ -388,8 +388,8 @@ export class SpineGameObject extends DepthMixin(
tx = transform.tx,
ty = transform.ty;
let offsetX = (src.offsetX - src.displayOriginX) * src.scaleX;
let offsetY = (src.offsetY - src.displayOriginY) * src.scaleY;
let offsetX = src.offsetX - src.displayOriginX;
let offsetY = src.offsetY - src.displayOriginY;
sceneRenderer.drawSkeleton(
src.skeleton,
@ -398,10 +398,10 @@ export class SpineGameObject extends DepthMixin(
-1,
(vertices, numVertices, stride) => {
for (let i = 0; i < numVertices; i += stride) {
let vx = vertices[i];
let vy = vertices[i + 1];
vertices[i] = vx * a + vy * c + tx + offsetX;
vertices[i + 1] = vx * b + vy * d + ty + offsetY;
let vx = vertices[i] + offsetX;
let vy = vertices[i + 1] + offsetY;
vertices[i] = vx * a + vy * c + tx;
vertices[i + 1] = vx * b + vy * d + ty;
}
}
);