Pixel by pixel morphing slows down

When I saw that @LCProCODER had done some nifty sprite morphing using fixed animations, it got me wondering if morphing would be possible on the fly using pixel by pixel manipulation. I was able to get it working without much trouble, but the speed of the morph seems to slow down as the morph progresses. When I do three morphs in a row, the second one starts off at the same slow speed the first one ended at, which makes me think it could be a limitation somewhere. Can y’all take a look and tell me if I’m doing something dumb in my algorithm?

Many thanks!
Jeff :slight_smile:

1 Like

I used animation for that

Two things were slowing it down here:

  • pick random 0 to array length will actually pick an invalid index 1 / array.length of the time - the random is inclusive, so the upper bound is 1 too high.
  • the 'set mySprite to sprite … ’ in the function is unnecessary, as the function is mutating the image of the sprite. More importantly, though, it’s creating a new sprite each time, and not setting the image - and just leaving the old ones sitting there. This means that by the end of the first animation, you will have (at least) 256 sprites at once (but almost certainly more, due to the first point causing extra iterations). If you want to visualize this a bit better, try giving mySprite a random velocity in the loop - you’ll see a lot more than expected.

With those two fixed it’s about as speedy as you would hope :). Also, I really like the idea of this as an extension, definitely a cool effect I could see being used for e.g. the big reveal of the bad guys true identity!

Terrific! Thanks, @jwunderl ! I’ll get cracking on turning it into a proper extension.

Alright, I’ve made my image-morphing algorithm into an extension. Here it is in a quick demo project:

And here is the GitHub repository:

And I implemented it in my latest game, as it seemed to work well with the mechanics I had:

Currently, the extension puts an extra block into the Sprites category, allowing you to morph a sprite’s image into another image. There are a few minor issues:

  • The speed works well for 16x16 and even 32x16 sprites, but is kinda slow for larger sprites. I think I have it set at the smallest “pause” possible, 0.01ms, but am not sure.
  • I don’t yet know how to cause an error if the two images are different sizes.
  • The block does not default to having mySprite filled in, and it must be dragged from Variables.

Let me know if you see any ways I can make it better or possibly useful to others. Perhaps in a future version I’ll add a block that does the reveal in a different pattern, such as spiraling out from the center. Feel free to send a pull request if you want in on this sweet morphing action.

Thanks, and have a great weekend!
Jeff :slight_smile:

P.S. I tried a couple different ways to get the extension working, and the way that was easiest was forking the simple-text repository. I don’t know if that’s kosher, but it got things moving for me. I saw something in GitHub about template repositories, is that an appropriate application, or could we make a more generic extension to fork? Just thinking out loud here.

Heres a link on making it start with a variable drop down on the blocks https://github.com/microsoft/pxt-arcade/issues/1853#issuecomment-667413640

The pause will likely not be that accurate down to .01ms - I would actually expect it to end up behaving about the same even if you had it at 5 - 20ms, as it’ll still end up yielding to other portions of the game loop. For large images, I think you might end up with better luck by swapping over multiple pixels per iteration depending on image size - e.g. if there are more than 250 pixels to swap left replace two at once, if over 500 three at once, etc.

For errors, I think you should be able to throw "images not same size";, but it might be interesting to consider handling that - e.g. set the sprites image to a new one of the larger size (or keep track of offsets for a smaller new size), draw the old image in the center, reposition it so the sprite doesn’t appear to have moved, and then apply the fade / morph.

Re: making a extension, you can actually do it from within the editor - at the bottom of the screen next to the save button theres a button with a github logo to promote a project to a github extension. You can also handle through the import dialog -> your github repo -> the link at the top to create a new repo. These will guide you to login to github and enable the github integration within arcade. I think I remember there being some slight wonkiness with searching for forks, but I’m not certain right away.

Thanks for the link and for the suggestions, @jwunderl ! I’ve never seen a forum with such actionable, prompt, and kind responses!

I’ve fixed the speed issue, added the ability to morph between different size images, and recreated my repository to avoid being a fork. I also added the ability to morph the background. Here’s a new demonstration:

And here is the new repository:

Thanks again for the help!
Jeff :slight_smile:

1 Like

Oh that’s great! It’s always nice to see a cool extension like this!

For anyone using it, one thing to be careful of - when you start to change an image we have to bring it from the code to memory - that is, it starts to take up the memory of the device, and not just storage (basically RAM vs a hard drive). When you use it on an image the size of a background, it ends up being a lot for some of the devices we support, like the meowbit - that one has 96kb of memory, and each full screen image ends up taking about 10kb of memory. The biggest chunk of memory we use is actually just the two large images we use to represent the screen, which ends up taking ~~20kb.

Long story short, you’ll probably want to limit the number of transitions for big sprites like this to one or so at a time if you want to make sure you are able to run it on smaller devices. (Smaller sprites are mostly fine though / likely won’t be too big of a burden if you’re doing a reasonable number of them.)

1 Like