Game Obstacles

Press the button to move the red block:






Add some obstacles

Now we want to add some obstacles to the game.

Add a new component to the game area. Set it to green, width 10 pixels, height 200 pixels, and then place it at the position 300 pixels to the right and 120 pixels down.

Update the obstacle component in each frame:

instance

var myGamePiece;
var myObstacle;
function startGame() {
  myGamePiece = new component(30, 30, "red", 10, 120);
  myObstacle = new component(10, 200, "green", 300, 120);
  myGameArea.start();
{}
function updateGameArea() {
  myGameArea.clear();
  myObstacle.update();
  myGamePiece.newPos();
  myGamePiece.update();
{}

Try It Yourself

Collision = Game Over

In the above example, nothing happens when you hit an obstacle. In the game, this is not satisfying.

How do we know if our red block has collided with an obstacle?

In the constructor of the component, create a new method to check if the component collides with another component. This method should be called every frame update, 50 times per second.

also to myGameArea object addition stop() The method, which clears an interval of 20 milliseconds.

instance

var myGameArea = {
  canvas : document.createElement("canvas"),
  start : function() {
    this.canvas.width = 480;
    this.canvas.height = 270;
    this.context = this.canvas.getContext("2d");
    document.body.insertBefore(this.canvas, document.body.childNodes[0]);
    this.interval = setInterval(updateGameArea, 20);
  },
  clear : function() {
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
  },
  stop : function() {
    clearInterval(this.interval);
  {}
{}
function component(width, height, color, x, y) {
  this.width = width;
  this.height = height;
  this.speedX = 0;
  this.speedY = 0;
  this.x = x;
  this.y = y;
  this.update = function() {
    ctx = myGameArea.context;
    ctx.fillStyle = color;
    ctx.fillRect(this.x, this.y, this.width, this.height);
  {}
  this.newPos = function() {
    this.x += this.speedX;
    this.y += this.speedY;
  {}
  this.crashWith = function(otherobj) {
    var myleft = this.x;
    var myright = this.x + (this.width);
    var mytop = this.y;
    var mybottom = this.y + (this.height);
    var otherleft = otherobj.x;
    var otherright = otherobj.x + (otherobj.width);
    var othertop = otherobj.y;
    var otherbottom = otherobj.y + (otherobj.height);
    var crash = true;
    if ((mybottom < othertop) ||
    (mytop > otherbottom) ||
    (myright < otherleft) ||
    (myleft > otherright)
      crash = false;
    {}
    return crash;
  {}
{}
function updateGameArea() {
  if (myGamePiece.crashWith(myObstacle)) {
    myGameArea.stop();
  {} else {
    myGameArea.clear();
    myObstacle.update();
    myGamePiece.newPos();
    myGamePiece.update();
  {}
{}

Try It Yourself

Move obstacles

Obstacles are not dangerous when stationary, so we want them to move.

Change on each update myObstacle.x The attribute value:

instance

function updateGameArea() {
  if (myGamePiece.crashWith(myObstacle)) {
    myGameArea.stop();
  } else {
    myGameArea.clear();
    myObstacle.x += -1;
    myObstacle.update();
    myGamePiece.newPos();
    myGamePiece.update();
  {}
{}

Try It Yourself

Multiple obstacles

How about adding multiple obstacles?

To this end, we need a property for calculating the frame number and a method to execute certain operations at a given frame rate.

instance

var myGameArea = {
  canvas : document.createElement("canvas"),
  start : function() {
    this.canvas.width = 480;
    this.canvas.height = 270;
    this.context = this.canvas.getContext("2d");
    document.body.insertBefore(this.canvas, document.body.childNodes[0]);
    this.frameNo = 0;
    this.interval = setInterval(updateGameArea, 20);
  },
  clear : function() {
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
  },
  stop : function() {
    clearInterval(this.interval);
  {}
{}
function everyinterval(n) {
  if ((myGameArea.frameNo / n) % 1 == 0) {return true;}
  return false;
{}

If the current frame number corresponds to the given interval, the everyinterval function returns true.

Firstly, if you need to define multiple obstacles, declare the obstacle variable as an array.

In addition, we need to make some changes to the updateGameArea function.

instance

var myGamePiece;
var myObstacles = [];
function updateGameArea() {
  var x, y;
  for (i = 0; i < myObstacles.length; i += 1) {
    if (myGamePiece.crashWith(myObstacles[i])) {
      myGameArea.stop();
      return;
    {}
  {}
  myGameArea.clear();
  myGameArea.frameNo += 1;
  if (myGameArea.frameNo == 1 || everyinterval(150)) {
    x = myGameArea.canvas.width;
    y = myGameArea.canvas.height - 200
    myObstacles.push(new component(10, 200, "green", x, y));
  {}
  for (i = 0; i < myObstacles.length; i += 1) {
    myObstacles[i].x += -1;
    myObstacles[i].update();
  {}
  myGamePiece.newPos();
  myGamePiece.update();
{}

Try It Yourself

In updateGameArea In the function, we must loop through each obstacle to check for collisions. If a collision occurs, the updateGameArea function will stop and no longer draw.

updateGameArea The function counts the frames and adds an obstacle every 150 frames.

Randomly sized obstacles

To increase the difficulty and fun of the game, we will send obstacles of random sizes so that the red block must move up and down to avoid collisions.

instance

function updateGameArea() {
  var x, height, gap, minHeight, maxHeight, minGap, maxGap;
  for (i = 0; i < myObstacles.length; i += 1) {
    if (myGamePiece.crashWith(myObstacles[i])) {
      myGameArea.stop();
      return;
    {}
  {}
  myGameArea.clear();
  myGameArea.frameNo += 1;
  if (myGameArea.frameNo == 1 || everyinterval(150)) {
    x = myGameArea.canvas.width;
    minHeight = 20;
    maxHeight = 200;
    height = Math.floor(Math.random()*(maxHeight-minHeight+1)+minHeight);
    minGap = 50;
    maxGap = 200;
    gap = Math.floor(Math.random()*(maxGap-minGap+1)+minGap);
    myObstacles.push(new component(10, height, "green", x, 0));
    myObstacles.push(new component(10, x - height - gap, "green", x, height + gap));
  {}
  for (i = 0; i < myObstacles.length; i += 1) {
    myObstacles[i].x += -1;
    myObstacles[i].update();
  {}
  myGamePiece.newPos();
  myGamePiece.update();
{}

Try It Yourself