The animation above is based on Starfield Simulation, or Warp drive. Instead of ‘stars’ we can see flying windows. Let’s recreate this but with the latest Windows logo so the result would look like this.
Index.html links the library and sketch.js is the file we are going to work with. It contains 2 main functions by default:
setup() is used for initialization and runs only once, while draw() function runs repeatedly and is used for animation. That’s all you need to know for now about p5.js.
Warp drive with Windows simulation
Warp drive basically means travelling faster-than-light, and you might be familiar with it from the Star Trek series. Instead of stars we want to create Windows, so let’s create a few variables first.
Then in the setup() function we can iterate through the number of windows and fill the array with a newly created Window objects.
How does Window object look like? Let’s use class to define it
Window has several properties: x, y, z (coordinates) and pz , which is the previous z location. width and height are system variables defining the canvas size.
Random() function returns a random floating-point number, and we use it to randomly redistribute our windows on the screen (x , y , z).
There is also update() function we can take a look at:
Just a few things going on here.
In canvas, ‘x’ and ‘y’ start at the top left corner.
We have also the ‘z’ coordinate even though we don’t have WEBGL (3D) mode enabled. We want to simulate movement on that axis though. In the update() function we update that coordinate by subtracting speed so the objects appear to come towards us.
this.z = this.z - speed;
If ‘z’ is less than 1, the objects are out of the canvas and therefore we reset the coordinates.
In the show() function we have:
Daniel Shiffman in his source code explain the above in the comments:
with theese “map”, I get the new star positions
the division x / z get a number between 0 and a very high number,
we map this number (proportionally to a range of 0–1), inside a range of 0 — width/2.
In this way we are sure the new coordinates “sx” and “sy” move faster at each frame and which they finish their travel outside of the canvas
I’d like to point out 2 things here:
- map() function re-maps a number from one range to another.
map(value, start1, stop1, start2, stop2)
- the divisions x / z and y / z represent the equation of weak perspective projection. In other words, transforming world-space coordinates (x,y,z) to screen-space (u,v)
u = x / z;
v = y / z;
Now we can update the main draw() function:
We iterate through the windows array and call the functions we defined before on each object. You should see this:
Almost there! But we want windows!
I downloaded the Windows logo and prepared several color variants:
We need to create a preload() function and create a new variable imgs
I prepared 5 images, and gave them the same name with the number suffix, so it’s easy to load them in a loop. Now we can add another property to constructor, where we can use again the random function. We are passing an array there, so a random image variant will be picked.
Note: Instead of creating several images, I tried changing the color of the image with a tint() function, but the performance suffered greatly.
Then we just replace ellipse() in a show() function with the image() like this:
image(this.img, sx, sy, r, r);
Yay! We recreated the Windows screensaver. I feel like something is missing though.
Loading (error) sound
I wanted to play the Windows error sound in a loop as if the windows flying out of the screen were making it. P5 has an additional library called p5.sound.js that we can use for that.
We just have to update the preload function like this:
And also update the main setup() function:
Well done, you should get this RESULT.
Thank you for reading!