[phaser] More example work, Stretchyman idle animation.

This commit is contained in:
Mario Zechner 2023-04-27 17:25:23 +02:00
parent bf3f70379f
commit 90e369fcfe
18 changed files with 273 additions and 189 deletions

View File

@ -358,12 +358,10 @@ cp -f ../coin/export/coin-pro.skel "$ROOT/spine-ts/spine-phaser/example/assets/"
cp -f ../coin/export/coin-pma.atlas "$ROOT/spine-ts/spine-phaser/example/assets/"
cp -f ../coin/export/coin-pma.png "$ROOT/spine-ts/spine-phaser/example/assets/"
cp -f ../stretchyman/export/stretchyman-pro.json "$ROOT/spine-ts/spine-phaser/example/assets/"
cp -f ../stretchyman/export/stretchyman-pro.skel "$ROOT/spine-ts/spine-phaser/example/assets/"
cp -f ../stretchyman/export/stretchyman-pma.atlas "$ROOT/spine-ts/spine-phaser/example/assets/"
cp -f ../stretchyman/export/stretchyman-pma.png "$ROOT/spine-ts/spine-phaser/example/assets/"
cp -f ../vine/export/vine-pro.skel "$ROOT/spine-ts/spine-phaser/example/assets/"
cp -f ../vine/export/vine-pma.atlas "$ROOT/spine-ts/spine-phaser/example/assets/"
cp -f ../vine/export/vine-pma.png "$ROOT/spine-ts/spine-phaser/example/assets/"
cp -f ../mix-and-match/export/mix-and-match-pro.json "$ROOT/spine-ts/spine-phaser/example/assets/"
cp -f ../mix-and-match/export/mix-and-match-pro.skel "$ROOT/spine-ts/spine-phaser/example/assets/"
cp -f ../mix-and-match/export/mix-and-match-pma.atlas "$ROOT/spine-ts/spine-phaser/example/assets/"
cp -f ../mix-and-match/export/mix-and-match-pma.png "$ROOT/spine-ts/spine-phaser/example/assets/"

View File

@ -3,14 +3,17 @@ stretchyman-pma.png
filter: Linear, Linear
pma: true
back-arm
bounds: 149, 45, 72, 202
bounds: 679, 173, 72, 202
rotate: 90
back-leg
bounds: 312, 4, 100, 318
bounds: 2, 2, 100, 318
rotate: 90
body
bounds: 223, 106, 141, 452
bounds: 2, 104, 141, 452
rotate: 90
front-arm
bounds: 2, 26, 145, 221
bounds: 456, 100, 145, 221
rotate: 90
head
bounds: 223, 2, 87, 102
bounds: 322, 15, 87, 102
rotate: 90

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 90 KiB

File diff suppressed because one or more lines are too long

View File

@ -2,14 +2,17 @@ stretchyman.png
size: 1024, 256
filter: Linear, Linear
back-arm
bounds: 149, 45, 72, 202
bounds: 679, 173, 72, 202
rotate: 90
back-leg
bounds: 312, 4, 100, 318
bounds: 2, 2, 100, 318
rotate: 90
body
bounds: 223, 106, 141, 452
bounds: 2, 104, 141, 452
rotate: 90
front-arm
bounds: 2, 26, 145, 221
bounds: 456, 100, 145, 221
rotate: 90
head
bounds: 223, 2, 87, 102
bounds: 322, 15, 87, 102
rotate: 90

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 97 KiB

View File

