Невозможно установить свойство "цвет" из неопределенного - PullRequest
0 голосов
/ 25 октября 2018

Я пытаюсь сделать простую игру, похожую на candyCrush, но продолжаю получать эту ошибку и не знаю, что делать.

Uncaught TypeError: Невозможно установить свойство 'color' для undefinedв testForClick (numbercrunch2.html: 50) при обновлении (numbercrunch2.html: 62)

Чтобы воссоздать ошибку, просто поместите несколько цифр в текстовые поля, нажмите кнопку запуска и нажмите на случайную плитку,

var c = document.getElementById("canvas");
var ctx = c.getContext("2d");

var tilesX = 0,
  tilesY = 0,
  tilesWidthX, tilesWidthY, space = 3;
var numb = [];

var mousepos = {
    x: 0,
    y: 0
  },
  click = false;

function init(rows, cols) {
  tilesWidthX = (canvas.height - rows * 3) / rows;
  tilesWidthY = (canvas.height - cols * 3) / cols;
  tilesX = rows;
  tilesY = cols;

  for (var i = 0; i < tilesX; i++) {
    numb[i] = [];
    for (var j = 0; j < tilesY; j++) {
      numb[i][j] = {
        val: 1 + Math.round(Math.random() * 6),
        color: "grey"
      };

      ctx.beginPath();
      ctx.fillStyle = numb[i][j].color;
      ctx.fillRect(space + i * (tilesWidthY + space), space + j * (tilesWidthX + space), tilesWidthY, tilesWidthX);
      ctx.closePath();

      ctx.beginPath();
      ctx.fillStyle = "white";
      ctx.font = "20px Arial";
      ctx.fillText(numb[i][j].val, 15 + i * (tilesWidthY + space), 30 + j * (tilesWidthY + space), 50);
      ctx.closePath();
    }
  }
}

function testForClick(x, y) {
  if (space + x * (tilesWidthX + space) <= mousepos.x && space + y * (tilesWidthY + space) <= mousepos.y && (x + 1) * (tilesWidthX + space) >= mousepos.x && (y + 1) * (tilesWidthY + space) >= mousepos.y) {
    numb[x][y].color = "green"; //line 50
  }
}

function drawTile(x, y) {

}

function update() {
  for (var i = 0; i < 9; i++) {
    numb[i] = [];
    for (var j = 0; j < 9; j++) {
      testForClick(i, j);
      drawTile(i, j);
    }
  }
}
setInterval(update, 300);

function mouseposition(e) {

}
document.getElementById("canvas").addEventListener("click", function(e) {
  mousepos.x = e.clientX;
  mousepos.y = e.clientY;
}, false);
<canvas id="canvas" height="600" width="600"></canvas>
<form name="formname">
  Rows: <input type="text" name="rows"> Columns: <input type="text" name="columns">
  <input type="button" value="Start" onClick="init(this.form.rows.value, this.form.columns.value)">
</form>
<div id="t"></div>

1 Ответ

0 голосов
/ 26 октября 2018

Каждый раз, когда вы запускаете update(), вы буквально обновляете переменную numb, заменяя предыдущий объект пустым Array object, поэтому при вызове testForClick() в нем нет объекта, выбрасывающего error.

function update() {
    for (var i = 0;i < 9;i++) {
        numb[i] = [];
        for ( var j = 0;j < 9;j++) {
            testForClick(i,j);
            drawTile(i,j);
        }
    }
} setInterval(update,300);

Должно быть:

function update()
{
    for (var i = 0; i < 9; i++)
    {
        for (var j = 0; j < 9; j++)
        {
            testForClick(i, j);
            drawTile(i, j);
        }
    }
};

Я создал фрагмент, показывающий, как комментирование (или удаление) строки numb[i] = []; из update() сделает ее работу.

Iобновил ваш скрипт:

// Also, I renamed your 'c' var to 'canvas' because in your init() you are calling it canvas and not 'c'.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

var tilesX = 0, tilesY = 0, tilesWidthX, tilesWidthY, space = 3;
var numb = [];

var mousepos = {x: 0, y: 0}, click = false;

