Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ==Using Spine runtimes==
- Animation data can be exported from Spine as JSON ([[http://esotericsoftware.com/spine/files/example.json|example]]) or binary. This data contains the bone, attachment, and animation information needed to render the animations just as they appear in Spine. There are many [[http://esotericsoftware.com/spine-runtimes/|official runtimes]] for various game toolkits that can load this data and render the animations. All of the official runtimes use the same class names and basic structure. This article explains the basics common to all runtimes.
- The code examples below use psuedo code that is easily translated to runtimes in any language. See the runtime specific documentation for examples in the appropriate langauge //(note: runtime specific documentation is under construction)//.
- An overview of the various pieces that make up a runtime can be seen [[http://esotericsoftware.com/spine/files/runtime-diagram.png|here]].
- ==Export==
- ===Skeletal animation===
- To export animation data from Spine, click the logo in the top left of the window and choose ##Export##. Choose ##JSON## or ##Binary## //(note: binary is not currently supported by most runtimes)//. Choose a directory and Spine will create a file for each skeleton in the project containing all the bone, attachment, and animation data for that skeleton. The name of each file will be the name of the skeleton.
- For JSON export, the ##Pretty print## setting makes the JSON output more human-readable. The ##Format## setting controls the type of JSON that is output. ##JSON## outputs valid JSON. ##JavaScript## outputs valid JavaScript, where field names are only quoted as necessary. ##Minimal## outputs a JSON-like format where both field names and values are only quoted as necessary. This can only be used with JSON parsers that are very lenient, such as the libgdx JSON parser.
- ===Sprite animation===
- Alternatively, Spine can export an animation as a sequence of images which can be used as traditional sprite animation. This has a number of disadvantages:
- * The images take up a lot of disk space.
- * The decompressed images take up a large amount of memory at runtime.
- * Sprite animation is not as smooth as interpolated Spine animation (sprite animation examples: [[http://esotericsoftware.com/spine/files/walk.gif|spineboy]], [[http://esotericsoftware.com/spine/files/dragon.gif|dragon]]).
- * Individual pieces of a skeleton cannot be tinted or attached on the fly at runtime.
- * Procedural animation cannot be done.
- * Animations cannot be mixed or crossfaded.
- Still, sprite animation may be useful in some situations. A Spine runtime is not needed for sprite animation, since rendering is simply drawing images.
- ==Texture atlas==
- In addition to the skeleton data exported from Spine, a runtime also needs a texture atlas (also known as a sprite sheet) which contains the texture regions to draw. In most game toolkits, changing which texture is being drawn is costly. Performance is increased by binding a large texture once, then drawing many portions of the large texture.
- When creating skeletons in Spine, individual images are used as this is the easiest way to organize many images. To create a texture atlas for use at runtime, the individual images need to be packed into one or more larger images. In the near future this will be built into Spine, but for now an external tool must be used such as:
- * [[http://code.google.com/p/libgdx/wiki/TexturePacker|libgdx TexturePacker]] This is a free, open source tool written and maintained by the author of Spine. It can pack all images for an entire application in one go. It is configured via filename and directory conventions, with a ##pack.json## file for further configuration. While this tool is intended to be used from the command line, a [[https://code.google.com/p/libgdx-texturepacker-gui/|GUI]] for it is available (though this is maintained by others).
- * [[http://texturepacker.com/|Texture Packer Pro]] This is a payware tool that has both GUI and command line interfaces, many features, and very nice documentation. Be sure to choose the "libgdx" output format if using a Spine runtime ##Atlas##.
- ===Atlas===
- Some runtimes use a game toolkit specific texture atlas. Other runtimes have their own texture atlas implementation called ##Atlas##. This loads texture atlas data in the "libgdx" format. Multiple backing pages are supported, though be warned that this will cause additional texture binds at runtime.
- An atlas is loaded this way:
- {{{
- TextureLoader textureLoader = ...
- Atlas atlas = new Atlas("myAtlas.atlas", textureLoader);
- }}}
- Creating an atlas parses the atlas file, loading the data for where the regions are in the page images. It also uses the ##TextureLoader## to load the page images. The texture loader has two method which are used to create and dispose textures:
- {{{
- void load (AtlasPage page, String path)
- void unload (Object texture)
- }}}
- Often a runtime will provide a texture loader that knows how to create and dispose for a specific game toolkit. An implementation might look like this:
- {{{
- void load (AtlasPage page, String path) {
- Texture texture = ...;
- page.rendererObject = texture;
- page.width = texture.width;
- page.height = texture.height;
- }
- void unload (Object texture) {
- ((Texture)texture).dispose();
- }
- }}}
- The ##AtlasPage## has a ##rendererObject## field which is an object (or void*). It holds any game toolkit specific object. This object will be used by the game toolkit specific code that renders the skeleton, which will be shown later. The ##load## method also must set the ##width## and ##height## on the page. The ##unload## method receives the ##rendererObject## and can cast it as necessary to dispose of the resources.
- ==SkeletonData==
- ##SkeletonData## stores the setup pose information for the bones and slots a skeleton. It also stores all the skins and animations. The setup pose is how the skeleton looks in Spine's Setup Mode and consists of the bone transforms, slot colors, and which attachment is visible for each slot.
- ==Loading==
- JSON or binary data is loaded using ##SkeletonJson## or ##SkeletonBinary##. Both have the same interface, which is a ##readSkeletonData## method that parses the data and returns a ##SkeletonData## instance:
- {{{
- AttachmentLoader attachmentLoader = ...
- SkeletonJson json = new SkeletonJson(attachmentLoader);
- SkeletonData skeletonData = json.readSkeletonData("mySkeleton.json");
- }}}
- See below for details on the ##AttachmentLoader##.
- ===Scaling===
- A scale can be specified on the JSON or binary loader which will scale the bone positions, image sizes, and animation translations:
- {{{
- AttachmentLoader attachmentLoader = ...
- SkeletonJson json = new SkeletonJson(attachmentLoader);
- json.scale = 2;
- SkeletonData skeletonData = json.readSkeletonData("mySkeleton.json");
- }}}
- This causes a skeleton to be drawn at a different size, twice as large in this example. This can be useful when using different sized images than were used when designing the skeleton in Spine. For example, if using images that are half the size than were used in Spine, a scale of 0.5 can be used. This is commonly used for games that can run with either low or high resolution texture atlases.
- Using a loader scale changes the units used. For example, if a bone has a local position of 50,100 then with a scale of 2 it will be changed at load time to 100,200. This can be useful when not using a pixel unit scale at runtime, such as with Box2D.
- A skeleton can also be scaled without affecting the units:
- {{{
- AttachmentLoader attachmentLoader = ...
- SkeletonJson json = new SkeletonJson(attachmentLoader);
- SkeletonData skeletonData = json.readSkeletonData("mySkeleton.json");
- BoneData root = skeletonData.findBone("root");
- root.scaleX = 2;
- root.scaleY = 2;
- }}}
- In this case, if a bone has a local position of 50,100 then it will remain at that position. When the bone's world transform is computed (explained below), its position will be scaled.
- ==AttachmentLoader==
- The ##AttachmentLoader## has a single method which is used to create attachment instances:
- {{{
- Attachment newAttachment (Skin skin, AttachmentType type, String name)
- }}}
- This returns a new attachment for the specified skin, attachment type, and name. Most attachments are a "region" attachment for rendering a texture region, but there can be other attachment types, such as a bounding box. The attachment loader allows attachments to be customized by application specific code. The built-in attachment types can be extended to customize rendering or other behavior.
- The most common attachment loader has a texture atlas. In ##newAttachment## it creates a ##RegionAttachment## and populates it by looking up a texture region in the atlas using the attachment name. Code to do that might look like this:
- {{{
- TextureAtlas textureAtlas = ...
- Attachment newAttachment (Skin skin, AttachmentType type, String name) {
- if (type != AttachmentType.region) throw new Error("Unknown attachment type: " + type);
- RegionAttachment attachment = new RegionAttachment(name);
- TextureRegion region = textureAtlas.findRegion(name);
- if (region == null) throw new Error("Region not found in atlas: " + name);
- attachment.rendererObject = region;
- return attachment;
- }
- }}}
- Note the ##rendererObject## field is runtime specific. Each runtime may have a different way of storing the texture region on the ##RegionAttachment##. The runtime specific rendering needs to know how to access the texture region, which will be shown later.
- The attachment loader only creates a new attachment. It may do some configuration, such as setting a texture region, but additional configuration is done by the JSON or binary loader. For example, the loader has code like this:
- {{{
- Attachment attachment = attachmentLoader.newAttachment(skin, type, name);
- if (attachment instanceof RegionAttachment) {
- RegionAttachment regionAttachment = (RegionAttachment)attachment;
- regionAttachment.setX(...);
- regionAttachment.setY(...);
- regionAttachment.setScaleX(...);
- regionAttachment.setScaleY(...);
- regionAttachment.setRotation(...);
- regionAttachment.setWidth(...);
- regionAttachment.setHeight(...);
- regionAttachment.updateOffset();
- }
- }}}
- ===AtlasAttachmentLoader===
- If using a runtime that has a Spine atlas, an ##AtlasAttachmentLoader## is provided:
- {{{
- TextureLoader textureLoader = ...
- Atlas atlas = new Atlas("myAtlas.atlas", textureLoader);
- AtlasAttachmentLoader attachmentLoader = new AtlasAttachmentLoader(atlas);
- SkeletonJson json = new SkeletonJson(attachmentLoader);
- SkeletonData skeletonData = json.readSkeletonData("mySkeleton.json");
- }}}
- Since this is very commonly used, the JSON and binary loaders for most runtimes will accept an atlas and create an atlas attachment loader internally:
- {{{
- TextureLoader textureLoader = ...
- Atlas atlas = new Atlas("myAtlas.atlas", textureLoader);
- SkeletonJson json = new SkeletonJson(atlas);
- SkeletonData skeletonData = json.readSkeletonData("mySkeleton.json");
- }}}
Add Comment
Please, Sign In to add comment