Siddharth Nand Siddharth Nand - 29 days ago 7
Javascript Question

Creating Objects Through Arays

I'm trying to make 2 rows and 5 columns of bricks using an object, but It doesn't seem to be working. I tried looking it up and using arrays, but It still didn't seem to work.

The bricks have a class of Brick

Demo

Here's the JavaScript

let canvas = $("#canvas")[0];
let ctx = canvas.getContext("2d");

let mouseX = 0;
let mouseY = 0;

class Paddle {
constructor(x, y, w, h, color) {
this.x = canvas.width / 2 - 100 / 2;
this.y = canvas.height - 60;
this.w = 100;
this.h = 10;
this.color = "#fff";
}

draw() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.w, this.h);
}
}

class Ball {
constructor (x, y, r, speedX, speedY, color) {
this.x = canvas.width / 2 - 10 / 2;
this.y = canvas.height / 2 - 10 / 2;
this.r = 10;
this.speedX = 3;
this.speedY = 3;
this.color = "#fff";
}

draw() {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
ctx.fill();
}

animate() {
this.x += this.speedX;
this.y += this.speedY;
}

collision() {
if(this.x >= canvas.width) {
this.speedX *= -1;
}
if(this.x <= 0) {
this.speedX *= -1;
}
if(this.y >= canvas.height) {
this.reset();
}
if(this.y <= 0) {
this.speedY *= -1;
}

let paddleTop = paddle.y;
let paddleBottom = paddleTop + paddle.h;
let paddleLeft = paddle.x;
let paddleRight = paddle.x + paddle.w;

if(ball.x >= paddleLeft &&
ball.x <= paddleRight &&
ball.y >= paddleTop &&
ball.y <= paddleBottom) {
ball.speedY *= -1;
ballControl();
}
}

reset() {
this.speedX = 3;
this.speedY = 3;

this.x = canvas.width / 2 - 10 / 2;
this.y = canvas.height / 2 - 10 / 2;
}
}

class Brick {
constructor(x, y, w, h, col, row, gap, color) {
this.x = 0;
this.y = 0;
this.w = 100;
this.h = 50;
this.col = 5; //# of brick columns
this.row = 2; //# of brick rows
this.gap = 2; //gap betweeb each brick
this.color = "#0000ff";
}

draw() {
for(let brickRow = 0; brickRow < this.row; brickRow++) {
for(let brickCol = 0; brickCol < this.col; brickCol++) {
ctx.fillStyle = this.color;
ctx.fillRect(this.x * brickCol, this.y * brickRow, this.w - this.gap, this.h - this.gap);
}
}
}
}

let paddle = new Paddle(this.x, this.y, this.w, this.h, this.color);
let ball = new Ball(this.x, this.y, this.r, this.speedX, this.speedY, this.color);
let brick = new Brick(this.x, this.y, this.w, this.h, this.col, this.row, this.gap, this.color);

// START

$(document).ready(() => {
let fps = 120;
setInterval(init, 1000 / fps);

$(canvas).bind("mousemove", paddleControl);
})

// INIT
let init = () => {
draw();
animate();
collision();
}

// DRAW
let draw = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
paddle.draw();
ball.draw();
brick.draw();
}

// ANIMATE
let animate = () => {
ball.animate();
}

// COLLISION
let collision = () => {
ball.collision();
}

// BALL CONTROL
let ballControl = () => {
let paddleCenter = paddle.x + paddle.w / 2;
let ballDistFromPaddleCenter = ball.x - paddleCenter;

ball.speedX = ballDistFromPaddleCenter * 0.15;
}

// PADDLE CONTROL
let paddleControl = (e) => {
let rect = canvas.getBoundingClientRect();
let root = document.documentElement;

mouseX = e.pageX - rect.left - root.scrollLeft;
mouseY = e.pageY - rect.top - root.scrollTop;

paddle.x = mouseX;
}

Answer

"Doesn't seem to work" is insufficient when describing your problem. You need to say what you expect and what you observe. Failing to do so has attracted 2 close votes for the reason that the question is unclear.


One of your problems is the way that you calculate the position of each brick. Another potential problem is that you have one object representing all bricks, a better way would be for each brick to be it's own object - this will simplify collision detection (a lot!)

Your code also relies upon the script element appearing after all of the HTML - while functional, this is a broken paradigm. While it is good practise to put it after the html, so that the content is first rendered as soon as possible, having code that only works when it's put there is not so good. For instance - the classes wont initialise before the canvas has been located (since they rely on it's width - a better option would be to have them rely on a separate width variable, which is set to the width of the canvas during page init)

