EN
creator cover aleha_84
aleha_84
Creating cozy pixelart seamless scenes
aleha_84
21
subscriber
Available to everyone
Aug 13 18:41

Article No. 2. Creation of a seamless animation + example analysis

Next, I will tell my vision of what is happening, starting from personal experience. The approaches I use may differ from those generally accepted, but I go my own way.
First of all, when creating a seamless/infinite animation, you need to accept the fact that you do not need to perceive the action taking place there, which has a beginning and an end. As if something starts on the 1st frame, and ends on the 100th. It can start on the 60th and end on the 20th. How can this be? It is logical that any video file or GIF has its own duration. I think of it as the number of frames that change at a given frequency. When creating a seamless animation, you need to accept the fact that there is no second wall. When we reach the frame limit in the final animation, the next index simply starts from zero.
In the code, this is solved as follows (frame pre-rendering, described in the previous article):
for(let f = 0; f < totalFrames; f++){
    let frameIndex = f + startFrameIndex;
    if(frameIndex > (framesCount-1)){
        frameIndex-=framesCount;
    }
    // do your action here   
}
(there are no tools for formatting the code on boosty)
Visually, the result can be achieved in two main ways.
The first. During the action, return the state of the object to its start state. In this situation, the number of frames of the object itself must match the number of frames of the final animation. If it is higher or lower, then there will be jerking frames. For example, the resulting animation is 100 frames long. We place a point on it, which during the same 100 frames changes its state back and forth (size, position, whatever).
Second. When we achieve a result at the expense of many other objects. In this situation, the number of frames of the object must be less than the number of frames in the final animation. In this case, we do not have to return the object to its original state at the end. Due to the existence of similar "neighbors" it is possible to create a visual sense of the continuity of the action, create a flow. The fewer frames an object has, the shorter it appears in the scene and vice versa. This works in tandem with the number of objects of the same type. Here it is necessary to find a balance so as not to create a lot of noise.
The first and second options can be combined to create a great variety.
A prerequisite when using more than one object in such an animation, regardless of the chosen rendering method (described above), is the distribution of the starting point along the timeline. The distribution can be random, linear or more complex, each option gives a different result. By the concept of randomness, I mean mechanisms built on the basis of the Javascript function Math.random().
You can extend the previous code example with: let startFrameIndex = getRandomInt(0, framesCount-1); which is essentially the definition of the starting point for the animation of the next object on the timeline. In the case of the first rendering option, when the animation time of the object is equal to the animation time of the object, a lot of continuous actions will look scattered, not amenable to any rules. In the case of the second option, this adds an extra level of chaos without which it would not make sense.
Further already there are only variations of the approaches described above. For example, along with visual parameters, you can randomly choose the duration of the animation of objects, for example, some will appear and go out faster or slower.
Summing up, we can highlight the following key points: choosing the duration of the animation, choosing the starting point on the timeline, throwing the next frames to the beginning, choosing the parameters for animation.
Example analysis
Iridescent wavy line. It may look like it's moving along a trigonometric function, but it's not.
Starting parameters: number of frames - 120; number of objects - 20; clamps along the X coordinate; clamps along the Y coordinate; the size of each object is 2x2; object animation duration - 120;
Here the option is used when the duration of the animation of the object is equal to the total duration of the animation. At the start, the location of the elements on the X scale is calculated using the selected range. A set of parameters is defined that will change for each object: the H-component of the HSV color representation, the position along the Y coordinate, the size of the object in height. The parameters change according to a quadratic equation with a given smoothness, i.e. the value of the parameter is calculated in advance in accordance with the required frame and an array of values is formed.
The starting frame for each object is determined by the formula: i*fast.r(framesCount/2/itemsCount); where i - object index starting from 0, fast.r - rounding, framesCount - total number of frames in the scene, we further divide them in half for better smoothness, itemsCount - number of objects. Thus, a linear distribution along the time scale was obtained.
Further, it's a matter of technology, we have the index of the next frame, its position in time, we just need to take the parameter values ​​and display it on the canvas. Many parameters are chosen by eye to satisfy me visually, it often happens that erroneous settings together with others give a great visual effect. Also, over the couple of years that I support this project, a large amount of auxiliary code has accumulated, which allows me to save time and not repeat previously written code.
Thank you for your attention. If you have any questions, please write to me on my social networks - IG, twitter, etc. I always answer.
Log in, to post comments

Subscription levels

Поддержка \ Support

100₽ per month
Go up