Keyable draw order

August 19th, 2013

We’ve completed the keyable draw order stretch goal! You can now change the draw order during animations without using multiple slots.

To use it, switch to animate mode and change the draw order in the tree, then click the key dot next to the Draw Order node in the tree. Similar to events, the visibility dot next to Draw Order can be used to hide the draw order keys in the dopesheet.

In other news, the dopesheet has gotten some fancy new icons!

Keyable draw order

Childhood dream come true: Building Spine

August 13th, 2013

A number of people have asked about our experiences building Spine and doing a Kickstarter, so I thought I would ramble a bit about it.

A Little History, Changing My Life

I (Nate) have always wanted to build Spine. At 11 years old I started learning programming using QBasic and my masterpiece was a 3D fighting game. It took years to finish and wasn’t really fun to play, but it had skeletal animation and a very simplistic editor.

QBasic fighting game

Out of high school at 19 years old I got into the corporate world and did software development for 12 years. At that point I had just got divorced, had a severely upside down mortgage, and basically life was nothing but work, eat, and sleep. I decided to change things. I ditched the house, quit my job at a certain Mickey Mouse company and become a nomad. Over the next year and a half I crashed with friends in San Francisco, Austria, London, Denmark, Bangkok and Seattle. I love programming, so I spent a lot of time on free open source software (and Street Fighter).

A Need Arises, The Journey Begins

Eventually Søren, my partner in crime, and I decided to make a game. Sprite animation is limiting and requires a lot of art time. Søren is an artist and Softimage guru, so we wrote some export scripts and a simple runtime to do skeletal animation. It worked, but the workflow was bad. It was tedious to setup and easy to accidentally use Softimage features that were unsupported by the runtime. We looked for dedicated tools but were disappointed. We had a vision, we felt like we knew exactly what needed to be built, so we set off doing it. 20 years after my QBasic fighting game, I’m happily working full time on Spine!

Spine screen

Spine screen

We held back releasing Spine until we had all the basics working, start to finish. We had tons of ideas for all the things we could do with the tool. It was very, very hard to keep feature creep in check, to stay on track and implement only the basic features. So many of my own and Søren’s ideas had to get shot down. We make ourselves feel slightly better by saying, “we can always add that later”. Anything that is complex and not a core feature just has to go. Other features are complex but are very important and have to be done. The trouble is knowing the difference. Thankfully Søren has a lot of industry experience and knows how things should work in a tool like this. At the same time he also has a million features he wants, so I’ve become good at saying no to absolutely everything until it’s clearly a must have (or it’s easy enough to do).

A Man Needs to Eat: Kickstarter

We had worked on the editor part of Spine for 9 months and had only one runtime for libgdx. We didn’t have any connections to investors and slowly but surely we were running out of our savings. We decided to give Kickstarter a try, both because we needed the money and also to spread the good word. I went to Denmark and crashed at Søren’s place so we could collaborate easier. I did the video by taping my cell phone to the back of a chair. It was a grueling process for me and I had to do many, many takes to get it right. My dreams (and probably yours) are still haunted by “Hi, my name is Nate!”. Søren did the screencast and put together the video. Our aim was something that grabs people in the first 20 seconds and makes them want to watch the rest.

Spine teaser

We were worried we wouldn’t make the goal so we set it at what we felt was rock bottom for a handful of runtimes, $12k. We made that in 3 days! This was totally unexpected. We then decided on a better way of doing runtimes — making generic runtimes that could more easily target many game toolkits. We went over our notes for features that didn’t make it and came up with tons of stretch goals.

KickTraq chart

Keeping a high level of customer support during the Kickstarter was a huge task. Many days were spent full time answering Kickstarter questions, comments, emails, and forums. This was very exhausting but we made sure that anyone with a question got an answer.

The Kickstarter ended at $67,569 which is a whopping 563% of our original goal. We reached all but one of the stretch goals. So, so many stretch goals. In hindsight, maybe too many! It’s been 6 months full time after the Kickstarter and we’re still not finished, but we will get there. We are dedicated to fulfilling our promises to everyone that backed us.

