diff --git a/BrickBreakerGame/.codesandbox/workspace.json b/BrickBreakerGame/.codesandbox/workspace.json
new file mode 100755
index 0000000..e7d06a2
--- /dev/null
+++ b/BrickBreakerGame/.codesandbox/workspace.json
@@ -0,0 +1,20 @@
+{
+ "responsive-preview": {
+ "Mobile": [
+ 320,
+ 675
+ ],
+ "Tablet": [
+ 1024,
+ 765
+ ],
+ "Desktop": [
+ 1400,
+ 800
+ ],
+ "Desktop HD": [
+ 1920,
+ 1080
+ ]
+ }
+}
\ No newline at end of file
diff --git a/BrickBreakerGame/README.md b/BrickBreakerGame/README.md
new file mode 100755
index 0000000..62cc16a
--- /dev/null
+++ b/BrickBreakerGame/README.md
@@ -0,0 +1,4 @@
+# BrickBreaker
+Created with CodeSandbox works in Parcel
+
+
diff --git a/BrickBreakerGame/assets/images/ball.png b/BrickBreakerGame/assets/images/ball.png
new file mode 100644
index 0000000..6c00647
Binary files /dev/null and b/BrickBreakerGame/assets/images/ball.png differ
diff --git a/BrickBreakerGame/assets/images/brick.png b/BrickBreakerGame/assets/images/brick.png
new file mode 100644
index 0000000..a5d6cee
Binary files /dev/null and b/BrickBreakerGame/assets/images/brick.png differ
diff --git a/BrickBreakerGame/index.html b/BrickBreakerGame/index.html
new file mode 100755
index 0000000..e58239f
--- /dev/null
+++ b/BrickBreakerGame/index.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+ JavaScript Game
+
+
+
+
+
+
+
+
+
diff --git a/BrickBreakerGame/package.json b/BrickBreakerGame/package.json
new file mode 100755
index 0000000..3292777
--- /dev/null
+++ b/BrickBreakerGame/package.json
@@ -0,0 +1,33 @@
+{
+ "name": "brickbreaker",
+ "version": "1.0.0",
+ "description": "JavaScript example starter project",
+ "main": "index.html",
+ "scripts": {
+ "start": "parcel index.html --open",
+ "build": "parcel build index.html"
+ },
+ "dependencies": {
+ "parcel-bundler": "^1.6.1"
+ },
+ "devDependencies": {
+ "@babel/core": "7.2.0"
+ },
+ "resolutions": {
+ "@babel/preset-env": "7.13.8"
+ },
+ "keywords": [
+ "javascript",
+ "starter"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/AbdulAziz0682/BrickBreaker.git"
+ },
+ "author": "Abdul Aziz Khoso",
+ "license": "ISC",
+ "bugs": {
+ "url": "https://github.com/AbdulAziz0682/BrickBreaker/issues"
+ },
+ "homepage": "https://github.com/AbdulAziz0682/BrickBreaker#readme"
+}
diff --git a/BrickBreakerGame/src/ball.js b/BrickBreakerGame/src/ball.js
new file mode 100755
index 0000000..7d6fa4d
--- /dev/null
+++ b/BrickBreakerGame/src/ball.js
@@ -0,0 +1,41 @@
+import { detectCollision } from "./collisionDetection";
+export default class Ball {
+ constructor(game) {
+ this.image = document.getElementById("ballImg");
+ this.size = 16;
+ this.gameHeight = game.gameHeight;
+ this.gameWidth = game.gameWidth;
+ this.game = game;
+ this.reset();
+ }
+ reset(){
+ this.pos = { x: 10, y: 500 };
+ this.speed = { x: 4, y: -4 };
+ console.log('Ball pos: '+this.pos.x+","+this.pos.y);
+ }
+ draw(ctx) {
+ ctx.drawImage(this.image, this.pos.x, this.pos.y, this.size, this.size);
+ }
+ update() {
+ this.pos.x += this.speed.x;
+ this.pos.y += this.speed.y;
+ //left and right walls
+ if (this.pos.x + this.size > this.gameWidth || this.pos.x < 0) {
+ this.speed.x = -this.speed.x;
+ }
+ //top
+ if (this.pos.y < 0) {
+ this.speed.y = -this.speed.y;
+ }
+ //bottom
+ if(this.pos.y + this.size >= this.gameHeight){
+ this.game.lives--;
+ this.reset();
+ }
+ //collision with paddle
+ if (detectCollision(this, this.game.paddle)) {
+ this.speed.y = -this.speed.y;
+ this.pos.y = this.game.paddle.pos.y - this.size;
+ }
+ }
+}
diff --git a/BrickBreakerGame/src/brick.js b/BrickBreakerGame/src/brick.js
new file mode 100755
index 0000000..b2bb553
--- /dev/null
+++ b/BrickBreakerGame/src/brick.js
@@ -0,0 +1,20 @@
+import { detectCollision } from "./collisionDetection";
+export default class Brick {
+ constructor(game, position) {
+ this.image = document.getElementById("brickImg");
+ this.pos = position;
+ this.game = game;
+ this.width = 80;
+ this.height = 25;
+ this.markForDeletion = false;
+ }
+ update() {
+ if (detectCollision(this.game.ball, this)) {
+ this.game.ball.speed.y = -this.game.ball.speed.y;
+ this.markForDeletion = true;
+ }
+ }
+ draw(ctx) {
+ ctx.drawImage(this.image, this.pos.x, this.pos.y, this.width, this.height);
+ }
+}
diff --git a/BrickBreakerGame/src/collisionDetection.js b/BrickBreakerGame/src/collisionDetection.js
new file mode 100755
index 0000000..9829101
--- /dev/null
+++ b/BrickBreakerGame/src/collisionDetection.js
@@ -0,0 +1,20 @@
+export function detectCollision(ball, gameObject) {
+ let bottomOfBall = ball.pos.y + ball.size;
+ let topOfBall = ball.pos.y;
+
+ let topOfObject = gameObject.pos.y;
+ let leftSideOfObject = gameObject.pos.x;
+ let rightSideoOfObject = gameObject.pos.x + gameObject.width;
+ let bottomOfObject = gameObject.pos.y + gameObject.height;
+
+ if (
+ bottomOfBall >= topOfObject &&
+ topOfBall <= bottomOfObject &&
+ ball.pos.x >= leftSideOfObject &&
+ ball.pos.x <= rightSideoOfObject
+ ) {
+ return true;
+ } else {
+ return false;
+ }
+}
diff --git a/BrickBreakerGame/src/game.js b/BrickBreakerGame/src/game.js
new file mode 100755
index 0000000..5397c70
--- /dev/null
+++ b/BrickBreakerGame/src/game.js
@@ -0,0 +1,94 @@
+import Paddle from "./paddle";
+import InputHandler from "./input";
+import Ball from "./ball";
+import { buildLevel, level1, level2 } from "./levels";
+
+const GAME_STATE = {
+ PAUSED: 0,
+ RUNNING: 1,
+ MENU: 2,
+ GAMEOVER: 3,
+ NEWLEVEL: 4
+};
+
+export default class Game {
+ constructor(gameWidth, gameHeight) {
+ this.gameWidth = gameWidth;
+ this.gameHeight = gameHeight;
+ this.gameState = GAME_STATE.MENU;
+ this.paddle = new Paddle(this);
+ this.ball = new Ball(this);
+ this.lives = 3;
+ this.bricks = [];
+ new InputHandler(this.paddle, this);
+ this.gameObjects = [];
+
+ this.levels = [level1, level2];
+ this.currentLevel = 0;
+ }
+ start() {
+ if(this.gameState !== GAME_STATE.MENU && this.gameState !== GAME_STATE.NEWLEVEL) return;
+ this.bricks = buildLevel(this, this.levels[this.currentLevel]);
+ this.ball.reset();
+ this.gameObjects = [this.paddle, this.ball];
+ this.gameState = GAME_STATE.RUNNING;
+ }
+ update(ctx) {
+ if(this.lives == 0) this.gameState = GAME_STATE.GAMEOVER;
+ if ((this.gameState == GAME_STATE.PAUSED) || (this.gameState == GAME_STATE.MENU) || (this.gameState == GAME_STATE.GAMEOVER)) return;
+ if(this.bricks.length === 0){
+ this.currentLevel++;
+ this.gameState = GAME_STATE.NEWLEVEL;
+ this.start();
+
+ }
+ [...this.gameObjects, ...this.bricks].forEach((obj) => {
+ obj.update(ctx);
+ });
+ this.bricks = this.bricks.filter((obj) => !obj.markForDeletion);
+ }
+ draw(ctx) {
+ [...this.gameObjects, ...this.bricks].forEach((obj) => {
+ obj.draw(ctx);
+ });
+ if(this.gameState == GAME_STATE.PAUSED){
+ ctx.rect(0, 0, this.gameWidth, this.gameHeight);
+ ctx.fillStyle = "rgb(0, 0, 5)";
+ ctx.fill();
+
+ ctx.font = "30px Arial";
+ ctx.fillStyle = "white";
+ ctx.textAlign = 'center';
+ ctx.fillText("Paused", this.gameWidth/2, this.gameHeight/2);
+ }
+ if(this.gameState == GAME_STATE.MENU){
+ ctx.rect(0, 0, this.gameWidth, this.gameHeight);
+ ctx.fillStyle = "rgb(0, 0, 5)";
+ ctx.fill();
+
+ ctx.font = "30px Arial";
+ ctx.fillStyle = "white";
+ ctx.textAlign = 'center';
+ ctx.fillText("Press Space to Start", this.gameWidth/2, this.gameHeight/2);
+ }
+ if(this.gameState == GAME_STATE.GAMEOVER){
+ ctx.rect(0, 0, this.gameWidth, this.gameHeight);
+ ctx.fillStyle = "rgb(0, 0, 5)";
+ ctx.fill();
+
+ ctx.font = "30px Arial";
+ ctx.fillStyle = "white";
+ ctx.textAlign = 'center';
+ ctx.fillText("GAME OVER", this.gameWidth/2, this.gameHeight/2);
+ }
+ }
+ togglePause() {
+
+ if (this.gameState == GAME_STATE.PAUSED) {
+ console.log('Pause func')
+ this.gameState = GAME_STATE.RUNNING;
+ } else {
+ this.gameState = GAME_STATE.PAUSED;
+ }
+ }
+}
diff --git a/BrickBreakerGame/src/index.js b/BrickBreakerGame/src/index.js
new file mode 100755
index 0000000..7a6add0
--- /dev/null
+++ b/BrickBreakerGame/src/index.js
@@ -0,0 +1,17 @@
+import Game from "./game";
+
+const GAME_WIDTH = 800;
+const GAME_HEIGHT = 600;
+let canvas = document.getElementById("gameScreen");
+let ctx = canvas.getContext("2d");
+
+let game = new Game(GAME_WIDTH, GAME_HEIGHT);
+
+function gameloop(timestamp) {
+ ctx.clearRect(0, 0, GAME_WIDTH, GAME_HEIGHT);
+ game.update();
+ game.draw(ctx);
+ requestAnimationFrame(gameloop);
+}
+
+gameloop();
diff --git a/BrickBreakerGame/src/input.js b/BrickBreakerGame/src/input.js
new file mode 100755
index 0000000..7f4f898
--- /dev/null
+++ b/BrickBreakerGame/src/input.js
@@ -0,0 +1,34 @@
+export default class InputHandler {
+ constructor(paddle, game) {
+ document.addEventListener("keydown", (e) => {
+ switch (e.keyCode) {
+ case 37:
+ paddle.moveLeft();
+ break;
+ case 39:
+ paddle.moveRight();
+ break;
+ case 27:
+ game.togglePause();
+ break;
+ case 32:
+ game.start();
+ break;
+ default:
+ break;
+ }
+ });
+ document.addEventListener("keyup", (e) => {
+ switch (e.keyCode) {
+ case 37:
+ if (paddle.speed < 0) paddle.stop();
+ break;
+ case 39:
+ if (paddle.speed > 0) paddle.stop();
+ break;
+ default:
+ break;
+ }
+ });
+ }
+}
diff --git a/BrickBreakerGame/src/levels.js b/BrickBreakerGame/src/levels.js
new file mode 100755
index 0000000..4efb92b
--- /dev/null
+++ b/BrickBreakerGame/src/levels.js
@@ -0,0 +1,31 @@
+import Brick from "./brick";
+
+export function buildLevel(game, level) {
+ let bricks = [];
+ level.forEach((row, rowIndex) => {
+ row.forEach((element, index) => {
+ if (element === 1) {
+ let position = {
+ x: index * 80,
+ y: 100 + 25 * rowIndex
+ };
+ bricks.push(new Brick(game, position));
+ }
+ });
+ });
+ return bricks;
+}
+
+export const level1 = [
+ [0, 1, 0, 1, 1, 0, 0, 0, 1, 1],
+ [1, 1, 1, 1, 0, 0, 0, 1, 1, 1],
+ [0, 1, 0, 1, 0, 1, 1, 0, 0, 0],
+ [0, 1, 1, 1, 0, 0, 1, 1, 0, 0]
+];
+
+export const level2 = [
+ [0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
+ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
+ [1, 1, 0, 1, 0, 1, 1, 0, 0, 1],
+ [0, 1, 1, 1, 1, 0, 1, 1, 0, 1]
+];
diff --git a/BrickBreakerGame/src/paddle.js b/BrickBreakerGame/src/paddle.js
new file mode 100755
index 0000000..4288552
--- /dev/null
+++ b/BrickBreakerGame/src/paddle.js
@@ -0,0 +1,32 @@
+export default class Paddle {
+ constructor(game) {
+ this.width = 150;
+ this.height = 25;
+ this.maxSpeed = 5;
+ this.speed = 0;
+ this.pos = {
+ x: game.gameWidth / 2 - this.width / 2,
+ y: game.gameHeight - this.height - 10
+ };
+
+ this.draw = (ctx) => {
+ ctx.fillStyle = "#0ff";
+ ctx.fillRect(this.pos.x, this.pos.y, this.width, this.height);
+ };
+ this.moveLeft = () => {
+ this.speed += -this.maxSpeed;
+ };
+ this.moveRight = () => {
+ this.speed += this.maxSpeed;
+ };
+ this.stop = () => {
+ this.speed = 0;
+ };
+ this.update = () => {
+ this.pos.x += this.speed;
+ if (this.pos.x < 0) this.pos.x = 0;
+ if (this.pos.x + this.width > game.gameWidth)
+ this.pos.x = game.gameWidth - this.width;
+ };
+ }
+}