Making a Lunar Lander in JavaScript

Drawing Stars

So right now what we have a spaceship which can flies around the screen, but, to be honest it looks very empty with the black background, the spaceship and the bare planet. It looks like something out of a budget version of Doctor Who.

We are going to rectify it by adding stars to the background to make it look more interesting to look at.

Calcuating the positions for the stars

What we are going to start with is our method for calculating where the stars are, and what size they are going to be.

To start, we have to declare on an array to hold our stars in:

var stars = [];

Afterwards, we have to populate the array with the stars, and the way we will store the information about each star is by storing a dictionary with the information about each star. The following code will do that:

for (var i = 0; i < 500; i++) {
  stars[i] = {
    x: Math.random() * canvas.width,
    y: Math.random() * canvas.height,
    radius: Math.sqrt(Math.random() * 2),
    alpha: 1.0,
    decreasing: true,
    dRatio: Math.random()*0.05;
  };
}

We will now break the code above into pieces to help you understand what it does, what we want is to produce information about 500 stars and the way we do it is a loop that get iterated through 500 times as you can see. Each pass of the loop adds a dictionary to the array with values for the x position (x), y position (y) size of the star (radius) how visible the star is (alpha) and whether the stars visibility is currently decreasing (decreasing). The final variable dRatio is how fast the star should twinkle, which as it is randomised make the scene seem more alive.

In order to get 500 stars in different places, we are using the random() function in the Math library and multiply it by the width and height to get an X position and Y position respectively.

Then we use a similar technique for the size of the stars as we take a random value between 0 and 1 and multiply it by 2 to get different sized stars.

We then just declare on two other variables to be used later.

Drawing the stars to the screen

Now that we have the information about our stars we need to use that information to draw them to the screen, and in order to draw them to the screen we will need to iterate through the array of stars and use the information they store to draw the different stars. A simple version of the new function drawStars() is shown below:

function drawStars() {
  context.save();
  context.fillStyle = "#111"
  context.fillRect(0, 0, canvas.width, canvas.height);
  for (var i = 0; i < stars.length; i++) {
    var star = stars[i];
    context.beginPath();
    context.arc(star.x, star.y, star.radius, 0, 2*Math.PI);
    context.closePath();
    context.fillStyle = "#bbb";
    context.fill();
  }
  context.restore();
}

As you van see this uses the information from each star to draw it on the screen, however, if you use that code and run it, the stars will look very static and not very interesting, which is why we are going to animate them with each frame, we will make them twinkle.

How do we do that? We use the alpha that we defined earlier and change the values between 0.1 and 0.95 to get the effect that we want, and the code for that will look like so:

function drawStars() 
{
  context.save();
  context.fillStyle = "#111"
  context.fillRect(0, 0, canvas.width, canvas.height);
  for (var i = 0; i < stars.length; i++) {
    var star = stars[i];
    context.beginPath();
    context.arc(star.x, star.y, star.radius, 0, 2*Math.PI);
    context.closePath();
    context.fillStyle = "rgba(255, 255, 255, " + star.alpha + ")";
    if (star.decreasing == true)
    {
      star.alpha -=dRatio;
      if (star.alpha < 0.1)
      { star.decreasing = false; }
    }
    else
    {
      star.alpha += dRatio;
      if (star.alpha > 0.95)
      { star.decreasing = true; }
    }
    context.fill();
  }
  context.restore();
}

This function will now use star.alpha to determine how bright the star should be as shown by the following line:

context.fillStyle = "rgba(255, 255, 255, " + star.alpha + ")";

Then we have to check which way the star needs to change its alpha value, if it should be decreasing we will reduce it by dRatio, otherwise, we will increase it by the same value. We also have to check for the edge cases so that we can flip that way the value is being changes, that is being done by the following bit of code:

if (star.decreasing == true)
{
  star.alpha -=dRatio;
  if (star.alpha < 0.1)
  { star.decreasing = false; }
}
else
{
  star.alpha += dRatio;
  if (star.alpha > 0.95)
  { star.decreasing = true; }
}