/****************************************************************************** * Spine Runtimes Software License * Version 2 * * Copyright (c) 2013, Esoteric Software * All rights reserved. * * You are granted a perpetual, non-exclusive, non-sublicensable and * non-transferable license to install, execute and perform the Spine Runtimes * Software (the "Software") solely for internal use. Without the written * permission of Esoteric Software, you may not (a) modify, translate, adapt or * otherwise create derivative works, improvements of the Software or develop * new applications using the Software or (b) remove, delete, alter or obscure * any trademarks or any copyright, trademark, patent or other intellectual * property or proprietary rights notices on or in the Software, including * any copy thereof. Redistributions in binary or source form must include * this license and terms. THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE * "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 SOFTARE BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ using System; using System.IO; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Media; using Spine; namespace Spine { public class Example : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SkeletonRenderer skeletonRenderer; Skeleton skeleton; Slot headSlot; AnimationState state; SkeletonBounds bounds = new SkeletonBounds(); public Example () { IsMouseVisible = true; graphics = new GraphicsDeviceManager(this); graphics.IsFullScreen = false; graphics.PreferredBackBufferWidth = 640; graphics.PreferredBackBufferHeight = 480; } protected override void Initialize () { // TODO: Add your initialization logic here base.Initialize(); } protected override void LoadContent () { skeletonRenderer = new SkeletonRenderer(GraphicsDevice); skeletonRenderer.PremultipliedAlpha = true; String name = "spineboy"; // "goblins"; Atlas atlas = new Atlas("data/" + name + ".atlas", new XnaTextureLoader(GraphicsDevice)); SkeletonJson json = new SkeletonJson(atlas); skeleton = new Skeleton(json.ReadSkeletonData("data/" + name + ".json")); if (name == "goblins") skeleton.SetSkin("goblingirl"); skeleton.SetSlotsToSetupPose(); // Without this the skin attachments won't be attached. See SetSkin. // Define mixing between animations. AnimationStateData stateData = new AnimationStateData(skeleton.Data); if (name == "spineboy") { stateData.SetMix("walk", "jump", 0.2f); stateData.SetMix("jump", "walk", 0.4f); } state = new AnimationState(stateData); if (true) { // Event handling for all animations. state.Start += Start; state.End += End; state.Complete += Complete; state.Event += Event; state.SetAnimation(0, "drawOrder", true); } else { state.SetAnimation(0, "walk", false); TrackEntry entry = state.AddAnimation(0, "jump", false, 0); entry.End += End; // Event handling for queued animations. state.AddAnimation(0, "walk", true, 0); } skeleton.X = 320; skeleton.Y = 440; skeleton.UpdateWorldTransform(); headSlot = skeleton.FindSlot("head"); } protected override void UnloadContent () { // TODO: Unload any non ContentManager content here } protected override void Update (GameTime gameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); // TODO: Add your update logic here base.Update(gameTime); } protected override void Draw (GameTime gameTime) { GraphicsDevice.Clear(Color.Black); state.Update(gameTime.ElapsedGameTime.Milliseconds / 1000f); state.Apply(skeleton); skeleton.UpdateWorldTransform(); skeletonRenderer.Begin(); skeletonRenderer.Draw(skeleton); skeletonRenderer.End(); bounds.Update(skeleton, true); MouseState mouse = Mouse.GetState(); headSlot.G = 1; headSlot.B = 1; if (bounds.AabbContainsPoint(mouse.X, mouse.Y)) { BoundingBoxAttachment hit = bounds.ContainsPoint(mouse.X, mouse.Y); if (hit != null) { headSlot.G = 0; headSlot.B = 0; } } base.Draw(gameTime); } public void Start (AnimationState state, int trackIndex) { Console.WriteLine(trackIndex + " " + state.GetCurrent(trackIndex) + ": start"); } public void End (AnimationState state, int trackIndex) { Console.WriteLine(trackIndex + " " + state.GetCurrent(trackIndex) + ": end"); } public void Complete (AnimationState state, int trackIndex, int loopCount) { Console.WriteLine(trackIndex + " " + state.GetCurrent(trackIndex) + ": complete " + loopCount); } public void Event (AnimationState state, int trackIndex, Event e) { Console.WriteLine(trackIndex + " " + state.GetCurrent(trackIndex) + ": event " + e); } } }