При запуске видает ошибку Uncaught TypeError: Cannot read property 'draw' of undefined. Что нужно поменять?

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

var width = canvas.width
var height = canvas.height


var Ball = function(){
    this.x = 100;
    this.y = 100;
    this.xSpeed = Math.floor(Math.random()* 4);
    this.ySpeed = Math.floor(Math.random()* -4);
}

var balls = []

for(var i = 0; i < 10; i++){balls[i] = new Ball()}

var circle = function(x,y,radius,kek){   
    ctx.beginPath();
    ctx.arc(x,y,radius,0,Math.PI * 2,false);
    ctx.stroke();
    if(kek){ctx.fill()};
    }

Ball.prototype.draw = function(){circle(this.x,this.y,3,true)}

Ball.prototype.move = function(){this.x += this.xSpeed,this.y += this.ySpeed}

Ball.prototype.checkCollision = function() {
    if(this.x < 0 || this.x > width){this.xSpeed = -this.xSpeed};

    if(this.y < 0 || this.y > height){this.ySpeed = -this.ySpeed};
}


for(var j = 0;j < balls.length;j++){
    setInterval(function(){
    ctx.clearRect(0,0,width,height);
    balls[i].draw();
    balls[i].move();
    balls[i].checkCollision();
    ctx.strokeRect(0,0,width,height);
},30)}

Ответы (1 шт):

Автор решения: Peter Lavreniuk

Вы все перепутали в последнем фрагменте кода. У вас в цикле for переменная i, но внутри вы работаете с j. Так же нужно вначале объявлять интервал, а уже внутри проходить по циклу.

setInterval(function () {
  ctx.clearRect(0, 0, width, height);
  for(var j = 0;j < balls.length;j++){
    balls[j].draw();
    balls[j].move();
    balls[j].checkCollision();
  }
  ctx.strokeRect(0, 0, width, height);
}, 30);

Так же лучше вместо :

for(var i = 0; i < 10; i++){balls[i] = new Ball()}

Делать так :

for(var i = 0; i < 10; i++){
  var ball = new Ball();
  balls.push(ball)
}

Никто по рукам бить не будет, но все таки лучше не с индексами работать...

Рабочая версия:

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

var width = canvas.width;
var height = canvas.height;

var balls = []

var Ball = function(){
    this.x = 100;
    this.y = 100;
    this.xSpeed = Math.floor(Math.random()* 4);
    this.ySpeed = Math.floor(Math.random()* -4);
}

var circle = function(x,y,radius,kek){   
    ctx.beginPath();
    ctx.arc(x,y,radius,0,Math.PI * 2,false);
    ctx.stroke();
    if(kek){ctx.fill()};
    }

Ball.prototype.checkCollision = function() {
    if(this.x < 0 || this.x > width){this.xSpeed = -this.xSpeed};

    if(this.y < 0 || this.y > height){this.ySpeed = -this.ySpeed};
}

Ball.prototype.draw = function(){circle(this.x,this.y,3,true)};

Ball.prototype.move = function(){this.x += this.xSpeed,this.y += this.ySpeed};


for(var i = 0; i < 10; i++){
  var ball = new Ball();
  balls.push(ball)
}
   
setInterval(function () {
  ctx.clearRect(0, 0, width, height);
  for(var j = 0;j < balls.length;j++){
    balls[j].draw();
    balls[j].move();
    balls[j].checkCollision();
  }
  ctx.strokeRect(0, 0, width, height);
}, 30);
<canvas id="canvas" width="200" height="100"></canvas>

→ Ссылка