Coding Enthusiast
Coding Enthusiast

Reputation: 51

TETRIS html5 GAME code check

Im working on a tetris project for uni. I have got most of the function to work except one. The intended flow is as follows:

  1. Index page with a button to load the game
  2. On clicking the button the game starts with a background audio(sample audio for now)
  3. on pause/play of the game the audio also should stop
  4. Once the audio is over, the game should stop and change to a div element with some text/questionnaire.

I have got steps 1-3 working, but kind of hit a bump at step 4. The page is rendered using js. I have added $('.tetrisGame').innerHTML = '<H1>GAME OVER</H1>'; to the music.oneded function. It does not render the innerHTML. So after the music stops, the console displays the message and that is it.

Also I have tried to add a hidden div element in the html file and display it after the music has ended, but the innerhtml returns null(probably because the js replaces the elements from the html file with the element rendered in the js file.

HELP NEEDED: Please check the code and let me know how to show a div element after the music stops.

Code added for verfification. Any further info in regards to code, let me know.

Thanks

var NUM_ROWS = 20;
var NUM_COLS = 10;
var BLOCK_WIDTH = 30;
var BLOCK_HEIGHT = 30;
var TICK_MS = 400;

var pieces = [
  [
    [0, 0, 0, 0],
    [0, 1, 1, 0],
    [0, 1, 1, 0],
    [0, 0, 0, 0]
  ],
  [
    [0, 0, 1, 0],
    [0, 0, 1, 0],
    [0, 0, 1, 0],
    [0, 0, 1, 0]
  ],
  [
    [0, 0, 1, 0],
    [0, 1, 1, 0],
    [0, 0, 1, 0],
    [0, 0, 0, 0]
  ],
  [
    [0, 0, 0, 0],
    [0, 0, 1, 1],
    [0, 1, 1, 0],
    [0, 0, 0, 0]
  ],
  [
    [0, 0, 0, 0],
    [0, 1, 1, 0],
    [0, 0, 1, 1],
    [0, 0, 0, 0]
  ],
  [
    [0, 0, 1, 0],
    [0, 0, 1, 0],
    [0, 1, 1, 0],
    [0, 0, 0, 0]
  ],
  [
    [0, 1, 0, 0],
    [0, 1, 0, 0],
    [0, 1, 1, 0],
    [0, 0, 0, 0]
  ]
];

var KEY_ENTER = 13;
var KEY_SPACE = 32;
var KEY_LEFT = 37;
var KEY_RIGHT = 39;
var KEY_DOWN = 40;
var KEY_A = 65;
var KEY_D = 68;
var KEY_R = 82;
var music = new Audio('http://www.sample-videos.com/audio/mp3/india-national-anthem.mp3');
//music = new Audio('http://techslides.com/demos/samples/sample.mp3');



function rotateLeft(piece) {
  return [
    [piece[0][3], piece[1][3], piece[2][3], piece[3][3]],
    [piece[0][2], piece[1][2], piece[2][2], piece[3][2]],
    [piece[0][1], piece[1][1], piece[2][1], piece[3][1]],
    [piece[0][0], piece[1][0], piece[2][0], piece[3][0]]
  ];
}

function rotateRight(piece) {
  return [
    [piece[3][0], piece[2][0], piece[1][0], piece[0][0]],
    [piece[3][1], piece[2][1], piece[1][1], piece[0][1]],
    [piece[3][2], piece[2][2], piece[1][2], piece[0][2]],
    [piece[3][3], piece[2][3], piece[1][3], piece[0][3]]
  ];
}

function intersects(rows, piece, y, x) {
  for (var i = 0; i < 4; i++)
    for (var j = 0; j < 4; j++)
      if (piece[i][j])
        if (y + i >= NUM_ROWS || x + j < 0 || x + j >= NUM_COLS || rows[y + i][x + j])
          return true;
  return false;
}

function apply_piece(rows, piece, y, x) {
  var newRows = [];
  for (var i = 0; i < NUM_ROWS; i++)
    newRows[i] = rows[i].slice();
  for (var i = 0; i < 4; i++)
    for (var j = 0; j < 4; j++)
      if (piece[i][j])
        newRows[y + i][x + j] = 1;
  return newRows;
}

function kill_rows(rows) {
  var newRows = [];
  var k = NUM_ROWS;
  for (var i = NUM_ROWS; i-- > 0;) {
    for (var j = 0; j < NUM_COLS; j++) {
      if (!rows[i][j]) {
        newRows[--k] = rows[i].slice();
        break;
      }
    }
  }
  for (var i = 0; i < k; i++) {
    newRows[i] = [];
    for (var j = 0; j < NUM_COLS; j++)
      newRows[i][j] = 0;
  }
  return {
    'rows': newRows,
    'numRowsKilled': k,
  };
}

function randomPiece() {
  return pieces[Math.floor(Math.random() * pieces.length)];
}

function TetrisGame() {
  this.gameOver = false;
  this.score = 0;
  this.currentPiece = randomPiece();
  this.nextPiece = randomPiece();
  this.pieceY = 0;
  this.pieceX = 3;
  this.rows = [];
  for (var i = 0; i < NUM_ROWS; i++) {
    this.rows[i] = []
    for (var j = 0; j < NUM_COLS; j++) {
      this.rows[i][j] = 0;
    }
  }
  playMusic();;
}

TetrisGame.prototype.tick = function() {
  if (this.gameOver)
    return false;
  if (intersects(this.rows, this.currentPiece, this.pieceY + 1, this.pieceX)) {
    /* burn current piece into board */
    this.rows = apply_piece(this.rows, this.currentPiece, this.pieceY, this.pieceX);
    var r = kill_rows(this.rows);
    this.rows = r.rows;
    this.score += r.numRowsKilled;
    /* fetch next piece */
    if (intersects(this.rows, this.nextPiece, 0, NUM_COLS / 2 - 2)) {
      this.gameOver = true;
    } else {
      this.currentPiece = this.nextPiece;
      this.pieceY = 0;
      this.pieceX = NUM_COLS / 2 - 2;
      this.nextPiece = randomPiece();
    }
  } else {
    this.pieceY += 1;
  }
  return true;
}

TetrisGame.prototype.steerLeft = function() {
  if (!intersects(this.rows, this.currentPiece, this.pieceY, this.pieceX - 1))
    this.pieceX -= 1;
}

TetrisGame.prototype.steerRight = function() {
  if (!intersects(this.rows, this.currentPiece, this.pieceY, this.pieceX + 1))
    this.pieceX += 1;
}

TetrisGame.prototype.steerDown = function() {
  if (!intersects(this.rows, this.currentPiece, this.pieceY + 1, this.pieceX))
    this.pieceY += 1;
}

TetrisGame.prototype.rotateLeft = function() {
  var newPiece = rotateLeft(this.currentPiece);
  if (!intersects(this.rows, newPiece, this.pieceY, this.pieceX))
    this.currentPiece = newPiece;
}

TetrisGame.prototype.rotateRight = function() {
  var newPiece = rotateRight(this.currentPiece);
  if (!intersects(this.rows, newPiece, this.pieceY, this.pieceX))
    this.currentPiece = newPiece;
}

TetrisGame.prototype.letFall = function() {
  while (!intersects(this.rows, this.currentPiece, this.pieceY + 1, this.pieceX))
    this.pieceY += 1;
  this.tick();
}

TetrisGame.prototype.get_rows = function() {
  return apply_piece(this.rows, this.currentPiece, this.pieceY, this.pieceX);
}

TetrisGame.prototype.get_next_piece = function() {
  return this.nextPiece;
}

TetrisGame.prototype.get_score = function() {
  return this.score;
}

TetrisGame.prototype.get_game_over = function() {
  return this.gameOver;
}

function draw_blocks(rows, num_rows, num_cols) {
  var boardElem = document.createElement('div');
  for (var i = 0; i < num_rows; i++) {
    for (var j = 0; j < num_cols; j++) {
      var blockElem = document.createElement('div');
      blockElem.classList.add('tetrisBlock');
      if (rows[i][j])
        blockElem.classList.add('habitated');
      blockElem.style.top = (i * BLOCK_HEIGHT) + 'px';
      blockElem.style.left = (j * BLOCK_WIDTH) + 'px';
      boardElem.appendChild(blockElem);
    }
  }
  return boardElem;
}

function draw_tetrisGame(game, isPaused) {
  var leftPaneElem = draw_tetrisLeftPane(game, isPaused);
  var rightPaneElem = draw_tetrisRightPane(game);
  var gameElem = document.createElement('div');
  gameElem.classList.add('tetrisGame');
  gameElem.appendChild(leftPaneElem);
  gameElem.appendChild(rightPaneElem);
  return gameElem;

}

function draw_tetrisLeftPane(game, isPaused) {
  var scoreElem = draw_tetrisScore(game, isPaused);
  var previewElem = draw_tetrisPreview(game);
  var usageElem = draw_tetrisUsage(game);
  var leftPaneElem = document.createElement('div');
  leftPaneElem.classList.add('tetrisLeftPane');
  leftPaneElem.appendChild(previewElem);
  leftPaneElem.appendChild(scoreElem);
  leftPaneElem.appendChild(usageElem);
  return leftPaneElem;
}

function draw_tetrisRightPane(game) {
  var boardElem = draw_tetrisBoard(game);
  var rightPaneElem = document.createElement('div');
  rightPaneElem.classList.add('tetrisRightPane');
  rightPaneElem.appendChild(boardElem);
  return rightPaneElem;
}

function draw_tetrisBoard(game) {
  var rows = game.get_rows();
  var boardElem = draw_blocks(rows, NUM_ROWS, NUM_COLS);
  boardElem.classList.add('tetrisBoard');
  return boardElem;
}


function draw_tetrisScore(game, isPaused) {
  var score = game.get_score();
  var scoreElem = document.createElement('div');
  scoreElem.classList.add('tetrisScore');
  scoreElem.innerHTML = '<p>SCORE: ' + score + '</p>';
  //showscore = "YOUR SCORE: " + score;
  if (isPaused)
    scoreElem.innerHTML += '<p class="blink_text">PAUSED</p>'
  if (game.get_game_over())
    scoreElem.innerHTML += '<p>GAME OVER</p>' + '<h4 class= "blink_text">PRESS <b>R</b> TO RESTART</h4>';
  return scoreElem;

}

function draw_tetrisPreview(game) {
  var piece = game.get_next_piece();
  var pieceElem = draw_blocks(piece, 4, 4);
  var previewElem = document.createElement('div');
  previewElem.classList.add('tetrisPreview');
  previewElem.appendChild(pieceElem);
  return previewElem;
}

function draw_tetrisUsage(game) {
  var usageElem = document.createElement('div');
  usageElem.classList.add('tetrisUsage');
  usageElem.innerHTML =
    "<table>" +
    "<tr><th>Keyboard Keys</th><td>Function</td></tr>" +
    "<tr><th>a/d</th><td>Rotate</td></tr>" +
    "<tr><th>Space bar</th><td>Let fall</td></tr>" +
    "<tr><th>Enter</th><td>Toggle pause</td></tr>" +
    "<tr><th>r</th><td>Restart game</td></tr>" +
    "</table>";
  return usageElem;
}

function redraw(game, isPaused, containerElem) {
  var gameElem = draw_tetrisGame(game, isPaused);
  containerElem.innerHTML = "<center style='margin-top:0;'><font size='15'>TETRIS</font><h3>Test your active listening skills</h3></center><br>";
  containerElem.appendChild(gameElem);

}

function playMusic(game) {
  music.play();
  music.onended = function(game) {
    var msg = "audio playback has ended";
    console.log(msg);
    $('.tetrisGame').innerHTML = '<H1>GAME OVER</H1>';
    //location.href = "intrimlandingpage.html";
  }
}


function tetris_run(containerElem) {
  var game = new TetrisGame();
  play1();
  playMusic();

  function play1() {
    var intervalHandler = setInterval(
      function() {
        if (game.tick())
          redraw(game, false, containerElem);
      },
      TICK_MS
    );

    function keyHandler(kev) {
      if (kev.shiftKey || kev.altKey || kev.metaKey)
        return;
      var consumed = true;
      var mustpause = false;

      if (kev.keyCode === KEY_ENTER) {
        mustpause = true;
        music.pause();
      } else if (kev.keyCode === KEY_R) {

        location.replace(location);
      } else if (kev.keyCode === KEY_LEFT) {
        game.steerLeft();
      } else if (kev.keyCode === KEY_RIGHT) {
        game.steerRight();
      } else if (kev.keyCode === KEY_DOWN) {
        game.steerDown();
      } else if (kev.keyCode === KEY_A) {
        game.rotateLeft();
      } else if (kev.keyCode === KEY_D) {
        game.rotateRight();
      } else if (kev.keyCode === KEY_SPACE) {
        game.letFall();
      } else {
        consumed = false;
      }
      if (consumed) {
        kev.preventDefault();
        if (mustpause) {
          containerElem.removeEventListener('keydown', keyHandler);
          clearInterval(intervalHandler);
          pause();

        } else {
          redraw(game, false, containerElem);
        }
      }
    }

    containerElem.addEventListener('keydown', keyHandler);
  }

  function pause() {
    function keyHandler(kev) {
      if (kev.keyCode == KEY_ENTER) {
        containerElem.removeEventListener('keydown', keyHandler);
        play1();
        music.play();
      }
    }

    containerElem.addEventListener('keydown', keyHandler);

    redraw(game, true, containerElem);
  }
}
div.tetrisGame {
  position: relative;
  margin: auto;
  padding: auto;
  border: none;
  width: 600px;
  height: 600px;
  float: left;
  right: -27%;
}

#audio1 {
  display: none;
}

