Learn Canvas and JavaScript Animation by Creating a Vertical Shooter (EXTENSION) – Part 10

Stage 10: Extension activities

There is still so much that can be done to our game to make it better. Ideas include:

  • Loading screen and menu so that if the Internet is slow there is some indication about how long the loading will take.
  • Adding a start menu and the ability to restart the game.
  • Parallax Scrolling, which is a visual technique where backgrounds move at different speeds to give the allusion of depth.
  • Saving High Scores.
  • Better enemies:
    • More than just three!
    • Wave patterns with some horizontal movement.
    • Enemies that can shoot.
    • End of stage “Boss”.
  • Explosion graphics.
  • … so much more.

The addition of a loading screen and Parallax scrolling is easy and allows for the introduction of two new JavaScript graphics context drawing functions, rectangles and transparency.

Loading Screen

Adding a loading screen is easy, though it will be hard to see because if your game is run from a hard drive there will be very little delay. To simulate a delay change the var numResources  to 30 but remember to change it back to 20 later otherwise your game never loads!

Add these lines to our loadingUpdate() function:

function loadingUpdate() {
  ctx.clearRect(0, 0, canvasWidth, canvasHeight);
  ctx.font = "60px Arial";
  ctx.fillStyle = 'white';
  ctx.fillText("Loading: " + loadProgress, 300, 400);
  ctx.rect(200, 450, 600, 50);
  ctx.stroke();
  ctx.fillStyle = 'green';
  ctx.fillRect(205,455,590*(loadProgress/numResources),40);

  if (loadProgress == numResources) {
    requestID = requestAnimationFrame(updateGame);
    setTimeout(function () {
      enemy1.yspeed = 3;
    }, 4000);
    setTimeout(function () {
      enemy2.yspeed = 4;
    }, 6000);
    setTimeout(function () {
      enemy3.yspeed = 5;
    }, 8000);
  }
}

Adding lines 2-9 above will draw the words “Loading: 5” in white text and under this draw a black outline box with a solid green progress bar inside. The width of the green box is calculated by dividing the number of items loaded (loadProgress) by the total number needed to be loaded (numResources).


Run the game and a loading screen should flash by quickly. If you change the numResources variable to a larger value you should see something similar to below. Make sure your change it back to 20.

Parallax Scrolling

The second simple addition we can make is adding background items that move at different speed to our islands. One idea I had was to have clouds blowing past at a slightly faster speed than our islands, it would be good to have these slightly transparent and maybe even drawn on top of all items, so our plane flies under them.

I say this is easy because the code is exactly the same as our landscape code except that it will draw our clouds with an alpha of 0.8 (eg transparent).  You can draw a simple cloud shape yourself or use the one from our images folder (https://goo.gl/f3n4QV). Either way the background of the cloud should be transparent or it will look odd.

Add the function clouds at the end of our code:

function clouds(file, x, y, width, height, wait) {
  this.wait = wait;
  this.timeout = false;
  this.image = new Image();
  
  this.image.onload = function () {
    loadProgress = loadProgress + 1;
    loadingUpdate();
  };

  this.image.src = "images/" + file;
  this.x = x;
  this.y = y;
  this.yspeed = 2;
  this.xspeed = 0;
  this.width = width;
  this.height = height;

  this.update = function () {
    this.y = this.y + this.yspeed;
    this.x = this.x + this.xspeed;
    if ((this.y > canvasHeight) && (!this.timeout)) {
      var self = this;
      setTimeout(function () {
        self.y = -100 - self.height;
        self.x = 30+Math.random()*(canvasWidth-self.width);
        self.timeout = false;
      }, self.wait);
      this.timeout = true;
    } else {
      ctx.globalAlpha = 0.8;
      ctx.drawImage(this.image,this.x,this.y,this.width,this.height);
      ctx.globalAlpha = 1;
    }
  };
}

You would have noticed one small change to our landscape code, the addition of the ctx.globalAlpha=0.8  property. This set’s the drawing context to drawn everything after this at 80% transparency. After we finish drawing out cloud we change the alpha back to 1 so it does not affect the rest of our drawing calls.

We need to load our clouds in our window.onload function. Add these lines at the end of the function (remember you can adjust the cloud sizes to fit your game theme):

window.onload = function () {
  gameCanvas = document.getElementById("gameCanvas");
  …
  …
  soundtrack = new gameAudio("01_Main Theme.mp3", true, false);
  explosionSound = new gameAudio("snd_explosion2.wav", false, true);
  bulletExplosionSound = new gameAudio("snd_explosion1.wav", false, true);
  
  cloud1=new clouds("cloud.png",Math.random()*canvasWidth,-200,400,400,2000);
  cloud2=new clouds("cloud.png",Math.random()*canvasWidth,-600,400,400,4000);
};

We also need to add the drawing method to our run loop. Add this code to gameUpdate() taking note of where you place it. The code should be placed before the score and health drawing but after our plane.update() function. This will mean that the clouds will draw on top of the plane but under the score:

function updateGame() {
  requestID = requestAnimationFrame(updateGame);
  ctx.clearRect(0, 0, canvasWidth, canvasHeight);
  landscape1.update();
  landscape2.update();
  landscape3.update();
  enemy1.update();
  enemy2.update();
  enemy3.update();
  player.update();
  for (var i = 0; i < maxBullets; i++) {
    if (bulletArray[i].active) {
      bulletArray[i].update();
    }
  }

  cloud1.update();
  cloud2.update();

  ctx.font = "30px Arial";
  ctx.fillStyle = 'white';
  ctx.fillText("Health: " + health, canvasWidth - 140, 40);
  ctx.fillText("Score: " + player.score, 20, 40);
}

Finally make sure you update the global variable numResources to 22 since we now will be loading two new cloud resources.

You may have noticed that we haven’t created any var cloud1 or var cloud2 global variables at the start of our code. Technically we never needed to create these for our sprite objects because any object written without the var keyword will automatically be created in the global scope.

Run your game now and you should have two transparent clouds floating by.

Add particle explosions to our game –> [coming soon]
Jump to: [Vertical Shooter Post: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 ]