function init(rows, cols)
{
    tilesWidthX = (canvas.height - rows * 3) / rows;
    tilesWidthY = (canvas.height - cols * 3) / cols;
    tilesX = rows;
    tilesY = cols;

    for (var i = 0; i < tilesX; i++)
    {
        numb[i] = [];

        for (var j = 0; j < tilesY; j++)
        {
            numb[i][j] = {
                val: 1 + Math.round(Math.random() * 6),
                color: 'grey'
            };

            ctx.beginPath();
            ctx.fillStyle = numb[i][j].color;
            ctx.fillRect(space + i * (tilesWidthY + space), space + j * (tilesWidthX + space), tilesWidthY, tilesWidthX);
            ctx.closePath();

            ctx.beginPath();
            ctx.fillStyle = 'white';
            ctx.font = '20px Arial';
            ctx.fillText(numb[i][j].val, 15 + i * (tilesWidthY + space), 30 + j * (tilesWidthY + space), 50);
            ctx.closePath();
        }
    }
}

function testForClick(x, y)
{
    // Now your 'numb' variable hasn't been changed.
    console.log('testForClick', numb);

    if (space + x * (tilesWidthX + space) <= mousepos.x && space + y * (tilesWidthY + space) <= mousepos.y && (x+1) * (tilesWidthX + space) >= mousepos.x && (y+1) * (tilesWidthY + space) >= mousepos.y)
    {
        numb[x][y].color = 'green'; //line 50
    }
}

function drawTile(x, y)
{
}

function update()
{
    for (var i = 0; i < 9; i++)
    {
        // Every time you update you replace your object with 'val' and 'color' for an empty array.
        // that is the reason why every time you call testForClick you have no object in it.
        // Just comment/delete this line so your object never disappears.
        // numb[i] = [];

        for (var j = 0; j < 9; j++)
        {
            testForClick(i, j);
            drawTile(i, j);
        }
    }
};

// Changed the interval because I didn't have enough time to enter the rows and columns.
setInterval(update, 5000);

function mouseposition(e)
{
}

document.getElementById('canvas').addEventListener('click', function(e){
    mousepos.x = e.clientX;
    mousepos.y = e.clientY;
}, false);

SNIPPET:

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

var tilesX = 0, tilesY = 0, tilesWidthX, tilesWidthY, space = 3;
var numb = [];

var mousepos = {x: 0, y: 0}, click = false;

function init(rows, cols)
{
	tilesWidthX = (canvas.height - rows * 3) / rows;
	tilesWidthY = (canvas.height - cols * 3) / cols;
	tilesX = rows;
	tilesY = cols;

	for (var i = 0; i < tilesX; i++)
	{
		numb[i] = [];

		for (var j = 0; j < tilesY; j++)
		{
			numb[i][j] = {
				val: 1 + Math.round(Math.random() * 6),
				color: 'grey'
			};

			ctx.beginPath();
			ctx.fillStyle = numb[i][j].color;
			ctx.fillRect(space + i * (tilesWidthY + space), space + j * (tilesWidthX + space), tilesWidthY, tilesWidthX);
			ctx.closePath();

			ctx.beginPath();
			ctx.fillStyle = 'white';
			ctx.font = '20px Arial';
			ctx.fillText(numb[i][j].val, 15 + i * (tilesWidthY + space), 30 + j * (tilesWidthY + space), 50);
			ctx.closePath();
		}
	}
}

function testForClick(x, y)
{
	// Now your 'numb' variable hasn't been changed.
	console.log('testForClick', numb);

	if (space + x * (tilesWidthX + space) <= mousepos.x && space + y * (tilesWidthY + space) <= mousepos.y && (x+1) * (tilesWidthX + space) >= mousepos.x && (y+1) * (tilesWidthY + space) >= mousepos.y)
	{
		numb[x][y].color = 'green'; //line 50
	}
}

function drawTile(x, y)
{
}

function update()
{
	for (var i = 0; i < 9; i++)
	{
		for (var j = 0; j < 9; j++)
		{
			testForClick(i, j);
			drawTile(i, j);
		}
	}
};

setInterval(update, 5000);

function mouseposition(e)
{
}

document.getElementById('canvas').addEventListener('click', function(e){
	mousepos.x = e.clientX;
	mousepos.y = e.clientY;
}, false);
<!DOCTYPE html>
<html>
	<head>
		<title>numbercrunch 2</title>
		<meta charset="utf-8">
		<style>
			canvas {
				border: 2px solid black;
			}
		</style>
	</head>
	<body>
	<canvas id="canvas" height="600" width="600"></canvas>
	<form name="formname">
		Rows: <input type="text" name="rows">
		Columns: <input type="text" name="columns">
		<input type="button" value="Start" onClick="init(this.form.rows.value, this.form.columns.value)">
	</form>
	<div id="t"></div>
	</body>
</html>
...