diff --git a/src/index.html b/index.html
similarity index 100%
rename from src/index.html
rename to index.html
diff --git a/index.ts b/index.ts
new file mode 100644
index 0000000..20008d0
--- /dev/null
+++ b/index.ts
@@ -0,0 +1 @@
+import './src/Game';
\ No newline at end of file
diff --git a/src/Game.ts b/src/Game.ts
new file mode 100644
index 0000000..d83de01
--- /dev/null
+++ b/src/Game.ts
@@ -0,0 +1,188 @@
+import { BrickGrid } from './components/BrickGrid';
+import { Ball } from './components/Ball';
+import { Paddle } from './components/Paddle';
+
+
+
+class Game {
+ canvas: HTMLCanvasElement;
+ ctx: CanvasRenderingContext2D;
+ ball: Ball;
+ paddle: Paddle;
+ brickGrid: BrickGrid;
+
+
+ dx = 2;
+ dy = -2;
+ rightPressed = false;
+ leftPressed = false;
+ score = 0;
+ lives = 3;
+ brickColumnCount = 5; // TODO get rid of
+ brickRowCount = 3; // TODO get rid of
+
+ constructor(config: { canvas: HTMLCanvasElement}) {
+ this.canvas = config.canvas;
+ this.ctx = this.canvas.getContext("2d");
+ this.ball = new Ball({
+ ctx: this.ctx,
+ x: this.canvas.width / 2,
+ y: this.canvas.height - 30,
+ color: '#f95',
+ radius: 10
+ });
+ this.paddle = new Paddle({
+ ctx: this.ctx,
+ x: (this.canvas.width - 75) / 2,
+ y: this.canvas.height - 10,
+ height: 10,
+ width: 75
+ })
+
+
+ this.brickGrid = new BrickGrid({
+ ctx: this.ctx,
+ rows: this.brickRowCount,
+ cols: this.brickColumnCount,
+ brickHeight: 20,
+ brickWidth: 75
+ });
+
+ document.addEventListener("keydown", this.handleKeyDown.bind(this), false);
+ document.addEventListener("keyup", this.handleKeyUp.bind(this), false);
+ document.addEventListener("mousemove", this.handleMouseMove.bind(this), false);
+
+ this.listenStart();
+ }
+
+ start() {
+ this.brickGrid.generateBricks();
+ this.draw();
+ }
+
+ listenStart() {
+ this.handleStartClick = this.handleStartClick.bind(this);
+ this.handleStartPress = this.handleStartPress.bind(this);
+
+ this.canvas.addEventListener("click", this.handleStartClick)
+ document.addEventListener('keyup', this.handleStartPress)
+ }
+ stopListenStart() {
+ this.canvas.removeEventListener('click', this.handleStartClick)
+ document.removeEventListener('keyup', this.handleStartPress)
+ }
+
+ handleStartClick() {
+ this.stopListenStart();
+ this.start();
+ }
+
+ handleStartPress(e: KeyboardEvent) {
+ if (e.key === ' ' || e.code === 'Space') {
+ this.stopListenStart();
+ this.start();
+ }
+ }
+
+
+ handleMouseMove(e) {
+ var relativeX = e.clientX - this.canvas.offsetLeft;
+ if (relativeX > 0 && relativeX < this.canvas.width) {
+ this.paddle.x = relativeX - this.paddle.width / 2;
+ }
+ }
+
+ handleKeyDown(e) {
+ if (e.key == "Right" || e.key == "ArrowRight") {
+ this.rightPressed = true;
+ } else if (e.key == "Left" || e.key == "ArrowLeft") {
+ this.leftPressed = true;
+ }
+ }
+
+ handleKeyUp(e) {
+ if (e.key == "Right" || e.key == "ArrowRight") {
+ this.rightPressed = false;
+ } else if (e.key == "Left" || e.key == "ArrowLeft") {
+ this.leftPressed = false;
+ }
+ }
+
+
+ collisionDetection() {
+ if (this.brickGrid.checkCollision(this.ball)) {
+ this.dy = -this.dy;
+ this.score++;
+ }
+}
+
+ checkScore() {
+ if (this.score == this.brickRowCount * this.brickColumnCount) {
+ console.log("YOU WIN, CONGRATULATIONS!");
+ document.location.reload();
+ // clearInterval(interval);
+ }
+}
+ drawScore() {
+ this.ctx.font = "16px Arial";
+ this.ctx.fillStyle = "#0095dd";
+ this.ctx.fillText("Score: " + this.score, 8, 20);
+}
+ drawLives() {
+ this.ctx.font = "16px Arial";
+ this.ctx.fillStyle = "#0095DD";
+ this.ctx.fillText("Lives: " + this.lives, this.canvas.width - 65, 20);
+}
+
+ draw() {
+ this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+ this.brickGrid.draw();
+ this.ball.draw();
+ this.paddle.draw();
+ this.collisionDetection();
+ this.checkScore();
+ this.drawScore();
+ this.drawLives();
+
+ if (this.ball.x + this.dx > this.canvas.width - this.ball.radius || this.ball.x + this.dx < this.ball.radius) {
+ this.dx = -this.dx;
+ }
+ if (this.ball.y + this.dy < this.ball.radius) {
+ this.dy = -this.dy;
+ } else if (this.ball.y + this.dy > this.canvas.height - this.ball.radius) {
+ if (this.ball.x > this.paddle.x && this.ball.x < this.paddle.x + this.paddle.width) {
+ this.ball.y -= this.paddle.height;
+ if (this.ball.y) {
+ this.dy = -this.dy;
+ }
+ } else {
+ this.lives--;
+ if (!this.lives) {
+ // alert("GAME OVER");
+ document.location.reload();
+ // clearInterval(interval); // Needed for Chrome to end game
+ } else {
+ this.ball.x = this.canvas.width / 2;
+ this.ball.y = this.canvas.height - 30;
+ this.dx = 2;
+ this.dy = -2;
+ this.paddle.x = (this.canvas.width - this.paddle.width) / 2;
+ }
+ }
+ }
+
+ if (this.rightPressed && this.paddle.x < this.canvas.width - this.paddle.width) {
+ this.paddle.x += 7;
+ } else if (this.leftPressed && this.paddle.x > 0) {
+ this.paddle.x -= 7;
+ }
+
+ this.ball.x += this.dx;
+ this.ball.y += this.dy;
+ requestAnimationFrame(this.draw.bind(this));
+}
+}
+
+const game = new Game({
+ canvas: document.getElementById("myCanvas") as HTMLCanvasElement
+});
\ No newline at end of file
diff --git a/src/game/components/Ball.ts b/src/components/Ball.ts
similarity index 100%
rename from src/game/components/Ball.ts
rename to src/components/Ball.ts
diff --git a/src/game/components/Brick.ts b/src/components/Brick.ts
similarity index 95%
rename from src/game/components/Brick.ts
rename to src/components/Brick.ts
index b41d439..a263a65 100644
--- a/src/game/components/Brick.ts
+++ b/src/components/Brick.ts
@@ -1,4 +1,4 @@
-export class Brick {
+export class Brick{
x: BrickConfig['x'];
y: BrickConfig['y'];
#ctx: BrickConfig['ctx']
@@ -41,6 +41,10 @@ export class Brick {
this.#ctx.closePath();
}
}
+
+ destroy() {
+ this.status = false
+ }
}
interface BrickConfig {
diff --git a/src/components/BrickGrid.ts b/src/components/BrickGrid.ts
new file mode 100644
index 0000000..06d6669
--- /dev/null
+++ b/src/components/BrickGrid.ts
@@ -0,0 +1,75 @@
+import { Ball } from './Ball';
+import { Brick } from './Brick';
+
+export class BrickGrid {
+ #ctx: BrickGridConfig['ctx']
+ cols: BrickGridConfig['cols']
+ rows: BrickGridConfig['rows']
+ brickWidth: BrickGridConfig['brickWidth']
+ brickHeight: BrickGridConfig['brickHeight']
+
+ bricks: Brick[][] = []
+
+
+ constructor(config: BrickGridConfig) {
+ this.cols = config.cols;
+ this.rows = config.rows;
+
+ this.#ctx = config.ctx;
+ this.brickWidth = config.brickWidth;
+ this.brickHeight = config.brickHeight;
+ }
+
+ generateBricks() {
+ for (var c = 0; c < this.cols; c++) {
+ this.bricks[c] = [];
+ for (var r = 0; r < this.rows; r++) {
+ this.bricks[c][r] = new Brick({
+ x: 0,
+ y: 0,
+ column: c,
+ row: r,
+ ctx: this.#ctx,
+ width: this.brickWidth,
+ height: this.brickHeight,
+ padding: 10,
+ offsetLeft: 30,
+ offsetTop: 30
+ });
+ }
+ }
+ }
+
+ draw() {
+ for (const brick of this.bricks.flat()) {
+ brick.draw();
+ }
+ }
+
+
+ checkCollision(ball: Ball): boolean {
+ for (const brick of this.bricks.flat()) {
+ if (brick.status === true) {
+ if (
+ ball.x > brick.x &&
+ ball.x < brick.x + this.brickWidth &&
+ ball.y > brick.y &&
+ ball.y < brick.y + this.brickHeight
+ ) {
+
+ brick.destroy();
+ return true
+ }
+ }
+ }
+ return false;
+ }
+}
+
+interface BrickGridConfig {
+ ctx: CanvasRenderingContext2D,
+ rows: number,
+ cols: number,
+ brickWidth: number,
+ brickHeight: number,
+}
\ No newline at end of file
diff --git a/src/game/components/Paddle.ts b/src/components/Paddle.ts
similarity index 100%
rename from src/game/components/Paddle.ts
rename to src/components/Paddle.ts
diff --git a/src/game/Game.ts b/src/game/Game.ts
deleted file mode 100644
index 72d3c76..0000000
--- a/src/game/Game.ts
+++ /dev/null
@@ -1,177 +0,0 @@
-import { Ball } from './components/Ball';
-import { Brick } from './components/Brick';
-import { Paddle } from './components/Paddle';
-
-// class Game {
-// constructor() {}
-// }
-
-
-const canvas = document.getElementById("myCanvas") as HTMLCanvasElement;
-const ctx = canvas.getContext("2d");
-
-
-const ball = new Ball({
- ctx: ctx,
- x: canvas.width / 2,
- y: canvas.height - 30,
- color: '#ff95DD',
- radius: 10
-})
-
-const paddle = new Paddle({
- ctx: ctx,
- x: (canvas.width - 75) / 2,
- y: canvas.height - 10,
- height: 10,
- width: 75
-});
-
-
-var dx = 2;
-var dy = -2;
-var rightPressed = false;
-var leftPressed = false;
-var brickRowCount = 3;
-var brickColumnCount = 5;
-var brickWidth = 75;
-var brickHeight = 20;
-var score = 0;
-var lives = 3;
-
-var bricks = [];
-for (var c = 0; c < brickColumnCount; c++) {
- bricks[c] = [];
- for (var r = 0; r < brickRowCount; r++) {
- bricks[c][r] = new Brick({
- x: 0,
- y: 0,
- column: c,
- row: r,
- ctx: ctx,
- width: 75,
- height: 30,
- padding: 10,
- offsetLeft: 30,
- offsetTop: 30
- });
- }
-}
-
-document.addEventListener("keydown", keyDownHandler, false);
-document.addEventListener("keyup", keyUpHandler, false);
-document.addEventListener("mousemove", mouseMoveHandler, false);
-
-function mouseMoveHandler(e) {
- var relativeX = e.clientX - canvas.offsetLeft;
- if (relativeX > 0 && relativeX < canvas.width) {
- paddle.x = relativeX - paddle.width / 2;
- }
-}
-
-function keyDownHandler(e) {
- if (e.key == "Right" || e.key == "ArrowRight") {
- rightPressed = true;
- } else if (e.key == "Left" || e.key == "ArrowLeft") {
- leftPressed = true;
- }
-}
-
-function keyUpHandler(e) {
- if (e.key == "Right" || e.key == "ArrowRight") {
- rightPressed = false;
- } else if (e.key == "Left" || e.key == "ArrowLeft") {
- leftPressed = false;
- }
-}
-
-function collisionDetection() {
- for (var c = 0; c < brickColumnCount; c++) {
- for (var r = 0; r < brickRowCount; r++) {
- var b = bricks[c][r];
- if (b.status == 1) {
- if (
- ball.x > b.x &&
- ball.x < b.x + brickWidth &&
- ball.y > b.y &&
- ball.y < b.y + brickHeight
- ) {
- dy = -dy;
- b.status = 0;
- score++;
- if (score == brickRowCount * brickColumnCount) {
- alert("YOU WIN, CONGRATULATIONS!");
- document.location.reload();
- // clearInterval(interval);
- }
- }
- }
- }
- }
-}
-function drawScore() {
- ctx.font = "16px Arial";
- ctx.fillStyle = "#0095dd";
- ctx.fillText("Score: " + score, 8, 20);
-}
-function drawLives() {
- ctx.font = "16px Arial";
- ctx.fillStyle = "#0095DD";
- ctx.fillText("Lives: " + lives, canvas.width - 65, 20);
-}
-function drawBricks() {
- for (var c = 0; c < brickColumnCount; c++) {
- for (var r = 0; r < brickRowCount; r++) {
- bricks[c][r].draw();
- }
- }
-}
-
-function draw() {
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- drawBricks();
- ball.draw();
- paddle.draw();
- collisionDetection();
- drawScore();
- drawLives();
-
- if (ball.x + dx > canvas.width - ball.radius || ball.x + dx < ball.radius) {
- dx = -dx;
- }
- if (ball.y + dy < ball.radius) {
- dy = -dy;
- } else if (ball.y + dy > canvas.height - ball.radius) {
- if (ball.x > paddle.x && ball.x < paddle.x + paddle.width) {
- ball.y -= paddle.height;
- if (ball.y) {
- dy = -dy;
- }
- } else {
- lives--;
- if (!lives) {
- // alert("GAME OVER");
- document.location.reload();
- // clearInterval(interval); // Needed for Chrome to end game
- } else {
- ball.x = canvas.width / 2;
- ball.y = canvas.height - 30;
- dx = 2;
- dy = -2;
- paddle.x = (canvas.width - paddle.width) / 2;
- }
- }
- }
-
- if (rightPressed && paddle.x < canvas.width - paddle.width) {
- paddle.x += 7;
- } else if (leftPressed && paddle.x > 0) {
- paddle.x -= 7;
- }
-
- ball.x += dx;
- ball.y += dy;
- requestAnimationFrame(draw);
-}
-
-draw();
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
deleted file mode 100644
index 3326f59..0000000
--- a/src/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-import './game/Game';
\ No newline at end of file
diff --git a/src/style.css b/src/style.css
deleted file mode 100644
index 38317a7..0000000
--- a/src/style.css
+++ /dev/null
@@ -1,3 +0,0 @@
-h1, h2 {
- font-family: Lato;
-}
\ No newline at end of file
diff --git a/webpack.config.ts b/webpack.config.ts
index e169f56..c73833a 100644
--- a/webpack.config.ts
+++ b/webpack.config.ts
@@ -3,11 +3,11 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
- entry: './src/index.ts',
+ entry: './index.ts',
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
- template: 'src/index.html'
+ template: './index.html'
}),
],
module: {