Best way to implement (complex) spritesheet animations


#1

Currently I am working on a racetrack (in perspective) with 5 running horses. The horses run on an oval track taking into account the perspective change when they turn a corner.

For this I have rendered 250 frames (per horse!) and created five spritesheets (see image below for one of the spritesheets. Currently I am trying to:

  • let the horses run on their own track
  • make sure that they also animate within the spritesheet
  • optimise everything for mobile (!!)

At the moment I managed to come up with the following solution:

  1. import the spritesheet into Hype
  2. put the spritesheet into a group and mask a single tile of the spritesheet (100x100)
  3. animate this group around the track (with the single frame)
  4. create a JS that is getting called on an FPS interval that changes the backgroundposition of the spritesheet

This works, however:

  1. it is pretty resource heavy (with 5 horses!)
  2. it runs poorly on mobile
  3. lack of framerate generates a lag where the HYPE animation (the static image around the track) and the spritesheet animation get out of sync.

I’ve already optimized the size and compression of the spritesheet as well as implemented a single FPS-based interval (instead of 5). I’ve also tried changing the spritesheet animation to a CSS-based one, but this is way more difficult to control (I need to control the speed of the horses as one has to run faster to win).

I also used different JS / JQuery tools to animate the spritesheet (i.e.: http://blaiprat.github.io/jquery.animateSprite/). But none seem to provide a proper solution.

The best way would be to have HYPE handle ALL the animation (so the animation around the track as well as the spritesheet animation), but there seems to be no proper support for spritesheets. I don’t want all the loose frames to be separate files (as the server-calls would be enourmous), so I’m stuck with the spritesheet.

I’ve found this topic, but it doesn’t provide any real answers: Spritesheet / frame sequence import / SVG I also don’t understand the answer of cowdar.

Anyone has any idea? Or do I have to switch out my trusted HYPE for a different toolkit for this one :frowning:

NOTE: I also know that this is the least optimal form of spritesheeting (as all the individual frames are separated by the same amount of pixels). Ideally you want to have an spritesheet that is as small as possible, where all the alpha-space is used for images. Positioning all the frames is done with an xml / textfile. Is this posisble?


(𝕄𝕚𝕔𝕙𝕒𝕖𝕝 𝔾𝕒𝕣𝕠𝕗𝕒𝕝𝕠) #2

That problem seems similar to here…

The way the mission brief video works is basically a sprite sheet. It’s processor intensive. That’s with just one animation. I’m not sure what you could do to fix that, as it’s a huge image.

You could try controlling the action with a requestAnimation frame event, so it’s not always updating when the screen isn’t being drawn.

You could try using SVG Animation to control the sprites instead of Hype. So, you’d still be using Hype but you’d have more options. (That’s how I created the 100 animated stars in the background. These are light weight particles though.)

You could try skipping frames, to lower the image size. Your image is huge. It might be too big for mobile.

Also, I find that Sprite Sheets are a problem. When I scale the scene, it can cause alignment problems. The edges of the box don’t always align properly. I’m using a filter of 98% saturation, just to blur it up a bit.

I’m not sure what else you could use besides Hype. I’m really starting to miss Flash a lot these days. Everything just worked. With HTML5, there are huge differences between the platforms - especially mobile. At first, I tried using a video instead of a Sprite Sheet, but mobile devices don’t work the same way. The autoplay video problem could be resolved with iOS 10, but not everyone has that.

A lot of the joy in this profession is gone, makes me want to move out of the city and be a farmer. :smile:


#3

Thank you for your reply. The sprite-sheet I’ve uploaded is not the same as the final spritesheet in the game (which is 980x630 and I’m still making it smaller by simply using smaller visuals as well as removing some frames (and reusing them). Remember I also have to use 5 (!) of these badboys.

Yes Flash was so much better at this. It sucks that these simple things seem to be so difficult. Right now I am looking into Phaser to see if that helps a bit in the preformance. I’ll keep you posted.


(Mattias Lindberg) #4

Not sure if it would work, but have you tried simple GIF animations instead? Maybe you can switch between different animated GIF’s for different speeds and directions?


#5

Yes! Also tried GIF, but I lose a lot of detail with GIF it seems. Also I can’t control the speed of a GIF through JS / CSS. Thanks for the tip though!


(Mattias Lindberg) #6

Well, if not Hype does the trick. Have you tried Animate CC? Got some new JS and HTML5 functionalities…
Maybe you can use both, importing the Animate content within Hype and iframes or something?


#7

Haven’t tried Animate CC yet, could be an option though. Phaser.io seems to be less suited as it doesn’t allow for timeline animations (as it is fully code based).

I’m also a bit hesitant on switching to a different toolkit, as I’ve optimised my workflow for these ‘games’ fully now. And switching toolkits would mean that I have to change some stuff on the server as well (which isn’t all that great deadline wise).

Difficult.


(Mattias Lindberg) #8

Yeah, for games maybe the best step or upgrade would be Unity. :slight_smile:


#9

Yes, that’s my prime dev-tool :smiley: But Unity supports horrible HTML-export unfortunately :frowning:


(𝕄𝕚𝕔𝕙𝕒𝕖𝕝 𝔾𝕒𝕣𝕠𝕗𝕒𝕝𝕠) #10

What about a hybrid approach? Why not use Phaser.io and Hype together? I took a look at the sample tutorial… http://phaser.io/tutorials/making-your-first-phaser-game …why couldn’t something like that run in Hype?

It’s mixing Canvas with DOM… http://tumult.com/hype/faq/#doestumulthypeusecanvas …so it’s not a perfect match. Yet, it might work.

Although, I’d probably try SVG Animation first. There’s lots of information about that online… https://duckduckgo.com/?q=sprite+animations+SVG

…and why use a Sprite Sheet? Like, why not just create Keyframes and separate images? If you’re worried about too many loading files, you could convert the images to base64 and then just change the inner HTML.


#11

I’m not really a fan of a hybrid solution, as it only complicates stuff more and more. SVG animation is also not an option unfortunately (the horses are rendered through Maya and come in PNG only).

Keyframes and separate images are a ton of work, as they require me to position all the 250 individual frames by hand (times 5). Also it increases the server calls with a factor 250. Using base64 might fix that, but it that seems a bit overkill (and I also haven’t used base64 :slight_smile: ).

I’ll try if I can address the timeline frame by frame (using goToTimeInTimelineNamed) through the same update-function as I address the spritesheet with. This way there will be no difference between updating the position of the horse and the spritesheet.


(𝕄𝕚𝕔𝕙𝕒𝕖𝕝 𝔾𝕒𝕣𝕠𝕗𝕒𝕝𝕠) #12

That’s what I mean. I haven’t tested it, but doesn’t SVG support bitmap images on the inside? (Although, this is probably not much more different than just using HTML.)

(Although, I did see this… https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/image-rendering …the “optimizeSpeed” setting seems like something interesting to test.)

Ideally, the horse would be vector. Couldn’t it be converted with a tracing program?

It’s not that bad. While working on Annoyed Tomatoes, I used Hype to convert the still tomato images into gifs. It was annoying, but I just clicked through in a few minutes. You’ve been at this for days now. Sometimes, brute force is a good solution.

I’ve used CSS Image Encoder to quickly covert images to Base64, but you could just use the Terminal app.

Although, there is the possibility that so much HTML could cause performance problems. So, all that work might be a waste of time.


#13

Haha :smiley: I lolled at ‘so, all that work might be a waste of time’ :smiley: That’s what I keep running into :smiley:

I want to test two additional things:

  1. move the animation by code (instead of by Hype) so I can pair up the animation with the sprite-switch.
  2. see if I can export the motion path into an array of x,y-points. This way I can animate both spritesheets and movement in one code-update.

Thanks for your comments so far! Greatly appreciated!


(Jonathan Deutsch) #14

Hype definitely could use proper image sequence/spritesheet support, and there’s a lot of experimentation I need to do to figure out the most performant methods across a wide variety of browsers/devices for this to be a feature yet.

It wasn’t clear if you had tried putting the sheet in a group with content overflow set to hidden in Hype, and then tried animating the top/left position? This would be a bit tedious now, though on a spritesheet that has a full last row you could do separate animations for x and y and run them concurrently. You can also drive this type of animation with the hypeDocument.setElementProperty() API. I would guess if you did this via requestAnimationFrame it would happen in the same tick as Hype animations and would not appear out of sync.


#15

Thank you for your reply. Do the Hype Timeline animations run on the requestAnimationFrame? Cause it seems that they run regardless of the available frames.

Also it looks like the Timeline animations run even when the window is not active / visible (in contrary to requestAnimationFrame, which only animates / runs when the window is active / visible).


(Jonathan Deutsch) #16

Yes, Hype uses requestAnimationFrame for its animations, though there are a few cases where they may be triggered outside of this callback. Hype will not specifically pause timelines when it is no longer visible, and the moment it returns will use the wall clock time to decide what to render. (The one exception is Physics; this will completely pause based on the page visibility APIs).