package com.cookbook.samples; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.graphics.g2d.TextureAtlas.TextureAtlasData; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; import com.badlogic.gdx.utils.viewport.FitViewport; import com.badlogic.gdx.utils.viewport.Viewport; import com.esotericsoftware.spine.AnimationState; import com.esotericsoftware.spine.AnimationStateData; import com.esotericsoftware.spine.Skeleton; import com.esotericsoftware.spine.SkeletonBinary; import com.esotericsoftware.spine.SkeletonData; import com.esotericsoftware.spine.SkeletonJson; import com.esotericsoftware.spine.SkeletonRenderer; import com.esotericsoftware.spine.SkeletonRendererDebug; public class SpineSample extends GdxSample { private static final String TAG = "SpineSample"; private static final float SCENE_WIDTH = 12.80f; private static final float SCENE_HEIGHT = 7.20f; private OrthographicCamera camera; private Viewport viewport; private SpriteBatch batch; private Vector3 point = new Vector3(); private Stage stage; private TextButton runBtn; private TextButton punchBtn; private TextButton run2idleBtn; private BitmapFont font; private SkeletonRenderer renderer; private SkeletonRendererDebug debugRenderer; private SkeletonData skeletonData; private Skeleton skeleton; private AnimationStateData stateData; private AnimationState state; private TextureAtlas atlas; @Override public void create() { camera = new OrthographicCamera(); viewport = new FitViewport(SCENE_WIDTH, SCENE_HEIGHT, camera); // Center camera viewport.getCamera().position.set( viewport.getCamera().position.x + SCENE_WIDTH*0.5f, viewport.getCamera().position.y + SCENE_HEIGHT*0.5f, 0); viewport.getCamera().update(); viewport.update((int)SCENE_WIDTH, (int)SCENE_HEIGHT); font = new BitmapFont(Gdx.files.internal("data/font.fnt")); stage = new Stage(new FitViewport(1280, 720)); Gdx.input.setInputProcessor(stage); batch = new SpriteBatch(); renderer = new SkeletonRenderer(); debugRenderer = new SkeletonRendererDebug(); debugRenderer.setBones(true); debugRenderer.setRegionAttachments(true); debugRenderer.setBoundingBoxes(true); debugRenderer.setMeshHull(true); debugRenderer.setMeshTriangles(true); loadSkeleton(Gdx.files.internal("data/spine/hero.json"), false); // Buttons TextButton.TextButtonStyle tbs = new TextButton.TextButtonStyle(); tbs.font = font; tbs.up = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("data/scene2d/myactor.png")))); runBtn = new TextButton("Run", tbs); runBtn.setPosition(50,600); runBtn.addListener( new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { state.clearTracks(); skeleton.setToSetupPose(); state.setAnimation(0, "run", true); }; }); punchBtn = new TextButton("Punch", tbs); punchBtn.setPosition(50,500); punchBtn.addListener( new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { state.clearTracks(); skeleton.setToSetupPose(); state.setAnimation(0, "punch", false); }; }); run2idleBtn = new TextButton("Run2Idle", tbs); run2idleBtn.setPosition(50,400); run2idleBtn.addListener( new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { state.clearTracks(); skeleton.setToSetupPose(); state.setAnimation(0, "run", true); state.setAnimation(0, "idle", true); }; }); stage.addActor(runBtn); stage.addActor(punchBtn); stage.addActor(run2idleBtn); } void loadSkeleton (FileHandle skeletonFile, boolean reload) { if (skeletonFile == null) return; String atlasFileName = skeletonFile.nameWithoutExtension(); if (atlasFileName.endsWith(".json")) atlasFileName = new FileHandle(atlasFileName).nameWithoutExtension(); FileHandle atlasFile = skeletonFile.sibling(atlasFileName + ".atlas"); TextureAtlasData data = !atlasFile.exists() ? null : new TextureAtlasData(atlasFile, atlasFile.parent(), false); atlas = new TextureAtlas(data) { public AtlasRegion findRegion (String name) { AtlasRegion region = super.findRegion(name); return region; } }; try { String extension = skeletonFile.extension(); if (extension.equalsIgnoreCase("json")) { SkeletonJson json = new SkeletonJson(atlas); json.setScale(.5f); skeletonData = json.readSkeletonData(skeletonFile); } else { SkeletonBinary binary = new SkeletonBinary(atlas); binary.setScale(.5f); skeletonData = binary.readSkeletonData(skeletonFile); } } catch (Exception ex) { ex.printStackTrace(); Gdx.app.log(TAG, "Error loading skeleton: " + skeletonFile.name()); return; } skeleton = new Skeleton(skeletonData); viewport.getCamera().project(point.set(SCENE_WIDTH * .5f, 0, 0)); skeleton.setX(point.x); skeleton.setY(point.y); skeleton.updateWorldTransform(); stateData = new AnimationStateData(skeletonData); state = new AnimationState(stateData); skeleton.setSkin(skeletonData.getSkins().first()); stateData.setMix("run", "idle", 5f); state.setAnimation(0, "idle", true); } @Override public void dispose() { atlas.dispose(); font.dispose(); batch.dispose(); stage.dispose(); } @Override public void render() { Gdx.gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); float delta = Gdx.graphics.getDeltaTime(); state.update(delta); state.apply(skeleton); skeleton.updateWorldTransform(); batch.begin(); renderer.draw(batch, skeleton); batch.end(); debugRenderer.draw(skeleton); stage.act(delta); stage.draw(); } @Override public void resize(int width, int height) { viewport.update(width, height); } }