microsoft / pxt-arcade

Arcade game editor based on Microsoft MakeCode
https://arcade.makecode.com
MIT License
477 stars 206 forks source link

The Future of Animation #1212

Closed dannytech closed 4 years ago

dannytech commented 5 years ago

This issue is to provide an outline of possible future improvements to the updated animation extension created in microsoft/pxt-common-packages#906.

Field editors

One of the originally discussed but never implemented features is a set of field editors to ease in the process of creating both frame and movement animations.

Frame animations

The frame animations block accepts three parameters: the target sprite, an array of images to animate through, and an interval between frames. The array is prefilled with image blocks to allow easy addition of frames. This approach, while certainly usable, has several limitations:

The recommended field editor would include the following features:

A possible implementation might look like this:

mockup

Movement animations

The movement animation block also accepts three inputs: the target sprite, a string containing an SVG path the follow, and the total duration of the animation. At the moment, while any SVG path can technically be provided, the block instead uses a dropdown containing several premade animations. There are several limitations to this approach:

The recommended field editor would include the following features:

We do not have a possible design for such a field editor at this point.

Elliptical Arcs

One of the few parts of the SVG path standard that is not supported is the elliptical arc command (written as A/a). This command essentially allows an arc to be taken from an ellipse and used as a path. While its behavior can in many cases be emulated with a quadratic or cubic bezier curve (which is supported), it may not be possible to do so in all scenarios. One such scenario is large arcs that might require multiple bezier curves to emulate. While the arcTo command is fairly easy to use, the implementation must be carefully planned and implemented to take into account edge cases using one of the more complicated flags. The syntax is as follows:

A radius-x radius-y x-rotation large-arc-flag sweep-flag x y OR a radius-x radius-y x-rotation large-arc-flag sweep-flag delta-x delta-y

More details can be found here. An example use case for this command (which has been requested several times during user testing) is a vortex/tornado, where the sprite gradually moves in a circular motion towards the center of a vortex. This could be accomplished with the arcTo command like so:

M 10 10 A 1 1 0 0 1 20 10 A 1 1 0 0 1 12 10 A 1 1 0 0 1 18 10 A 1 1 0 0 1 14 10 A 1 1 0 0 1 16 10

Documentation

The newly introduced blocks do not currently have any documentation attached to them about how they can be used. This is especially problematic as there are some features (such as raw SVG path input) that do not have visibility. Any documentation for the blocks would be liable to change based on the other changes mentioned in this document.

Another issue is that the old documentation is not in a usable state. Unfortunately, several of the blocks do not correctly link to their documentation pages (the filenames are different from what the blocks reference), resulting in those pages being unreachable.

Deprecation

The intent of the new extension was to supersede the old code. However, it is known that the existing blocks are already in use, and so they should not be deprecated just yet. The use of these old blocks should be monitored, and if at a certain point there is a clear trend of moving away from the older blocks, then they can be marked as deprecated/hidden/removed.

Miscellaneous

Animation comparison

In the previous extension, activating an already running animation state would not cause the animation to restart, instead simply letting it continue. A similar behavior might be desirable for the new extension code, however it is far more complicated to implement. In order to match the behavior, a comparison between the existing animation and the new animation would need to be made, ignoring any variables such as time. Unfortunately, there is no such way to perform a comparison. While some parts of the class can be compared, such as the interval, there is no way to compare two Image objects.

Movement animation comparison is an issue that could be solved fairly gracefully already. A possible comparison method would be to have each PathNode export its corresponding SVG path syntax, which could then be concatenated at the MovementAnimation level and compared to a corresponding SVG path string.

Existing use of comparisons

The existing animation code makes use of an image comparison so that a new image will not be applied if it is the same as the current image. This functionality, migrated from the previous codebase, does not currently break any functionality, but would benefit from the ability to perform image comparison for purposes of optimization.

Closing suggestions

The below suggestions are just for consideration, and are likely not worth the time investment to implement them.

Exponents and Floats

The SVG path standard supports the use of exponents and floats in most parameters. Neither of these are currently supported, due to the fact that neither are a reasonable use case. Since rendering does not take into account partial pixels, float handling was never implemented. In addition, since the screen is only 160x120 pixels, it would not make sense for a sprite to move far enough that exponents are needed to represent their target.

With that said, there is the possibility of a user pasting in externally generated SVG paths that use these features, and this could potentially cause SVG path parsing to fail. As such, accepting them in some form could make sense. For floats, simply rounding to the closest integer, and for exponents, just parsing them into integers normally.

Nth Degree Beziers

The current SVG path implementation supports quadratic and cubic bezier curves. With that said, bezier curves can in theory have many more control points than just 1 or 2. Implementing an nth degree bezier curve command would likely require refactoring of the parser in order to accept a multitude of arguments rather than a fixed amount.

dannytech commented 4 years ago

For the elliptical arc function, here are the relevant implementation notes (including the math that should be necessary to calculate a given point on the path): https://www.w3.org/TR/SVG/implnote.html

abchatra commented 4 years ago

fixed