Marketing? What’s That?

We’ve never done any marketing for Spine, mostly because we have no idea what to do. The Kickstarter was a form of marketing I suppose. Twitter was pretty active for us and probably helped a lot. I expect there are many developers out there that would love to use Spine but just haven’t found it yet. We have to just hope people find us on Google and through word of mouth. I’m sure I’m being naive, but marketing is such a mystery. It seems silly to spend money on marketing and then not really know if it was worth it.

Life After Kickstarter: Support & Stretch Goals

After the Kickstarter we have users, so a good portion of the day is still spent on support. Sometimes it is frustrating as a whole day goes by without working on a single feature, just answering emails, forums, and fixing bugs. I’m lucky when I have just half a day to work on new features.

As we find time, we have been doing some neat features. Animation is usually done by roughing out the major poses, then adding poses inbetween. Small tweaks to offset keys and create secondary motion are what makes an animation come alive. Being able to tweak an existing animation is very important, so really most of Spine is about making this easier. I’ll quickly mention some of the features we’ve been doing lately:

Ghosting

Ghosting

Ghosting draws frames in the past and/or future. It is useful when posing the skeleton based on other parts of the animation. Our little innovation is an x and y offset, which opens some new possibilities. Eg, when doing a walk animation, usually the animation is done in place and the skeleton is moved at run time. You can set the ghosting x offset to the x movement per frame at runtime and the ghosts will show you if your feet are sliding.

Key adjust mode allows multiple keys to be selected in the dopesheet, then when changes are made to the pose the relative change is also applied to the selected keys. This allows multiple keys to be adjusted at once. Eg, say you had a shoot animation that has 10 keys for the arm translation. Later, you decide the arm needs to move up a little bit. You would need to go to each key, adjust the arm upward, and key it again. With key adjust mode, you would select all the keys and move the arm up once.

We found setting up a skeleton was the most time consuming part of using Spine, so we reworked our skeleton setup workflow. We added features to the bone create tool so an existing bone could be redrawn. Also, when drawing a new bone it can automatically attach the image the bone is being drawn over. This makes the workflow: position images, draw bones, adjust draw order, and you are done rigging and ready to animate.

Spine supports multiple skeletons in the same project and they can be animated synchronously, allowing Spine to be used for cutscenes. However, there are still a few important features (like skeleton draw order) missing for cutscene usage. Supporting multiple skeletons was (is) a pretty big pain, but we chose to do it early on to enable more complex usage later. It would be great to have an animation mixer someday, which is like a dopesheet but instead of keys it is for which animations are playing.

Texture packer

Texture packer

Spine can now do texture packing, allowing you to export animation data and a texture atlas directly usable in your game.

A few days ago we finished the event timeline feature. This allows you to specify events during animations which can trigger anything you like at runtime. Eg, sounds, particles, etc.

We spend a lot of time on ton of little features and polish that make using the app more pleasant. Last week I made a quick tips video that runs through a bunch of the more esoteric minor features.

The Tech Behind Spine

Spine is built with Java, but there is no Swing to be found. Unbeknownst to most, nowadays Java is actually good for UIs (and games!) by using libgdx. I am co-author of libgdx along with the venerable Mario Zechner. libgdx is a game development framework which provides APIs for OpenGL-based graphics, input, audio, etc. Your resulting app can then run on Windows, Mac, Linux, iOS, Android, and in a browser via WebGL. Spine could actually run on all those platforms!

KickTraq chart

The key to making UIs with libgdx is scene2d.ui, a UI toolkit built on top of libgdx’s 2D scenegraph, called scene2d. scene2d is originally Mario’s brainchild. At some point I ended up taking it over and it has seen a few teardown and rewrites. It is in wide usage today and is quite solid for game, mobile, and desktop UIs as well as general scenegraph needs.

