Asteroids Plus 2.0 - Milestone 17 - Dynamic Background Part 1


This post is broken into 2 Parts, this is Part 1

This is one of the biggest updates not only in the game but in my approach to game development.  The goal of this step is to replace the ‘space’ background image of the game with a procedurally generated starfield, with dynamic objects floating through it.  this is something that can be developed and iterated on independent of the actual game.  One of my intentions with this whole rewrite was to move away from any unowned assets in the game, and this was a big one.

So, I started off with this item as I usually do, I started a completely different project just dedicated to the development of the dynamic background.

My background is going to be a canvas element, I think that makes the most sense with respect to the type of drawing that is going to be required for this.  My intent is to have a canvas fill the screen on startup and then drawing several stars that make sense for the size of the screen. Also, over time, the stars will ‘drift’ to the right of the screen, and then they get repurposed after they leave the screen, so we have a limited amount of star objects to manage.  The stars must twinkle, with a level of pure randomness.

After the stars, we are adding objects, and for starters I’ve drawn a galaxy sprite sheet to use. 


There are a couple of concepts that I’m going to employ here:

  • geometric parallax
  • particle systems
  • request animation frame
  • Simplex Noise and Fractal Brownian Motion
  • pixel manipulation
  • animations in canvas

The geometric parallax is a visual illusion of seeing items off into the distance.  I’m going to accomplish this by creating three separate layers or fields of stars that are different size ranges, but also, they will move across the screen at different rates so that stars that are supposed to be further away, look smaller and move slower.  Stars that are closer will be larger, have a more distinct twinkle animation, and move faster across the screen.

The particle system approach will let me create arrays of star and galaxy objects that I can loop through quickly to manipulate how each object is drawn on the canvas.  Also, this lets me re-use objects that are no longer on the screen, so I must detect when a star leaves the screen on the right, and then regenerate that same star, randomly on the left of the screen to begin its journey to the right.  This prevents memory leaks by not allocating more memory to this activity over time.  Each particle in this system will be a typed object, initially a star and a galaxy.  The properties of each object will make it easier to control in the draw and update methods.  The galaxy object has a velocity parameter so that each individual galaxy can randomly have its own direction and speed moving across the canvas.  The stars velocity will be dictated by the layer, as there will be 3 layers of starts in parallax.

   

The request animation frame loop, or RAF, is the primary game loop engine for this background.  This is a recursive call to an update method that clears the canvas, redraws the background, updates all the star and object positions, then redraws them to the canvas.  This loop runs based on the refresh rate of your display, so to control this update step independently of the refresh rate, we employ a fixed step engine, which uses accumulated time as the trigger to conduct these updates.  The RAF loop as an input parameter has the elapsed time passed into it.  In parts the routine has an initialization, then I manage the overall change in time, and based on my render update parameter limits, I fire off an update, or multiple updates if the refresh time has been too long. 

The update method is boiled down to, updating the star objects position and animations, resetting the canvas, using the canvas.data.set() method, looping through each layer of starfield and redrawing each star, and then looping through the galaxies.  You can see I added some logic to change the animation update speed of the galaxies.


The Simplex noise and Brownian movement came simply from wishing to not have a boring ‘black’ void of space.  In looking at reference images of space, you see different colors.  My intent is to have a varying level of indigo also represented.  I leveraged several libraries here, as I have no desire to write my own.  I used the simplex-noise npm library, as well as chroma, for color scales, and alea for a seeding library that’s recommended to be used with simplex-noise.

The approach here is to use seed the simplex-noise library with alea, then generate a noise field of simplex noise.  If you’re not familiar with noise fields, it looks a little something like this.


A noise field like this can be used to create very ‘organic’ looking aesthetics in MANY different game dev applications.  Many use fields like this to generate terrain, or cities, or any other complex constructs.  I’m using it to vary the color of the background. 

The fractal Brownian movement (FBM) creates a manipulation of that noise field, to twist it into shapes like this:


All these will create very subtle effects in my background, but I didn’t want it to be pure black.

The initialization of the noise methods is simple.


This creates my noise field and employs 2 octaves of FMB to the noise field.  Also, I initialize a scale of colors via Chroma that let’s me vary the shades of color that get drawn.

The FBM is driven by a method that iterates over the noise field and manipulates based on the FBM algorithm, which I recommend you google if you’re interested.


The real ‘application’ of this noise field is when I use the fillCanvas() method.  This is an expensive routine, so I run it ONE time at startup. This method creates the static image of the background one time, and I copy that buffer into a saved value to reuse on each redraw.  This reduces the processing cost so I’m not regenerating this each frame.


Pixel manipulation is what I’m calling the approach to drawing all the different stars.  I could draw rectangles or circles iteratively.  But that would be a bit expensive in processing time, the fastest way to draw large amounts of canvas data is to directly write to the canvas buffer and manage each pixel one by one.  Initially, this sounds absolutely bonkers.  But its not as bad as you think.

I have 5 different radii for stars, 1pixel (px) to 5px.  Each of the three layers of star fields for the parallax has its own range of radii.  The furthest away has 1-2px, the medium is 3-4px, and the nearest field of stars has 4-5px of radius stars.   Furthermore, the 5px stars have a special animation sequence that fires since they are ‘close’ enough to see.  Smaller stars simply flicker in opacity to simulate the twinkling.  So candidly, there is a LOT going on in this.

If you recall, each star object in the particle system had a R property, and a position property(x,y) associated with it.  


This is where Part 1 Ends, below is link to Part 2

Part 2 of this article: Part 2

This currently hosted game site: https://mookie4242.itch.io/asteroids-plus-20

Twitter: @jyoung424242

SlideShare: https://www.slideshare.net/JustinYoung3/next-gen-asteroids

GitHub: https://t.co/utxHxXKdOz

Leave a comment

Log in with itch.io to leave a comment.