Couldn't get the fiddle to work, nor a snippet for that matter. But here's your code reworked a little. I can now see 2 rows of 5 blue bricks.

<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<style>
#canvas {
    position: absolute;
    background-color: #000;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    margin: auto;
}
</style>
<head>
<body>
        <canvas id="canvas" width="600" height="500"></canvas>
<script>
var canvas, ctx, mouseX=0, mouseY=0;
 canvas = $("#canvas")[0];
 ctx = canvas.getContext("2d");

 mouseX = 0;
 mouseY = 0;

class Paddle
{
    constructor(x, y, w, h, color)
    {
        this.x = canvas.width / 2 - 100 / 2;
        this.y = canvas.height - 60;
        this.w = 100;
        this.h = 10;
        this.color = "#fff";
    }

    draw()
    {
        ctx.fillStyle = this.color;
        ctx.fillRect(this.x, this.y, this.w, this.h); 
    }
}

class Ball {
    constructor (x, y, r, speedX, speedY, color) {
        this.x = canvas.width / 2 - 10 / 2;
        this.y = canvas.height / 2 - 10 / 2;
        this.r = 10;
        this.speedX = 3;
        this.speedY = 3;
        this.color = "#fff";
    }

    draw() {
        ctx.fillStyle = this.color;
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
        ctx.fill();
    }

    animate() {
        this.x += this.speedX;
        this.y += this.speedY;
    }

    collision() {
        if(this.x >= canvas.width) {
            this.speedX *= -1;
        }
        if(this.x <= 0) {
            this.speedX *= -1;
        }
        if(this.y >= canvas.height) {
            this.reset();
        }
        if(this.y <= 0) {
            this.speedY *= -1;
        }

        let paddleTop = paddle.y;
        let paddleBottom = paddleTop + paddle.h;
        let paddleLeft = paddle.x;
        let paddleRight = paddle.x + paddle.w;

        if(ball.x >= paddleLeft &&
           ball.x <= paddleRight &&
           ball.y >= paddleTop &&
           ball.y <= paddleBottom) {
            ball.speedY *= -1;
            ballControl();
        }
    }

    reset() {
        this.speedX = 3;
        this.speedY = 3;

        this.x = canvas.width / 2 - 10 / 2;
        this.y = canvas.height / 2 - 10 / 2;
    }
}

class Brick {
    constructor(x, y, w, h, col, row, gap, color) {
        this.x = 0;
        this.y = 0;
        this.w = 100;
        this.h = 50;
        this.col = 5; //# of brick columns
        this.row = 2; //# of brick rows
        this.gap = 2; //gap betweeb each brick
        this.color = "#0000ff";
    }

    draw() {
        for(let brickRow = 0; brickRow < this.row; brickRow++) 
        {
            for(let brickCol = 0; brickCol < this.col; brickCol++) 
            {
                ctx.fillStyle = this.color;
                ctx.fillRect( (this.w+this.gap) * brickCol, (this.h+this.gap) * brickRow, this.w, this.h );
            }
        }
    }
}

let paddle = new Paddle(this.x, this.y, this.w, this.h, this.color);
let ball = new Ball(this.x, this.y, this.r, this.speedX, this.speedY, this.color);
let brick = new Brick(this.x, this.y, this.w, this.h, this.col, this.row, this.gap, this.color);

// START

$(document).ready(() => {
    let fps = 120;
    setInterval(init, 1000 / fps);

    $(canvas).bind("mousemove", paddleControl);
})

// INIT
let init = () => {
    draw();
    animate();
    collision();
}

// DRAW
let draw = () => {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    paddle.draw();
    ball.draw();
    brick.draw();
}

// ANIMATE
let animate = () => {
    ball.animate();
}

// COLLISION
let collision = () => {
    ball.collision();
}

// BALL CONTROL
let ballControl = () => {
    let paddleCenter = paddle.x + paddle.w / 2;
    let ballDistFromPaddleCenter = ball.x - paddleCenter;

    ball.speedX = ballDistFromPaddleCenter * 0.15;
}

// PADDLE CONTROL
let paddleControl = (e) => {
    let rect = canvas.getBoundingClientRect();
    let root = document.documentElement;

    mouseX = e.pageX - rect.left - root.scrollLeft;
    mouseY = e.pageY - rect.top - root.scrollTop;

    paddle.x = mouseX;
}
</script>
</body>
</html>
Comments