div.tetrisGame div.tetrisLeftPane {
  position: absolute;
  top: 0;
  left: 0;
  width: 300px;
}

div.tetrisLeftPane div.tetrisScore {
  position: absolute;
  top: 150px;
  left: 0;
  font-size: 20pt;
}

div.tetrisLeftPane div.tetrisPreview {
  position: absolute;
  left: 150px;
  width: 120px;
  /* 4 cols * 30px */
  height: 120px;
  /* 4 rows * 30px */
}

div.tetrisLeftPane div.tetrisUsage {
  position: absolute;
  left: 0;
  top: 350px;
}

div.tetrisLeftPane div.tetrisUsage th,
div.tetrisLeftPane div.tetrisUsage td {
  text-align: left;
}

div.tetrisLeftPane div.tetrisUsage td {
  padding-left: 1em;
}

div.tetrisRightPane {
  position: absolute;
  left: 300px;
  top: 0px;
  width: 300px;
  /* 10 cols * 30px */
  height: 600px;
  /* 20 rows * 30px */
}

div.tetrisRightPane div.tetrisBoard {
  position: absolute;
  left: 0;
  top: 0;
  width: 300px;
  /* 10 cols * 30px */
  height: 600px;
  /* 20 rows * 30px */
}

div.tetrisBlock {
  position: absolute;
  width: 29px;
  height: 29px;
  border: 1px solid black;
  background-color: #EAEAEA;
}

