Make your own fun page 404 game

Make your own fun page 404 game

Reduce the Pain of an error Page by Adding a fun page 404 game of Tetris.

Make your own fun page 404 game

Hey there, fellow experts! Are you tired of the same old boring page 404? You know, that frustrating error page that pops up when you’re trying to access a non-existent or broken link on a website. Well, guess what? I’ve got some exciting news for you! We have found a fantastic solution to turn that dreaded page 404 experience into something quick, fun, and enjoyable – by adding a Tetris game! Yes, you read that right. So, buckle up and get ready to learn how you can reduce the pain of a page 404 and inject some gaming joy into your error pages!

Why a Page 404 Can Be Frustrating

Before we dive into the solution, let’s quickly understand why encountering a page 404 can be such a frustrating experience. Here are a few reasons:

  1. Disruption of User Experience: When users land on a page 404, they expect to find the information they were seeking. However, encountering an error disrupts their browsing experience and leaves them feeling unsatisfied.

  2. Lost Opportunities: A page 404 signifies a missed opportunity to engage and retain users. If not handled properly, it can lead to users abandoning your website and never returning.

  3. Negative Perception: Page 404s can give users the impression that your website is not well-maintained or reliable. It may lead them to question the credibility of your content or products/services.

The Tetris Game Solution

Now, let’s get to the exciting part! By incorporating a quick and fun Tetris game into your page 404, you can transform a negative experience into a positive one. Here’s why adding a Tetris game is a brilliant idea:

  1. Engagement and Entertainment: Instead of staring at a dull page 404, users can now enjoy playing a classic game of Tetris. It provides an engaging and entertaining experience that keeps users on your website for longer.

  2. Positive User Experience: By offering a fun distraction, you can turn a frustrating situation into a delightful one. Users will appreciate the effort put into making their experience enjoyable, even when things go wrong.

  3. Increased Brand Recall: Imagine a user remembering your website not just for its excellent content but also for the memorable Tetris game they played on your page 404. It’s a unique way to leave a lasting impression and increase brand recall.

How to Implement the page 404 game

Implementing a Tetris game on your page 404 doesn’t have to be a complicated process. Here’s a simple step-by-step guide to help you get started:

  1. Choose a Tetris Library: There are various JavaScript libraries available that allow you to easily integrate a Tetris game into your website. Some popular options include Tetris.js and React Tetris.

  2. Customize the Game: Once you’ve selected a Tetris library, you can customize the game to match the look and feel of your website. Consider incorporating your brand colors and logo to maintain consistency.

  3. Integrate with Page 404: Add the necessary code to display the Tetris game whenever a user encounters a page 404. You can do this by modifying your server-side code or using a content management system (CMS) if you’re using one.

  4. Provide an Exit Option: While playing Tetris can be fun, it’s important to provide users with an option to return to their original intent. Include a prominent “Return to Home” button or a clear navigation path back to the main website.

Benefits of Adding a page 404 game to an annoying error page

Now that you know how to implement a Tetris game, let’s explore the benefits it brings to your website and users:

  • Enhanced User Engagement: A Tetris game on your page 404 encourages users to stay on your website longer, boosting overall engagement metrics.

  • Reduced Bounce Rates: Instead of bouncing away from your website after encountering an error, users will be more likely to explore and navigate further after enjoying a round of Tetris.

  • Positive Brand Perception: Users appreciate when a website goes the extra mile to make their experience enjoyable, even in unexpected situations. Adding a Tetris game demonstrates your dedication to providing a positive user experience.

  • Social Sharing Potential: A delightful and unexpected surprise like a Tetris game on a page 404 is something users love to share with others. It can generate social media buzz and attract new visitors to your website.

  • Error Tracking Opportunities: While the Tetris game adds an element of fun, it’s crucial to continue monitoring and analyzing the frequency and cause of page 404 errors. This information can help you improve your website’s overall user experience.

Here is our take

<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>404 - Page not found</title>
  <meta charset="UTF-8">
  <link href="https://fonts.googleapis.com/css?family=VT323" rel="stylesheet">

  <style>
  html, body {
    height: 100%;
    margin: 0;
    font-family: 'VT323', sans-serif;
  }

  body {
    background: black;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  canvas {
    border: 1px solid white;
  }

  .footer {
   position: fixed;
   left: 0;
   bottom: 0;
   width: 100%;
   background-color: gainsboro;
   color: white;
   text-align: center;
}

 .header {
   position: fixed;
   left: 0;
   top: 0;
   width: 100%;
   background-color: gainsboro;
   color: #000;
   text-align: center;
}

  </style>
</head>
<body>

<canvas width="320" height="640" id="game"></canvas>

<div class="header">
  <h1>404 - Page Not Found</h1>
</div>

<div class="footer">
  <p><button onclick="history.back()">That page was not found - Click to go Back..or play!</button></p>
</div>

<script>

// get a random integer between the range of [min,max]
function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);

  return Math.floor(Math.random() * (max - min + 1)) + min;
}

