Simulating movement with ES6 generators
A more complex and practical example to infinite collections
One particularly good example to infinite collections and ES6 generators is movement simulation. This requires a possibly complex calculation of the points along the path, and you need to take care of a few additional cases like collision detection and eventual termination. In a traditional way, you might use a while-loop that takes care of all the necessary parts. This results in an intermingled function that does many things. Using ES6 generators, you can nicely separate the different concerns, making the code easier to understand and maintain.
This post is intended only to give an example on how to use infinite collections for a more complex use case. It is not meant to give a thorough guide on every aspect of movement simulation.
There are a few typical building blocks when you want to calculate movement. You might want to
- calculate the series of points that forms the path
- control when to terminate (for example collision detection)
- protect against infinite loops
- emit the points at a lower resolution for display
Live demo and full source are available.
For an example to this post, I’ll use a simple gravitational simulation. The user can hover over the canvas to set the initial velocity of a rock, then the path is calculated based on the gravitational pull of three planets. If the rock crashes into a planet or the infinite loop protection kicks in (after 3000 points) then the simulation terminates. Also because there is no need to have subpixel-level precision, only the points that moves at least a pixel are emitted.
Using a while-loop
Without using an infinite collection, you might use a while-loop. In this function, all concerns are mixed, and it is quite hard to reuse this function.
Using an infinite collection
If you are using an infinite collection, then the different parts can be separated. The path calculation does not need to know about neither stop conditions nor display resolution. It just emits the path infinitely.
Using the generator function from above, we can then fit the other parts in:
- limit the number of points, so that it never results in an infinite loop
- add a stop condition
- lower the display resolution
The first part uses the limit operation. The order is important; if you put it to a later stage, it can easily result in an infinite loop, which we aim to prevent. 3000 is an arbitrary number, the exact value is not that important.
The stop condition is implemented using takeWhile. It is somewhat similar to the filter, but terminates once the predicate is false. It ensures that the simulation finishes when the trajectile is crashed into a planet.
Resolution conversion is done with a simple filter. It stores the last emitted point internally, and compare the stream to see if is displaced by at least a pixel. If not, then the point is filtered out.
This example uses the gentoo library, but you can use any others you like that provides these functions.
Infinite collections are useful only in a handful of situations and I’ve found that path calculation is a great example. They allow better separation, readability, and cleaner code overall over the traditional while-loop way, all without sacrificing performance.