scene2d.ui makes extensive use of TableLayout, which is my OSS, platform agnostic, table-based UI layout library. So many UI toolkits fall short when it comes to layout, which is an extremely important piece. I wish TableLayout saw more use outside libgdx, as it supports libgdx, Swing, Android, TWL, and is extensible for supporting additional UI toolkits.

KickTraq chart

In addition to libgdx and scene2d, Spine uses a number of my other OSS projects: Scar, Wildcard, Kryo, JsonBeans, TexturePacker. As you can see, I tend to build lots of tools and libraries instead of making games. Spine also uses MattiasM and Riven’s green threads for Java, which is really neat stuff.

Spine has a sweet build system. Along with an auto update mechanism in the app, with one button press I can build and deploy an update to all users on all operating systems. Because of this we do releases all the time, often multiple times per day. This is great for quickly getting fixes out. As a 2 man team with only 1 coder, its inevitable that users end up testing. With such fast updates, if a user reports a bug we can usually get it fixed and deployed before it affects many other users. The end result is that users generally experience fewer bugs overall. We also have crash report submission which really helps, as it seems less than 5% of users bother to report issues via email or the forums. I monitor it daily and have chased down lots of bugs this way.

We have all the official runtimes on GitHub. As a result of the Kickstarter we support 18 game toolkits officially and we have generic runtimes that can be extended for other toolkits in C, C++, Objective-C, C#, Java, ActionScript 3, Lua, and JavaScript. The generic runtimes do all the heavy lifting and provide a flexible API for manipulation skeletons and animations, the only thing they don’t do is rendering.

Runtime object model

There are also third party runtimes built by the game development community for more than 20 game toolkits. As a result, Spine animations can basically run anywhere, and if not then it isn’t hard at all to grab a generic runtime and implement rendering.

Life Is Good

Spine is doing ok sales-wise. I’m sure the $61k (after fees) from the Kickstarter sounds like an awful lot. It is a lot, but at the same time there are two of us who worked 9 months without income and then 6+ months doing stretch goals. We aren’t complaining by any means though, we love the work and can support ourselves, which is all we could have asked for.

We have a lot planned for the future. Once we get through the Kickstarter goals (bounding boxes and a number of smaller features) we’d like to look at supporting free form deformation, which would make animating really powerful. We already have IK (in the editor, not at runtime) via the Pose tool, but we want to do more by allowing bones to be pinned. Eg, this is great for keeping the feet in place while moving other bones. At some point we’d like to make games, too!

Looking back, it’s crazy how things have taken a turn. From a terrible QBasic fighting game to a self-sustained business in a niche we love. I just got married in June and I’m now living in Croatia where my wife is from, on a small island 8km in circumference with no roads or cars. The internet is slow 3G, but living expenses are minimal and the Croatian seaside is amazing. I code, swim, and raise a little puppy. Life is good!

puppy

Event timeline, texture packing and more

August 9th, 2013

We’ve been hard at work in the two months that have passed since the last update. In that time we’ve done 37 releases, which averages to a release every other day! As always, you can see release details in the changelog. The most notable new features are probably the event timeline and integrated texture packing.

The event timeline allows you to specify events during your animations, then at runtime you can take some action such as playing a sound or spawning particles.

Event timeline

Integrated texture packing means you can pack your images into a texture atlas when you export your skeletons from Spine. You can even use the Spine texture packer for general packing purposes, for use without Spine.

Texture packer

There are also many other new features:

  • Key adjust mode enables editing many keys all at once for quickly adjusting entire animations.
  • Key shift mode makes it easy to drag all subsequent keys.
  • Playback options.
  • Multiple slot drag and drop.
  • Background images.
  • A number of new features work together to create a new skeleton setup workflow.
  • Ghosting is shown off in the ghosting video.
  • Lots of minor features, some of which are shown in the quick tips video.
  • Tons of minor tweaks and bug fixes.

We are closing in on finishing all the Kickstarter stretch goals. Most of the largest and hardest goals have been completed and we hope to get the rest done very soon!

OlderNewer