// generate a new tetromino sequence
function generateSequence() {
  const sequence = ['I', 'J', 'L', 'O', 'S', 'T', 'Z'];

  while (sequence.length) {
    const rand = getRandomInt(0, sequence.length - 1);
    const name = sequence.splice(rand, 1)[0];
    tetrominoSequence.push(name);
  }
}

// get the next tetromino in the sequence
function getNextTetromino() {
  if (tetrominoSequence.length === 0) {
    generateSequence();
  }

  const name = tetrominoSequence.pop();
  const matrix = tetrominos[name];

  // I and O start centered, all others start in left-middle
  const col = playfield[0].length / 2 - Math.ceil(matrix[0].length / 2);

  // I starts on row 21 (-1), all others start on row 22 (-2)
  const row = name === 'I' ? -1 : -2;

  return {
    name: name,      // name of the piece (L, O, etc.)
    matrix: matrix,  // the current rotation matrix
    row: row,        // current row (starts offscreen)
    col: col         // current col
  };
}

// rotate an NxN matrix 90deg
function rotate(matrix) {
  const N = matrix.length - 1;
  const result = matrix.map((row, i) =>
    row.map((val, j) => matrix[N - j][i])
  );

  return result;
}

// check to see if the new matrix/row/col is valid
function isValidMove(matrix, cellRow, cellCol) {
  for (let row = 0; row < matrix.length; row++) {
    for (let col = 0; col < matrix[row].length; col++) {
      if (matrix[row][col] && (
          // outside the game bounds
          cellCol + col < 0 ||
          cellCol + col >= playfield[0].length ||
          cellRow + row >= playfield.length ||
          // collides with another piece
          playfield[cellRow + row][cellCol + col])
        ) {
        return false;
      }
    }
  }

  return true;
}

// place the tetromino on the playfield
function placeTetromino() {
  for (let row = 0; row < tetromino.matrix.length; row++) {
    for (let col = 0; col < tetromino.matrix[row].length; col++) {
      if (tetromino.matrix[row][col]) {

        // game over if piece has any part offscreen
        if (tetromino.row + row < 0) {
          return showGameOver();
        }

        playfield[tetromino.row + row][tetromino.col + col] = tetromino.name;
      }
    }
  }

  // check for line clears starting from the bottom and working our way up
  for (let row = playfield.length - 1; row >= 0; ) {
    if (playfield[row].every(cell => !!cell)) {

      // drop every row above this one
      for (let r = row; r >= 0; r--) {
        for (let c = 0; c < playfield[r].length; c++) {
          playfield[r][c] = playfield[r-1][c];
        }
      }
    }
    else {
      row--;
    }
  }

  tetromino = getNextTetromino();
}

// show the game over screen
function showGameOver() {
  cancelAnimationFrame(rAF);
  gameOver = true;

  context.fillStyle = 'black';
  context.globalAlpha = 0.75;
  context.fillRect(0, canvas.height / 2 - 30, canvas.width, 60);

  context.globalAlpha = 1;
  context.fillStyle = 'white';
  context.font = '36px monospace';
  context.textAlign = 'center';
  context.textBaseline = 'middle';
  context.fillText('GAME OVER!', canvas.width / 2, canvas.height / 2);
}

const canvas = document.getElementById('game');
const context = canvas.getContext('2d');
const grid = 32;
const tetrominoSequence = [];

// keep track of what is in every cell of the game using a 2d array
// tetris playfield is 10x20, with a few rows offscreen
const playfield = [];

// populate the empty state
for (let row = -2; row < 20; row++) {
  playfield[row] = [];

  for (let col = 0; col < 10; col++) {
    playfield[row][col] = 0;
  }
}

// how to draw each tetromino
const tetrominos = {
  'I': [
    [0,0,0,0],
    [1,1,1,1],
    [0,0,0,0],
    [0,0,0,0]
  ],
  'J': [
    [1,0,0],
    [1,1,1],
    [0,0,0],
  ],
  'L': [
    [0,0,1],
    [1,1,1],
    [0,0,0],
  ],
  'O': [
    [1,1],
    [1,1],
  ],
  'S': [
    [0,1,1],
    [1,1,0],
    [0,0,0],
  ],
  'Z': [
    [1,1,0],
    [0,1,1],
    [0,0,0],
  ],
  'T': [
    [0,1,0],
    [1,1,1],
    [0,0,0],
  ]
};