@ -19,19 +19,20 @@
<li>Phaser</li>
<ul>
<li><a href="/spine-phaser/example/basic-example.html">Basic example</a></li>
<li><a href="/spine-phaser/example/events-example.html">Events example</a></li>
<li><a href="/spine-phaser/example/mix-and-match-example.html">Mix and match example</a></li>
<li><a href="/spine-phaser/example/arcade-physics-example.html">Arcade physics example</a></li>
<li><a href="/spine-phaser/example/control-bones-example.html">Control bones example</a></li>
<li><a href="/spine-phaser/example/batching-test.html">Batching test</a></li>
<li><a href="/spine-phaser/example/multi-scene-test.html">Multi-scene test</a></li>
<li><a href="/spine-phaser/example/bounds-test.html">Bounds test</a></li>
<li><a href="/spine-phaser/example/visibility-test.html">Visibility test</a></li>
<li><a href="/spine-phaser/example/arcade-physics-test.html">Arcade physics example</a></li>
<li><a href="/spine-phaser/example/visibility-test.html">Visibility test</a></li>
<li><a href="/spine-phaser/example/blend-test.html">Blend test</a></li>
<li><a href="/spine-phaser/example/camera-pipeline-test.html">Camera pipeline test</a></li>
<li><a href="/spine-phaser/example/control-bones-test.html">Control bones</a></li>
<li><a href="/spine-phaser/example/camera-pipeline-test.html">Camera pipeline test</a></li>
<li><a href="/spine-phaser/example/extended-class-test.html">Extended class</a></li>
<li><a href="/spine-phaser/example/canvas-test.html">Canvas test</a></li>
<li><a href="/spine-phaser/example/depth-test.html">Depth test</a></li>
<li><a href="/spine-phaser/example/render-to-texture-test.html">Render to texture test</a></li>
<li><a href="/spine-phaser/example/mix-and-match.html">Mix and match</a></li>
<li><a href="/spine-phaser/example/depth-test.html">Depth test</a></li>
<li><a href="/spine-phaser/example/render-to-texture-test.html">Render to texture test</a></li>
</ul>
<li>Player</li>
<ul>

View File

@ -0,0 +1,61 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
<script src="../dist/iife/spine-phaser.js"></script>
<title>Spine Phaser Example</title>
</head>
<body>
<h1>Arcade Physics example</h1>
</body>
<script>
class PhysicsExample extends Phaser.Scene {
preload() {
this.load.spineBinary("coin-data", "assets/coin-pro.skel");
this.load.spineAtlas("coin-atlas", "assets/coin-pma.atlas");
}
create() {
const coin = this.add.spine(400, 200, 'coin-data', "coin-atlas");
coin.animationState.setAnimation(0, "animation", true);
coin.setScale(0.3);
coin.setSize(280, 280);
this.physics.add.existing(coin);
coin.body.setOffset(0, 50);
coin.body.setVelocity(100, 200);
coin.body.setBounce(1, 1);
coin.body.setCollideWorldBounds(true);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
type: Phaser.WEBGL,
physics: {
default: 'arcade',
arcade: {
debug: true,
gravity: { y: 200 }
}
},
scene: [PhysicsExample],
plugins: {
scene: [
{ key: "spine.SpinePlugin", plugin: spine.SpinePlugin, mapping: "spine" }
]
}
};
const game = new Phaser.Game(config);
</script>
</html>

View File

@ -1,61 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
<title>Spine Phaser Example</title>
</head>
<body>
<h1>Arcade Physics example</h1>
</body>
<script>
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
type: Phaser.WEBGL,
physics: {
default: 'arcade',
arcade: {
debug: true,
gravity: { y: 200 }
}
},
scene: {
preload: preload,
create: create,
pack: {
files: [
{ type: "scenePlugin", key: "spine.SpinePlugin", url: "../dist/iife/spine-phaser.js", sceneKey: "spine" }
]
}
}
};
const game = new Phaser.Game(config);
function preload() {
this.load.spineBinary("coin-data", "assets/coin-pro.skel");
this.load.spineAtlas("coin-atlas", "assets/coin-pma.atlas");
}
function create() {
const coin = this.add.spine(400, 200, 'coin-data', "coin-atlas");
coin.animationState.setAnimation(0, "animation", true);
coin.setScale(0.3);
coin.setSize(280, 280);
this.physics.add.existing(coin);
coin.body.setOffset(0, 50);
coin.body.setVelocity(100, 200);
coin.body.setBounce(1, 1);
coin.body.setCollideWorldBounds(true);
}
</script>
</html>

View File

@ -24,16 +24,11 @@
const spineboy = this.add.spine(400, 500, 'spineboy-data', "spineboy-atlas");
spineboy.scale = 0.5;
spineboy.animationState.setAnimation(0, "walk", true);
const spineboy2 = this.make.spine({
x: 200, y: 500, dataKey: "spineboy-data", atlasKey: "spineboy-atlas"
});
this.add.existing(spineboy2);
}
}
const config = {
type: Phaser.AUTO,
new Phaser.Game({
type: Phaser.AUTO,
width: 800,
height: 600,
type: Phaser.WEBGL,
@ -43,9 +38,7 @@
{ key: "spine.SpinePlugin", plugin: spine.SpinePlugin, mapping: "spine" }
]
}
};
const game = new Phaser.Game(config);
});
</script>
</html>

