0

So I'm trying to make a Tetris game but when I open it in my browser I get Uncaught TypeError: Cannot read property 'length' of undefined. Tetris.html:245 in the JavaScript console. Then I go and take a look at it and it looks right so I posted it on Stackoverflow because I can't figure out what's wrong. Line 245 is in the checkMove(xpos, ypos, newState) function this is what the code for that line is. for (var r = 0, len = curPiece.states[newState].length; r < len; r++) {//code goes here} Here's the whole HTML/

<!DOCTYPE HTML>
<HTML lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="description" content="null">
  <meta name="author" content="null">
  <meta name="title" content="Tetris Clone">
  <title title="Tetris - HTML5">
   Tetris - HTML5
  </title>
  <link rel="apple-touch-icon" href="null">
  <link rel="shortcut icon" href="null">
  <link rel="stylesheet" type="text/css" href="css/tetris.css">
  <script type="text/javascript" src="http://code.jquery.com/jquery-2.1.4.js"></script>
  <script type="text/javascript" src="http://gigaboywebdesigns.com/ClassStyles.js"></script>
  <script type="text/javascript" src="js/style.js"></script>
 </head>
 <body class = "body">
  <center>
   <div id = "gameboard">
    <canvas id = "gameCanvas" class = "gameCanvas" width = "320" height = "640"></canvas>
   </div>
   
   <div id = "score" class = "score">
    <p>Lines: <span id = "lines" class = "lines"></span></p>
   </div>
  </center>
  
  <script type = "text/javascript" src = "js/pieces.js"></script>
  <script type = "text/javascript" src = "js/BulkImageLoader.js"></script>
  
  <script type = "text/javascript">
   var ROWS = 20;
   var COLS = 10;
   var SIZE = 32;
   
   var canvas
   var ctx;
   var blockImg;
   var bgImg;
   var gameOverImg;
   var curPiece;
   var gameData;
   var imgLoader;
   var prevTime;
   var curTime;
   var isGameOver;
   var lineSpan;
   var curLines;
   
   window.onload = onReady;
   
   function onReady() {
    imgLoader = new BulkImageLoader();
    imgLoader.addImage("blocks.png", "blocks");
    imgLoader.addImage("bg.png", "bg");
    imgLoader.addImage("over.png", "gameover");
    imgLoader.onReadyCallback = onImagesLoaded;
    imgLoader.loadImages();
    
    canvas = document.getElementById("gameCanvas");
    ctx = canvas.getContext("2d");
    lineSpan = document.getElementById("lines");
    
    prevTime = curTime = 0;
    
    document.onkeydown = getInput;
   }
   
   function getInput(e) {
    
   }
   
   function onImagesLoaded(e) {
    blockImg = imgLoader.getImageAtIndex(0);
    bgImg = imgLoader.getImageAtIndex(1);
    gameOverImg = imgLoader.getImageAtIndex(2);
    initGame();
   }
   
   function initGame() {
    var r, c;
    curLines = 0;
    isGameOver = false;
    
    if (gameData == undefined) {
     gameData = new Array();
     
     for (r = 0; r < ROWS; r++) {
      gameData[r] = new Array();
      
      for (c = 0; c < COLS; c++) {
       gameData[r].push(0);
      }
     }
    } else {
     for (r = 0; r < ROWS; r++) {
      for (c = 0; c < COLS; c++) {
       gameData[r][c] = 0;
      }
     }
    }
    
    curPiece = getRandomPiece();
    lineSpan.innerHTML = curLines.toString();
    
    var requestAnimFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
    
    window.requestAnimationFrame = requestAnimFrame;
    
    requestAnimationFrame(update);
   }
   
   function update() {
    curTime = new Date().getTime();
    
    if (curTime - prevTime > 500) {
     if (checkMove(curPiece.gridx, curPiece.gridy + 1, curPiece.curState)) {
      curPiece.gridy += 1;
     } else {
      copyData(curPiece);
      curPiece = getRandomPiece();
     }
     
     prevTime = curTime;
    }
    
    ctx.clearRect(0, 0, 320, 640);
    drawBoard();
    drawPiece(curPiece);
    
    if (isGameOver == false) {
     requestAnimationFrame(update);
    } else {
     ctx.drawImage(gameOverImg, 0, 0, 320, 640, 0, 0, 320, 640);
    }
   }
   
   function copyData(p) {
    var xpos = p.gridx;
    var ypos = p.gridy;
    var state = p.curState;
    
    for (var r = 0, len = p.states[state].length; r < len; r++) {
     for (var c = 0, len2 = p.states[state][r].length; c < len2; c++) {
      if (p.states[state][r][c] == 1 && ypos >= 0) {
       gameData[ypos][xpos] = (p.color + 1);
      }
      
      xpos += 1;
     }
     
     xpos = p.gridx;
     ypos += 1;
    }
    
    checkLines();
    
    if (p.gridy < 0) {
     isGameOver == true;
    }
   }
   
   function checkLines() {
    var lineFound = false;
    var fullRow = true;
    var r = ROWS - 1;
    var c = COLS -1;
    
    while(r >= 0) {
     while(c >= 0) {
      if (gameData[r][c] == 0) {
       fullRow = false;
       c = -1;
      }
      c--;
     }
     
     if (fullRow == true) {
      zeroRow(r);
      r++;
      lineFound = true;
      curLines++;
     }
     
     fullRow = true;
     c = COLS - 1;
     r--;
    }
   }
   
   function zeroRow(row) {
    var r = row;
    var c = 0;
    
    while (r >= 0) {
     while (c < COLS) {
      if (r > 0) {
       gameData[r][c] = gameData[r-1][c];
      } else {
       gameData[r][c] = 0;
      }
      c++;
     }
     
     c = 0;
     r--;
    }
   }
   
   function drawBoard() {
    ctx.drawImage(bgImg, 0, 0, 320, 640);
    
    for (var r = 0; r < ROWS; r++) {
     for (var c = 0; c < COLS; c++) {
      ctx.drawImage(blockImg, (gameData[r][c] - 1) * SIZE, 0, SIZE, SIZE, c * SIZE, r * SIZE, SIZE);
     }
    }
   }
   
   function drawPiece(p) {
    var drawX = p.gridx;
    var drawY = p.gridy;
    var state = p.curState;
    
    for (var r = 0, len = p.states[state].length; r < len; r++) {
     for (var c = 0, len2 = p.states[state][r].length; c < len2; c++) {
      if (p.states[state][r][c] == 1 && drawY >= 0) {
       ctx.drawImage(blockImg, p.color * SIZE, 0, SIZE, SIZE, drawX * SIZE, drawY * SIZE, SIZE, SIZE);
      }
      
      drawX += 1;
     }
     
     drawX = p.gridx;
     drawY += 1;
    }
   }
   
   function checkMove(xpos, ypos, newState) {
    var result = true;
    var newx = xpos;
    var newy = ypos;
    
    for (var r = 0, len = curPiece.states[newState].length; r < len; r++) {
     for (var c = 0, len2 = curPiece.states[newState][r].length; c < len2; c++) {
      if (newx < 0 || newx >= COLS) {
       result = false;
       c = len2
       r = len;
      }
      
      if (gameData[newy] != undefined && gameData[newy][newx] != 0 && curPiece.states[newState][r] != undefined && curPiece.states[newState[r][c]] != 0) {
       result = false;
       c = len2;
       r = len;
      }
      
      newx += 1;
     }
     
     newx = xpos;
     newy += 1;
     
     if (newy > ROWS) {
      r = len;
      result = false;
     }
    }
    
    return result;
   }
  </script>
 </body>
</HTML>

JS file if you need it.

Adam Oates
  • 193
  • 3
  • 12
  • The question is too long, and lacks `pieces.js` code which would make it longer. What debugging have you attempted? console logging of the `typeof` arguments and their values is often a good way to start. – traktor Feb 24 '16 at 23:02
  • Did you make any progress? – Macainian Feb 26 '16 at 03:46

1 Answers1

1

Well in short, curPiece.states[newState] is undefined. The code you put there is a lot to look through, but you should answer the question as to why that is undefined. It could be that newState is not correct, or it could be that states is undefined altogether. Perhaps the order of operations is wrong and it hasn't been created yet.

Do some debugging on what the value of curPiece.states is right before that for loop. Also check what newState is. Then report back with an update so people can help you further if needed.

Macainian
  • 362
  • 2
  • 10