// color of each tetromino
const colors = {
  'I': 'cyan',
  'O': 'yellow',
  'T': 'purple',
  'S': 'green',
  'Z': 'red',
  'J': 'blue',
  'L': 'orange'
};

let count = 0;
let tetromino = getNextTetromino();
let rAF = null;  // keep track of the animation frame so we can cancel it
let gameOver = false;

// game loop
function loop() {
  rAF = requestAnimationFrame(loop);
  context.clearRect(0,0,canvas.width,canvas.height);

  // draw the playfield
  for (let row = 0; row < 20; row++) {
    for (let col = 0; col < 10; col++) {
      if (playfield[row][col]) {
        const name = playfield[row][col];
        context.fillStyle = colors[name];

        // drawing 1 px smaller than the grid creates a grid effect
        context.fillRect(col * grid, row * grid, grid-1, grid-1);
      }
    }
  }

  // draw the active tetromino
  if (tetromino) {

    // tetromino falls every 35 frames
    if (++count > 35) {
      tetromino.row++;
      count = 0;

      // place piece if it runs into anything
      if (!isValidMove(tetromino.matrix, tetromino.row, tetromino.col)) {
        tetromino.row--;
        placeTetromino();
      }
    }

    context.fillStyle = colors[tetromino.name];

    for (let row = 0; row < tetromino.matrix.length; row++) {
      for (let col = 0; col < tetromino.matrix[row].length; col++) {
        if (tetromino.matrix[row][col]) {

          // drawing 1 px smaller than the grid creates a grid effect
          context.fillRect((tetromino.col + col) * grid, (tetromino.row + row) * grid, grid-1, grid-1);
        }
      }
    }
  }
}

// listen to keyboard events to move the active tetromino
document.addEventListener('keydown', function(e) {
  if (gameOver) return;

  // left and right arrow keys (move)
  if (e.which === 37 || e.which === 39) {
    const col = e.which === 37
      ? tetromino.col - 1
      : tetromino.col + 1;

    if (isValidMove(tetromino.matrix, tetromino.row, col)) {
      tetromino.col = col;
    }
  }

  // up arrow key (rotate)
  if (e.which === 38) {
    const matrix = rotate(tetromino.matrix);
    if (isValidMove(matrix, tetromino.row, tetromino.col)) {
      tetromino.matrix = matrix;
    }
  }

  // down arrow key (drop)
  if(e.which === 40) {
    const row = tetromino.row + 1;

    if (!isValidMove(tetromino.matrix, row, tetromino.col)) {
      tetromino.row = row - 1;

      placeTetromino();
      return;
    }

    tetromino.row = row;
  }
});

// start the game
rAF = requestAnimationFrame(loop);
</script>
</body>
</html>

You can see the page 404 Tetris live at this URL.

Conclusion

Why settle for a boring and frustrating page 404 experience when you can inject some quick and fun gaming joy into it? By adding a Tetris game, you transform an annoying error page into an engaging and memorable encounter for your users. It’s an excellent opportunity to turn a negative situation into a positive one while increasing user engagement, reducing bounce rates, and leaving a lasting impression. So, what are you waiting for? Let the Tetris game begin!


FAQ

Q: Will a page 404 game slow down my website’s load time?

A: When implemented correctly, the impact on your website’s load time should be minimal. Make sure to optimize the game’s code and assets for optimal performance.

Q: Can I add a different game instead of Tetris?

A: Absolutely! While Tetris is a classic and popular choice, you can integrate any game of your preference as long as it provides a quick and enjoyable experience.

Q: Are there any legal concerns when adding a page 404 game to my website?

A: It’s important to ensure that you have the necessary rights or licenses to use the game you intend to add. Consider using open-source or licensed games that allow for integration on websites.

Q: How can I track and analyze the frequency of page 404 errors?

A: You can utilize various website analytics tools, such as Google Analytics, to track the number of page 404 errors and analyze the underlying causes. This data will help you identify areas for improvement.

Q: Can I customize the Tetris game to match my website’s branding?

A: Yes, most Tetris libraries allow customization options. You can modify the game’s colors, fonts, and even incorporate your website’s logo to create a cohesive visual experience.

Share
Share
Website maintenance by: dp