<repo_name>cksharma11/bricks<file_sep>/src/paddle.js
class Paddle {
  constructor(height, width, bottom, left, speed = 10) {
    this.height = height;
    this.width = width;
    this.bottom = bottom;
    this.left = left;
    this.speed = speed;
  }

  moveLeft() {
    this.left = Math.max(0, this.left - this.speed);
  }

  moveRight() {
    this.left = Math.min(760, this.left + this.speed);
  }

  isWithinRange(difference) {
    return difference > 0 && difference < this.width;
  }

  doesCollideWith(ball) {
    const difference = ball.getPositionX() - this.left;
    return this.isWithinRange(difference) && ball.getPositionY() < this.height;
  }

  manageCollisionWith(ball, velocity) {
    const newVelocity = new Velocity(velocity.x, velocity.y);
    if (this.doesCollideWith(ball)) newVelocity.negateY();
    return newVelocity;
  }
}
<file_sep>/src/brick.js
class Brick {
  constructor(height, width, positionX, positionY) {
    this.height = height;
    this.width = width;
    this.positionX = positionX;
    this.positionY = positionY;
    this.brickStore = [];
    this.collideCount = 0;
  }

  increaseCollideCount() {
    this.collideCount += 1;
  }

  storeBricks(brick) {
    this.brickStore.push(brick);
  }

  checkCollision(differenceInPositionX, differenceInPositionY) {
    const isWithinX =
      differenceInPositionX >= 0 && differenceInPositionX <= 110;
    const isWithinY = differenceInPositionY >= 0 && differenceInPositionY <= 20;
    return isWithinX && isWithinY;
  }

  doesCollideWith(brick, ball) {
    const differenceInPositionX = ball.positionX - brick.X;
    const differenceInPositionY = brick.Y - ball.positionY;
    return this.checkCollision(differenceInPositionX, differenceInPositionY);
  }

  manageCollisionWith(ball, velocity) {
    const newVelocity = new Velocity(velocity.x, velocity.y);
    const doesCollide = this.brickStore.some(brick => {
      if (!this.doesCollideWith(brick, ball)) return false;
      document.getElementById(brick.ID).remove();
      delete this.brickStore[brick.ID];
      this.increaseCollideCount();
      return true;
    });
    if (doesCollide) newVelocity.negateY();

    return newVelocity;
  }
}
<file_sep>/src/velocity.js
class Velocity {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  negateX() {
    this.x *= -1;
  }
  negateY() {
    this.y *= -1;
  }
}
<file_sep>/src/game.js
class Game {
  constructor(screen, paddle, ball, brick) {
    this.screen = screen;
    this.paddle = paddle;
    this.ball = ball;
    this.brick = brick;
  }

  score() {
    return this.brick.collideCount;
  }

  lifesCount() {
    return this.screen.lifeCount;
  }

  checkCollision() {
    let velocity = this.paddle.manageCollisionWith(
      this.ball,
      this.ball.velocity
    );

    velocity = this.brick.manageCollisionWith(this.ball, velocity);
    velocity = this.screen.manageCollisionWith(this.ball, velocity);
    return velocity;
  }

  updateState() {
    const velocity = this.checkCollision();
    this.ball.setVelocity(velocity);
    this.ball.move();
  }
}
<file_sep>/src/screen.js
class Screen {
  constructor(height, width) {
    this.height = height;
    this.width = width;
    this.lifeCount = 3;
  }

  decreaseLifeCount() {
    this.lifeCount -= 1;
  }

  doesRightOrLeftCollide(ball) {
    return ball.getPositionX() == 920 || ball.getPositionX() == 0;
  }
  doesTopCollide(ball) {
    return ball.getPositionY() == 559;
  }

  doesBottomCollide(ball) {
    return ball.getPositionY() == 1;
  }

  manageCollisionWith(ball, velocity) {
    const newVelocity = new Velocity(velocity.x, velocity.y);
    if (this.doesTopCollide(ball)) newVelocity.negateY();
    if (this.doesRightOrLeftCollide(ball)) newVelocity.negateX();
    if (this.doesBottomCollide(ball)) {
      newVelocity.negateY();
      this.decreaseLifeCount();
    }
    return newVelocity;
  }
}
<file_sep>/src/ball.js
class Ball {
  constructor(radius, positionX, positionY, velocity) {
    this.height = radius;
    this.width = radius;
    this.positionX = positionX;
    this.positionY = positionY;
    this.velocity = velocity;
  }
  move() {
    this.positionX += this.velocity.x;
    this.positionY += this.velocity.y;
  }

  setVelocity(velocity) {
    this.velocity = velocity;
  }

  getVelocityX() {
    return this.velocity.x;
  }

  getVelocityY() {
    return this.velocity.y;
  }

  getPositionX() {
    return this.positionX;
  }

  getPositionY() {
    return this.positionY;
  }
}
<file_sep>/test/game.test.js
const expect = chai.expect;

describe('Paddle', () => {
  it('should subtract 10 from left position of paddle', () => {
    const paddle = new Paddle(20, 100, 5, 430);
    paddle.moveLeft();
    expect(paddle)
      .to.have.property('left')
      .equals(420);
  });

  it('should add 10 to left position of paddle', () => {
    const paddle = new Paddle(20, 100, 5, 430);
    paddle.moveRight();
    expect(paddle)
      .to.have.property('left')
      .equals(440);
  });

  it('should return true when difference between ball.x and paddle.x is between 200 and ball height is less then 25', () => {
    const paddle = new Paddle(10, 100, 100, 100);
    const ball = new Ball(10, 200, 10);
    expect(paddle.doesCollideWith(ball)).to.equals(true);
  });

  it('should return false when difference between ball.x and paddle.x is not between 200 and ball height is less then 25', () => {
    const paddle = new Paddle(10, 100, 100, 100);
    const ball = new Ball(10, 100, 10);
    expect(paddle.doesCollideWith(ball)).to.equals(false);
  });
});

describe('Ball', () => {
  const ball = new Ball(40, 10, 10);
  it('should increase the velocity of ball', () => {
    const velocity = { x: 10, y: 10 };
    ball.move(velocity);
    expect(ball)
      .to.have.property('x')
      .equals(20);
    expect(ball)
      .to.have.property('y')
      .equals(20);
  });

  it('should return false when x is less then 920', () => {
    expect(ball.doesRightCollide()).to.equals(false);
  });

  it('should return true when x is equals to 920', () => {
    const ball = new Ball(40, 920, 10);
    expect(ball.doesRightCollide()).to.equals(true);
  });
});

describe('Velocity', () => {
  it('should make velocity.x nagetive', () => {
    const velocity = new Velocity(10, 10);
    velocity.negateX();
    expect(velocity.x).to.equals(-10);
  });
  it('should make velocity.y nagetive', () => {
    const velocity = new Velocity(10, 10);
    velocity.negateY();
    expect(velocity.y).to.equals(-10);
  });
  it('should make velocity.x nagetive to positive value', () => {
    const velocity = new Velocity(-10, -10);
    velocity.negateX();
    expect(velocity.x).to.equals(10);
  });
  it('should make velocity.y nagetive to positive value', () => {
    const velocity = new Velocity(-10, -10);
    velocity.negateY();
    expect(velocity.y).to.equals(10);
  });
});
<file_sep>/README.md
# Bricks

JavaScript version of Brick and Ball Game.

Play Now : https://cksharma11.github.io/bricks/