View File

@ -14,15 +14,25 @@
<h1>Basic example</h1>
</body>
<script>
class BasicExample extends Phaser.Scene {
preload() {
this.load.spineBinary("spineboy-data", "assets/spineboy-pro.skel");
this.load.spineAtlas("spineboy-atlas", "assets/spineboy-pma.atlas");
}
create() {
const spineboy = this.add.spine(400, 500, 'spineboy-data', "spineboy-atlas");
spineboy.scale = 0.5;
spineboy.animationState.setAnimation(0, "walk", true);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
type: Phaser.WEBGL,
scene: {
preload: preload,
create: create,
},
scene: [BasicExample],
plugins: {
scene: [
{ key: "spine.SpinePlugin", plugin: spine.SpinePlugin, mapping: "spine" }
@ -31,17 +41,6 @@
};
const game = new Phaser.Game(config);
function preload() {
this.load.spineBinary("spineboy-data", "assets/spineboy-pro.skel");
this.load.spineAtlas("spineboy-atlas", "assets/spineboy-pma.atlas");
}
function create() {
const spineboy = this.add.spine(400, 500, 'spineboy-data', "spineboy-atlas");
spineboy.scale = 0.5;
spineboy.animationState.setAnimation(0, "walk", true);
}
</script>
</html>

View File

@ -0,0 +1,72 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
<script src="../dist/iife/spine-phaser.js"></script>
<title>Spine Phaser Example</title>
</head>
<body>
<h1>Control bones</h1>
<script>
class ControlBonesExample extends Phaser.Scene {
preload() {
this.load.spineBinary("stretchyman-data", "assets/stretchyman-pro.skel");
this.load.spineAtlas("stretchyman-atlas", "assets/stretchyman-pma.atlas");
}
create() {
const stretchyman = this.add.spine(400, 580, 'stretchyman-data', "stretchyman-atlas");
stretchyman.animationState.setEmptyAnimation(0, true);
stretchyman.updatePose(0);
const controlBoneNames = ["back-arm-ik-target", "back-leg-ik-target", "front-arm-ik-target", "front-leg-ik-target"];
const controlBones = [];
for (var i = 0; i < controlBoneNames.length; i++) {
const bone = stretchyman.skeleton.findBone(controlBoneNames[i]);
const point = { x: bone.worldX, y: bone.worldY };
stretchyman.skeletonToPhaserWorldCoordinates(point);
const control = this.add.circle(point.x, point.y, 4, 0xff00ff).setData('bone', bone);
controlBones.push(control);
control.setInteractive();
this.input.setDraggable(control);
this.input.on('drag', function (pointer, gameObject, dragX, dragY) {
gameObject.x = dragX;
gameObject.y = dragY;
}, this);
}
stretchyman.beforeUpdateWorldTransforms = () => {
for (let controlBone of controlBones) {
const bone = controlBone.getData('bone');
const point = { x: controlBone.x, y: controlBone.y};
stretchyman.phaserWorldCoordinatesToBone(point, bone);
bone.x = point.x;
bone.y = point.y;
}
}
}
}
new Phaser.Game({
type: Phaser.AUTO,
width: 800,
height: 600,
type: Phaser.WEBGL,
scene: [ControlBonesExample],
plugins: {
scene: [
{ key: "spine.SpinePlugin", plugin: spine.SpinePlugin, mapping: "spine" }
]
}
});
</script>
</body>
</html>

View File

@ -1,70 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
<title>Spine Phaser Example</title>
</head>
<body>
<h1>Control bones</h1>
<script>
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
type: Phaser.WEBGL,
scene: {
preload: preload,
create: create,
pack: {
files: [
{ type: "scenePlugin", key: "spine.SpinePlugin", url: "../dist/iife/spine-phaser.js", sceneKey: "spine" }
]
}
}
};
const game = new Phaser.Game(config);
function preload() {
this.load.spineBinary("stretchyman-data", "assets/stretchyman-pro.skel");
this.load.spineAtlas("stretchyman-atlas", "assets/stretchyman-pma.atlas");
}
function create() {
const stretchyman = this.add.spine(400, 550, 'stretchyman-data', "stretchyman-atlas");
stretchyman.scale = 0.8;
stretchyman.skeleton.updateWorldTransform();
const controlBones = ["back-arm-ik-target", "back-leg-ik-target", "front-arm-ik-target", "front-leg-ik-target"];
for (var i = 0; i < controlBones.length; i++) {
const bone = stretchyman.skeleton.findBone(controlBones[i]);
const point = { x: bone.worldX, y: bone.worldY };
stretchyman.skeletonToPhaserWorldCoordinates(point);
const control = this.add.circle(point.x, point.y, 4, 0xff00ff).setData('bone', bone);
control.setInteractive();
this.input.setDraggable(control);
this.input.on('drag', function (pointer, gameObject, dragX, dragY) {
gameObject.x = dragX;
gameObject.y = dragY;
const bone = gameObject.getData('bone');
const point = { x: dragX, y: dragY };
stretchyman.phaserWorldCoordinatesToBone(point, bone);
bone.x = point.x;
bone.y = point.y;
bone.update();
}, this);
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,70 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
<script src="../dist/iife/spine-phaser.js"></script>
<title>Spine Phaser Example</title>
</head>
<body>
<h1>Events example</h1>
<div style="display: flex; flex-direction: column; width: 800px">
<canvas id="game" width="800" height="600"></canvas>
<textarea id="log" style="height: 10em;"></textarea>
</div>
</body>
<script>
function log(message) {
let log = document.querySelector("#log");
log.textContent += message + "\n";
log.scrollTop = log.scrollHeight;
console.log(message);
}
class EventsExample extends Phaser.Scene {
preload() {
this.load.spineBinary("spineboy-data", "assets/spineboy-pro.skel");
this.load.spineAtlas("spineboy-atlas", "assets/spineboy-pma.atlas");
}
create() {
const spineboy = this.add.spine(400, 500, 'spineboy-data', "spineboy-atlas");
spineboy.scale = 0.5;
spineboy.animationState.addListener({
start: (entry) => log(`Started animation ${entry.animation.name}`),
interrupt: (entry) => log(`Interrupted animation ${entry.animation.name}`),
end: (entry) => log(`Ended animation ${entry.animation.name}`),
dispose: (entry) => log(`Disposed animation ${entry.animation.name}`),
complete: (entry) => log(`Completed animation ${entry.animation.name}`),
})
spineboy.animationState.setAnimation(0, "walk", true);
const trackEntry = spineboy.animationState.addAnimation(0, "run", 3, true);
trackEntry.listener = {
event: (entry, event) => log(`Custom event for ${entry.animation.name}: ${event.data.name}`)
}
}
}
const config = {
canvas: document.querySelector("#game"),
width: 800,
height: 600,
type: Phaser.WEBGL,
scene: [EventsExample],
plugins: {
scene: [
{ key: "spine.SpinePlugin", plugin: spine.SpinePlugin, mapping: "spine" }
]
}
};
const game = new Phaser.Game(config);
</script>
</html>

View File

@ -96,7 +96,8 @@ export class SpineGameObject extends ComputedSizeMixin(DepthMixin(FlipMixin(Scro
this.skeleton = this.plugin.createSkeleton(dataKey, atlasKey);
this.animationStateData = new AnimationStateData(this.skeleton.data);
this.animationState = new AnimationState(this.animationStateData);
this.updateSize();
this.skeleton.updateWorldTransform();
this.updateSize();
}
public get displayOriginX () {
@ -172,9 +173,7 @@ export class SpineGameObject extends ComputedSizeMixin(DepthMixin(FlipMixin(Scro
}
}
preUpdate (time: number, delta: number) {
if (!this.skeleton || !this.animationState) return;
updatePose(delta: number) {
this.animationState.update(delta / 1000);
this.animationState.apply(this.skeleton);
this.beforeUpdateWorldTransforms(this);
@ -182,6 +181,11 @@ export class SpineGameObject extends ComputedSizeMixin(DepthMixin(FlipMixin(Scro
this.afterUpdateWorldTransforms(this);
}
preUpdate (time: number, delta: number) {
if (!this.skeleton || !this.animationState) return;
this.updatePose();
}
preDestroy () {
// FIXME tear down any event emitters
}