-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added a basic game built in VanillaJavascript with Parcel bundeler
- Loading branch information
Showing
14 changed files
with
371 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"responsive-preview": { | ||
"Mobile": [ | ||
320, | ||
675 | ||
], | ||
"Tablet": [ | ||
1024, | ||
765 | ||
], | ||
"Desktop": [ | ||
1400, | ||
800 | ||
], | ||
"Desktop HD": [ | ||
1920, | ||
1080 | ||
] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# BrickBreaker | ||
Created with CodeSandbox works in Parcel | ||
|
||
 |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>JavaScript Game</title> | ||
<style> | ||
#gameScreen { | ||
border: 1px solid black; | ||
} | ||
img { | ||
width: 10px; | ||
height: 8px; | ||
display: none; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<img id="ballImg" src="./assets/images/ball.png" /> | ||
<img id="brickImg" src="./assets/images/brick.png" alt="brick" /> | ||
<canvas id="gameScreen" width="800px" height="600px"></canvas> | ||
<script src="src/index.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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] | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
}; | ||
} | ||
} |