Click on the blue rectangle to drop the upper box on top of lower box!

Tower game


Click to drop the upper box on top of lower box!

Full screen mode

The point of this game is to stack as many boxes on top of one another as possible.
When you click on the screen, the bouncing box starts to fall. Unless you click in the exact moment when the two boxes are ideally aligned, the part of the box that is sticking out falls off the screen ("debris") and the next box has less room for landing.
To make things even harder, each box bounces faster than the previous one.

The full source code is below and here is a brief explanation:

[Lines 1-7] Initiate the HTML5 Canvas.
[8-20] Declare variables and objects.
[22-28] The function that create a new box after the previous one falls.
[30-33] The 'Game over' function.
[35-89] The main game loop. Let's look at the details since this is where all the action is.
[36] If the game is active:
[37-38] Clear the previous frame and display the score.
[39-43] Draw all the boxes.
[41] Select the color of the box.
[44-45] Draw the debris.
[46] If the game is in the 'bounce' mode (the current box is bouncing horizontally off the walls):
[47-52] Move the current box in the x axis. Reverse the direction if it hits a wall.
[53] If the game is in the 'fall' mode (the current box has been released):
[54] Move the current box in the y axis.
[55] If it lands on top of the previous box:
[56] Change the mode back to 'bounce'.
[57] Calculate the length of the non-overlapping part.
[58-60] If the difference is greater than the box, it means the player missed completely: game over!
[61-64] Update the debris object.
[65-72] Determine whether the debris should be on the left or the right side of the box.
[73-76] Increase the bouncing speed.
[77-79] Create the new box.
[82] Animate the debris - it keeps falling until it gets updated again in [61-64].
[83-85] The scrollCounter determines for how many frames the camera should move up. If it's positive, the camera position is updated.
[88] Wait for the next animation frame
[91] Function that reassigns initial values to the variables at the beginning of a new game.
[102-109] The click (mouse or touch) handler:
[103-4] If we're in the 'gameOver' mode, just restart the game.
[106-7] If we're in the 'bounce' mode, switch to 'fall' (release the box).
[111] Initialize the first game.
[112] Kick off the animation.

<html>
<body>
<canvas id="myCanvaswidth="800height="600"></canvas>
<script>
let canvas = document.getElementById("myCanvas");
let context = canvas.getContext("2d");
context.font = 'bold 30px sans-serif';
let scrollCountercameraYcurrentmodexSpeed;
let ySpeed = 5;
let height = 50;
let boxes = [];
boxes[0] = {
  x300,
  y300,
  width200
};
let debris = {
  x0,
  width0
};
 
function newBox() {
  boxes[current] = {
    x0,
    y: (current + 10) * height,
    widthboxes[current - 1].width
  };
}
 
function gameOver() {
  mode = 'gameOver';
  context.fillText('Game overClick to play again!', 5050);
}
 
function animate() {
  if (mode != 'gameOver') {
    context.clearRect(00canvas.widthcanvas.height);
    context.fillText('Score: ' + (current - 1).toString(), 100200);
    for (let n = 0n < boxes.lengthn++) {
      let box = boxes[n];
      context.fillStyle = 'rgb(' + n * 16 + ',' + n * 16 + ',' + n * 16 + ')';
      context.fillRect(box.x600 - box.y + cameraYbox.widthheight);
    }
    context.fillStyle = 'red';
    context.fillRect(debris.x600 - debris.y + cameraYdebris.widthheight);
    if (mode == 'bounce') {
      boxes[current].x = boxes[current].x + xSpeed;
      if (xSpeed > 0 && boxes[current].x + boxes[current].width > canvas.width)
        xSpeed = -xSpeed;
      if (xSpeed < 0 && boxes[current].x < 0)
        xSpeed = -xSpeed;
    }
    if (mode == 'fall') {
      boxes[current].y = boxes[current].y - ySpeed;
      if (boxes[current].y == boxes[current - 1].y + height) {
        mode = 'bounce';
        let difference = boxes[current].x - boxes[current - 1].x;
        if (Math.abs(difference) >= boxes[current].width) {
          gameOver();
        }
        debris = {
          yboxes[current].y,
          widthdifference
        };
        if (boxes[current].x > boxes[current - 1].x) {
          boxes[current].width = boxes[current].width - difference;
          debris.x = boxes[current].x + boxes[current].width;
        } else {
          debris.x = boxes[current].x - difference;
          boxes[current].width = boxes[current].width + difference;
          boxes[current].x = boxes[current - 1].x;
        }
        if (xSpeed > 0)
          xSpeed++;
        else
          xSpeed--;
        current++;
        scrollCounter = height;
        newBox();
      }
    }
    debris.y = debris.y - ySpeed;
    if (scrollCounter) {
      cameraY++;
      scrollCounter--;
    }
  }
  window.requestAnimationFrame(animate);
}
 
function restart() {
  boxes.splice(1boxes.length - 1);
  mode = 'bounce';
  cameraY = 0;
  scrollCounter = 0;
  xSpeed = 2;
  current = 1;
  newBox();
  debris.y = 0;
}
 
canvas.onpointerdown = function() {
  if (mode == 'gameOver')
    restart();
  else {
    if (mode == 'bounce')
      mode = 'fall';
  }
};
 
restart();
animate();
</script>
</body>
</html>





Check out these programming tutorials:

JavaScript:

Optical illusion (18 lines)

Spinning squares - visual effect (25 lines)

Oldschool fire effect (20 lines)

Fireworks (60 lines)

Animated fractal (32 lines)

Physics engine for beginners

Physics engine - interactive sandbox

Physics engine - silly contraption

Starfield (21 lines)

Yin Yang with a twist (4 circles and 20 lines)

Tile map editor (70 lines)

Sine scroller (30 lines)

Interactive animated sprites

Image transition effect (16 lines)

Your first program in JavaScript: you need 5 minutes and a notepad


Fractals in Excel

Python in Blender 3d:

Domino effect (10 lines)


Wrecking ball effect (14 lines)

3d fractal in Blender Python