2025-07-16 01:35:13 +02:00

223 lines
7.4 KiB
Haxe

/******************************************************************************
* Spine Runtimes License Agreement
* Last updated April 5, 2025. Replaces all prior versions.
*
* Copyright (c) 2013-2025, Esoteric Software LLC
*
* Integration of the Spine Runtimes into software or otherwise creating
* derivative works of the Spine Runtimes is permitted under the terms and
* conditions of Section 2 of the Spine Editor License Agreement:
* http://esotericsoftware.com/spine-editor-license
*
* Otherwise, it is permitted to integrate the Spine Runtimes into software
* or otherwise create derivative works of the Spine Runtimes (collectively,
* "Products"), provided that each user of the Products must obtain their own
* Spine Editor license and redistribution of the Products in any form must
* include this license and copyright notice.
*
* THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
* BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
package flixelExamples;
import flixel.ui.FlxButton;
import flixel.group.FlxSpriteGroup;
import flixel.FlxSprite;
import flixel.graphics.FlxGraphic;
import spine.animation.AnimationStateData;
import openfl.Assets;
import spine.atlas.TextureAtlas;
import spine.SkeletonData;
import spine.flixel.SkeletonSprite;
import spine.flixel.FlixelTextureLoader;
import flixel.FlxG;
import flixel.FlxState;
import flixel.text.FlxText;
class FlixelState extends FlxState {
var spineSprite:SkeletonSprite;
var sprite:FlxSprite;
var sprite2:FlxSprite;
var myText:FlxText;
var group:FlxSpriteGroup;
var justSetWalking = false;
var jumping = false;
var scale = 4;
var speed:Float;
override public function create():Void {
FlxG.cameras.bgColor = 0xffa1b2b0;
// setting speed of spineboy (450 is the speed to not let him slide)
speed = 450 / scale;
// creating a group
group = new FlxSpriteGroup();
group.setPosition(50, 50);
add(group);
// creating the sprite to check overlapping
sprite = new FlxSprite();
sprite.loadGraphic(FlxGraphic.fromRectangle(150, 100, 0xff8d008d));
group.add(sprite);
// creating the text to display overlapping state
myText = new FlxText(0, 25, 150, "", 16);
myText.alignment = CENTER;
group.add(myText);
var button = new FlxButton(0, 0, "Next scene", () -> FlxG.switchState(() -> new BasicExample()));
button.setPosition(FlxG.width * .75, FlxG.height / 10);
add(button);
// creating a sprite for the floor
var floor = new FlxSprite();
floor.loadGraphic(FlxGraphic.fromRectangle(FlxG.width, FlxG.height - 100, 0xff822f02));
floor.y = FlxG.height - 100;
add(floor);
// instructions
var groupInstructions = new FlxSpriteGroup();
groupInstructions.setPosition(50, 405);
groupInstructions.add(new FlxText(0, 0, 200, "Left/Right - Move", 16));
groupInstructions.add(new FlxText(0, 25, 150, "Space - Jump", 16));
groupInstructions.add(new FlxText(200, 25, 400, "Click the button for the next example", 16));
add(groupInstructions);
// loading spineboy
var atlas = new TextureAtlas(Assets.getText("assets/spineboy.atlas"), new FlixelTextureLoader("assets/spineboy.atlas"));
var skeletondata = SkeletonData.from(Assets.getText("assets/spineboy-pro.json"), atlas, 1 / scale);
var animationStateData = new AnimationStateData(skeletondata);
spineSprite = new SkeletonSprite(skeletondata, animationStateData);
// positioning spineboy
spineSprite.setPosition(.5 * FlxG.width, .5 * FlxG.height);
// setting mix times
animationStateData.defaultMix = 0.5;
animationStateData.setMixByName("idle", "walk", 0.1);
animationStateData.setMixByName("walk", "idle", 0.1);
animationStateData.setMixByName("idle", "idle-turn", 0.05);
animationStateData.setMixByName("idle-turn", "idle", 0.05);
animationStateData.setMixByName("idle-turn", "walk", 0.3);
animationStateData.setMixByName("idle", "jump", 0);
animationStateData.setMixByName("jump", "idle", 0.05);
animationStateData.setMixByName("jump", "walk", 0.05);
animationStateData.setMixByName("walk", "jump", 0.05);
// setting idle animation
spineSprite.state.setAnimationByName(0, "idle", true);
// setting y offset function to move object body while jumping
var hip = spineSprite.skeleton.findBone("hip");
var initialY = 0.;
var initialOffsetY = 0.;
spineSprite.state.onStart.add(entry -> {
if (entry.animation.name == "jump") {
initialY = spineSprite.y;
initialOffsetY = spineSprite.offsetY;
}
});
spineSprite.state.onComplete.add(entry -> {
if (entry.animation.name == "jump") {
jumping = false;
spineSprite.y = initialY;
spineSprite.offsetY = initialOffsetY;
}
});
var diff = .0;
spineSprite.afterUpdateWorldTransforms = spineSprite -> {
if (jumping) {
diff -= hip.pose.y;
spineSprite.offsetY -= diff;
spineSprite.y += diff;
}
diff = hip.pose.y;
}
// adding spineboy to the stage
add(spineSprite);
// FlxG.debugger.visible = !FlxG.debugger.visible;
// debug ui
// FlxG.debugger.visible = true;
// FlxG.debugger.drawDebug = true;
// FlxG.log.redirectTraces = true;
// FlxG.debugger.track(spineSprite);
// FlxG.watch.add(spineSprite, "width");
// FlxG.watch.add(spineSprite, "offsetY");
// FlxG.watch.add(spineSprite, "y");
// FlxG.watch.add(this, "jumping");
super.create();
}
var justSetIdle = true;
override public function update(elapsed:Float):Void {
if (FlxG.overlap(spineSprite, group)) {
myText.text = "Overlapping";
} else {
myText.text = "Non overlapping";
}
if (!jumping && FlxG.keys.anyJustPressed([SPACE])) {
spineSprite.state.setAnimationByName(0, "jump", false);
jumping = true;
justSetIdle = false;
justSetWalking = false;
}
if (FlxG.keys.anyJustPressed([J])) {
// spineSprite.antialiasing = !spineSprite.antialiasing;
FlxG.debugger.visible = !FlxG.debugger.visible;
}
if (FlxG.keys.anyPressed([RIGHT, LEFT])) {
justSetIdle = false;
var flipped = false;
var deltaX;
if (FlxG.keys.anyPressed([RIGHT])) {
if (spineSprite.flipX == true)
flipped = true;
spineSprite.flipX = false;
}
if (FlxG.keys.anyPressed([LEFT])) {
if (spineSprite.flipX == false)
flipped = true;
spineSprite.flipX = true;
}
deltaX = (spineSprite.flipX == false ? 1 : -1) * speed * elapsed;
spineSprite.x += deltaX;
if (!jumping && !justSetWalking) {
justSetWalking = true;
if (flipped) {
spineSprite.state.setAnimationByName(0, "idle-turn", false);
spineSprite.state.addAnimationByName(0, "walk", true, 0);
} else {
spineSprite.state.setAnimationByName(0, "walk", true);
}
}
} else if (!jumping && !justSetIdle) {
justSetWalking = false;
justSetIdle = true;
spineSprite.state.setAnimationByName(0, "idle", true);
}
super.update(elapsed);
}
}