div.tetrisBlock.habitated {
  border: 1px solid black;
  background-color: black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="author" content="Andrew Patrick">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Tetris</title>
  <link rel="stylesheet" type="text/css" href="tetris.css">
  <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700">
  <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/icon?family=Material+Icons">
  <style>
    #footer {
      position: absolute;
      bottom: 0;
      width: 100%;
      height: 60px;
      /* Height of the footer */
    }
    
    body {
      color: #666;
      font-family: sans-serif;
      line-height: 1.4;
    }
    
    h1 {
      color: #444;
      font-size: 1.2em;
      padding: 14px 2px 12px;
      margin: 0px;
    }
    
    h1 em {
      font-style: normal;
      color: #999;
    }
    
    a {
      color: #888;
      text-decoration: none;
    }
    
    #player {
      width: 400px;
      margin: auto;
    }
    
    ol {
      padding: 0px;
      margin: 0px;
      list-style: decimal-leading-zero inside;
      color: #ccc;
      width: 460px;
      border-top: 1px solid #ccc;
      font-size: 0.9em;
    }
    
    ol li {
      position: relative;
      margin: 0px;
      padding: 9px 2px 10px;
      border-bottom: 1px solid #ccc;
      cursor: pointer;
    }
    
    ol li a {
      display: block;
      text-indent: -3.3ex;
      padding: 0px 0px 0px 20px;
    }
    
    li.playing {
      color: #aaa;
      text-shadow: 1px 1px 0px rgba(255, 255, 255, 0.3);
    }
    
    li.playing a {
      color: #000;
    }
    
    li.playing:before {
      content: '♬';
      width: 14px;
      height: 14px;
      padding: 3px;
      line-height: 14px;
      margin: 0px;
      position: absolute;
      left: -24px;
      top: 17px;
      color: #000;
      font-size: 13px;
      text-shadow: 1px 1px 0px rgba(0, 0, 0, 0.2);
    }
    
    #shortcuts {
      position: fixed;
      bottom: 0px;
      width: 100%;
      color: #666;
      font-size: 0.9em;
      margin: 60px 0px 0px;
      padding: 20px 20px 15px;
      background: #f3f3f3;
      background: rgba(240, 240, 240, 0.7);
    }
    
    #shortcuts div {
      width: 460px;
      margin: 0px auto;
    }
    
    #shortcuts h1 {
      margin: 0px 0px 6px;
    }
    
    #shortcuts p {
      margin: 0px 0px 18px;
    }
    
    #shortcuts em {
      font-style: normal;
      background: #d3d3d3;
      padding: 3px 9px;
      position: relative;
      left: -3px;
      -webkit-border-radius: 4px;
      -moz-border-radius: 4px;
      -o-border-radius: 4px;
      border-radius: 4px;
      -webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
      -moz-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
      -o-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
      box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
    }
    
    @media screen and (max-device-width: auto) {
      #player {
        position: relative;
      }
    }
    
    .blink_text {
      animation: 1s blinker linear infinite;
      -webkit-animation: 1s blinker linear infinite;
      -moz-animation: 1s blinker linear infinite;
      color: red;
    }
    
    @-moz-keyframes blinker {
      0% {
        opacity: 1.0;
      }
      50% {
        opacity: 0.0;
      }
      100% {
        opacity: 1.0;
      }
    }
    
    @-webkit-keyframes blinker {
      0% {
        opacity: 1.0;
      }
      50% {
        opacity: 0.0;
      }
      100% {
        opacity: 1.0;
      }
    }
    
    @keyframes blinker {
      0% {
        opacity: 1.0;
      }
      50% {
        opacity: 0.0;
      }
      100% {
        opacity: 1.0;
      }
    }
  </style>
  <script type='text/javascript' src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
  <script src="tetris.js"></script>
