How the animation engine of Cubecubed works?
Tags: contributorswanted, javascript, webdev, github
Published: 2022-06-30 07:44:16

Hello, everyone. It has been a tough day to me so far. Nah, it's okay, I can continue working with Cubecubed.

[Summer of Math Exposition 2](https://www.youtube.com/watch?v=hZuYICAEN9Y) (#SoME2) ~~deadline~~ is coming to town. If you haven't heard about it but want to make an explanatory math video then I would encourage you to join in the competition. August 15 is the deadline (we are much far from there).

Cubecubed is the tool our team use for the final entry. It's not so great because it lacks a lot of features we need.

But my point is not just that.

As I said in the last article, my ambition for maintaining Cubecubed is to build a tool for teachers and students to visually interact with math. Cubecubed, still, has not gained much popularity, nor Manim nor any other visualization tools out there. So now, I am here, listing them to spread the word of teaching and learning math in a new way.

## The first version - the bad, the worst and the horrible

Back when I first implemented the animation engine, it was a complete mess. The code is even the mystery to me, let alone other people. Maybe they just pass by the [repo](https://github.com/imaphatduc/cubecubed) to see what is inside, or they want to contribute to it. I realized that is not fair to them. So I simplified it to a whole new level.

Now I want to share it with you.

## The new one

Let this small [video](https://imaphatduc.github.io/cubecubed/assets/videos/simpleScene.mp4) exemplify it.

The full code listing for the video is [here](https://imaphatduc.github.io/cubecubed/#/quickstart?id=all-code). We will not talk about the whole thing, but focus more on the animation stuff.

Let's play the first animation.

```ts
group.play([new Create({ cubicon: square1, duration: 2000 })]);
```

Here, `group.play()` takes in an array of animations to play, which are technically called a `queue` in Cubecubed. The current queue has only one animation `Create`.

### The man behind the mystery - `groupElapsed`

In `Group` class, `groupElapsed` is a trivial property. It is the heart of the animation engine. When the engine sees the above line of code, it will play all of the animations included in the queue then calculate the time needed (which we call `queueElapsed`) to finish them. `queueElapsed` now has the value of 2000 (2 seconds).

Move on to the next queue!

```ts
group.play([
    new Create({ cubicon: square2, duration: 2000 }),
    new Rotate({ cubicon: square1, duration: 3000, degree: 45 }),
]);
```

### Line up, guys!

We all want the second queue plays after the last one has finished. Actually, this is a thing in Cubecubed. Queues are played sequentially, one after another. So what is the magic here? If you inspect the code of Cubecubed on GitHub, you'll see the `play()` method of all animation classes take `sleepTime` as a parameter. `sleepTime` is the amount of time to wait before playing.

But how can we calculate this `sleepTime` magic?

It's really simple. `sleepTime` is just `Group().groupElapsed` in disguise. Passing the former to the `play()` methods solves everything.

### Queue-mon says: "Just play, don't wait"

We can see there are two animations in the queue now, `Create` and `Rotate`. Keep in mind, all animations in the **same** queue will play asynchronously. But what exactly happens behind the scene?

Similar to the last queue, the current one needs to calculate the `queueElapsed`. But how?

(Just to remind you, `groupElapsed` is now 2000)

Because the animations play asynchronously, we just need to take their maximum duration. Pseudocode: `queueElapsed = max(2000, 3000) = 3000`, then `groupElapsed = groupElapsed + queueElapsed = 2000 + 3000 = 5000`.

Any next queues will have to wait 5 seconds, and so on.

## Guide for contributions

![camelCase](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9p2wq09m0mqoh1eshwg4.png)

If you plan to code a new animation and create a PR to the GitHub repo, make sure the class has:

- the constructor which takes in `params` parameters, an object with `cubicon`, `duration` and `ease` properties. If the `cubicon` property accepts two or more cubicon types, please define the union TypeScript type for it.

- a `play(sleepTime: number)` method. Then, create a private method, name it as the (camelCase) form of the class name (CamelCase). Finally, call it from the `play()` method.

Phew, just imagine how many words I would have written in this article if the animation engine did not improve. It would be a... Anyway, that is everything of the animation engine. In the next article, I will talk about [d3](https://github.com/d3/d3) and how to render cubicons with it. It will definitely the great resource for you if you want to contribute to the Cubecubed project. So, stay tuned.