class Ball { constructor() { this.size = 10; this.moving = false; this.speed = 7; // this.angle = 90; this.setAngle(180 +60, 360 - 60); this.color = 'red'; this.limits = null; this.angleTR = this.g2r(360); this.angleBR = this.g2r(90); this.angleBL = this.g2r(180); this.angleTL = this.g2r(270); } start() { this.moving = true; } update(ctx, x, y) { this.limits ??= { l: this.size, t: this.size, r: ctx.canvas.width - this.size, b: ctx.canvas.height }; if (this.move(x,y)) { this.draw(ctx); return true; } return false; } draw(ctx) { ctx.beginPath(); ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI, false); ctx.fillStyle = this.color; ctx.fill(); ctx.lineWidth = 1; ctx.strokeStyle = '#003300'; ctx.stroke(); } move(x,y) { if (this.moving) { this.x += this.speed * Math.cos(this.angle); this.y += this.speed * Math.sin(this.angle); // Escaped from the pad if (this.y > this.limits.b) { this.moving = false; return false; } this.collideWalls(this.limits.l, this.limits.t, this.limits.r, this.limits.b); } else { this.x = x; this.y = y - this.size - 1; } return true; } bounceL(r) { if(this.angle<=this.angleBL) this.setAngle(0 + r, 90 - r); else this.setAngle(270 + r, 360 - r); } bounceR(r) { if(this.angle<=this.angleBR) this.setAngle(90 + r, 180 - r); else this.setAngle(180 + r, 270 - r); } bounceT(r) { if(this.angle<=this.angleTL) this.setAngle(90 + r, 180 - r); else this.setAngle(0 + r, 90 - r); } bounceB(r) { if(this.angle<=this.angleBR) this.setAngle(270 + r, 360 - r); else this.setAngle(180 + r, 270 - r); } collideWalls(x0, y0, x1, y1) { let r = 20; if ( this.x <= x0 ) { this.bounceL(r); return true; } if (this.x >= x1 ) { this.bounceR(r); return true; } if (this.y <= y0 ) { this.bounceT(r); return true; } if (this.y >= y1 ) { this.bounceB(r); return true; } return false; } /* TL 270 TR 180 0 BL 90 BR B --------- R | | L --------- T */ collide(x0,y0,x1,y1) { // 0 = hit Left/Right, 1 = hit Up/Down let r = 20; if (this.x>=x0 && this.x<=x1 && (this.y+this.size)>=y0 && (this.y+this.size)=x0 && this.x<=x1 && (this.y-this.size)<=y1 && (this.y-this.size)>y0) { this.bounceT(r); return true; } if (this.y>=y0 && this.y<=y1 && (this.y+this.size)>=x0 && (this.y-this.size)=y0 && this.y<=y1 && (this.y-this.size)<=x1 && (this.y-this.size)>x0) { this.bounceL(r); return true; } return false; } setAngle(min, max) { this.angle = this.g2r(Math.floor(Math.random() * (max - min)) + min); } g2r(deg) { return (((360 + deg) % 360) * Math.PI) / 180.0; } r2g(rad) { return rad * 180 / Math.PI; } }