</head>

<body>
  <div id="header" style="margin-top:600px; background-image:url('Header.jpg');background-size: contain; display: block; width: 100%; height: auto; padding: 0px; margin: 0px; border: none;">
    <br><br><br><br><br><br><br><br><br><br><br><br />
    <center>
      <font size="15" color="white">TETRIS</font>
      <h3>
        <font color="white">Test your active listening skills</h3>
      </font>
    </center>
  </div><br>
  <div class="container">
    <center>
      <div class="col-xs-12">
        <button id="gamerun" type="button" style="margin-top:1px ; margin-bottom:1px" onclick="tetris_run(document.body)" class="btn btn-raised btn-success btn-lg"> Start Game</button>
      </div>
    </center>
  </div>

  <center>
    <div id="footer"><b>Project Tertris 2017</b></div>
  </center>
</body>

</html>

Upvotes: 1

Views: 1631

Answers (1)

prateekm33
prateekm33

Reputation: 111

Calling $('.tetrisGame') will give back an array like jQuery object that is a list of elements that match that given class - and you will not be able to call innerHTML on that. Call instead something like this:

$('.tetrisGame')[0].innerHTML = '<H1>GAME OVER</H1>'

Or if you have multiple tetris games, then you can call the each function like so :

$('.tetrisGame').each((callback, args) => { /* do stuff */ })

Or use Array.prototype.slice.call($('.tetrisGame')) to get an Array instead to run forEach on.

Upvotes: 3

Related Questions