Skip to content

Commit 673568d

Browse files
committed
add finished breakout game
1 parent 9b26258 commit 673568d

File tree

4 files changed

+201
-3
lines changed

4 files changed

+201
-3
lines changed

75-breakout game/index.html

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
<!-- References: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API -->
2+
<!-- https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame -->
3+
14
<!DOCTYPE html>
25
<html lang="en">
36
<head>
@@ -18,7 +21,7 @@ <h2>How To Play:</h2>
1821
<p>If you miss the ball, your score and the blocks will reset.</p>
1922
<button id="close-btn" class="btn">Close</button>
2023
</div>
21-
<canvas id="canvas" width="800" height="600"></canvas>
24+
<canvas id="canvas"></canvas>
2225
<script src="script.js"></script>
2326
</body>
2427
</html>

75-breakout game/script.js

+195
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,202 @@ const closeButton = document.getElementById("close-btn");
33
const rules = document.getElementById("rules");
44
const canvas = document.getElementById("canvas");
55
const ctx = canvas.getContext("2d");
6+
const color = getComputedStyle(document.documentElement).getPropertyValue(
7+
"--background-color"
8+
);
9+
const secondaryColor = getComputedStyle(
10+
document.documentElement
11+
).getPropertyValue("--background-secondary-color");
12+
let score = 0;
13+
const brickRowCount = 9;
14+
const brickColumnCount = 5;
15+
16+
// Reference: https://stackoverflow.com/questions/34772957/how-to-make-canvas-responsive
17+
// https://stackoverflow.com/questions/39771732/drawing-to-responsive-canvas-that-is-100-width-and-height
18+
const heightRatio = 0.75;
19+
canvas.height = canvas.width * heightRatio;
20+
ctx.canvas.width = 800;
21+
ctx.canvas.height = ctx.canvas.width * heightRatio;
22+
23+
// Elements
24+
const ball = {
25+
x: canvas.width / 2,
26+
y: canvas.height / 2,
27+
size: 10,
28+
speed: 4,
29+
dx: 4,
30+
dy: -4,
31+
};
32+
33+
const paddle = {
34+
x: canvas.width / 2 - 40,
35+
y: canvas.height - 20,
36+
w: 80,
37+
h: 10,
38+
speed: 8,
39+
dx: 0,
40+
};
41+
42+
const brickInfo = {
43+
w: 70,
44+
h: 20,
45+
padding: 10,
46+
offsetX: 45,
47+
offsetY: 60,
48+
visible: true,
49+
};
50+
51+
const bricks = [];
52+
for (let i = 0; i < brickRowCount; i++) {
53+
bricks[i] = [];
54+
for (let j = 0; j < brickColumnCount; j++) {
55+
const x = i * (brickInfo.w + brickInfo.padding) + brickInfo.offsetX;
56+
const y = j * (brickInfo.h + brickInfo.padding) + brickInfo.offsetY;
57+
bricks[i][j] = { x, y, ...brickInfo };
58+
}
59+
}
60+
61+
// Create Elements
62+
function drawBall() {
63+
ctx.beginPath();
64+
ctx.arc(ball.x, ball.y, ball.size, 0, Math.PI * 2);
65+
ctx.fillStyle = secondaryColor;
66+
ctx.fill();
67+
ctx.closePath();
68+
}
69+
70+
function drawPaddle() {
71+
ctx.beginPath();
72+
ctx.rect(paddle.x, paddle.y, paddle.w, paddle.h);
73+
ctx.fillStyle = color;
74+
ctx.fill();
75+
ctx.closePath();
76+
}
77+
78+
function drawScore() {
79+
ctx.font = '20px "Balsamiq Sans"';
80+
ctx.fillText(`Score: ${score}`, canvas.width - 100, 30);
81+
}
82+
83+
function drawBricks() {
84+
bricks.forEach((column) => {
85+
column.forEach((brick) => {
86+
ctx.beginPath();
87+
ctx.rect(brick.x, brick.y, brick.w, brick.h);
88+
ctx.fillStyle = brick.visible ? color : "transparent";
89+
ctx.fill();
90+
ctx.closePath();
91+
});
92+
});
93+
}
94+
95+
function draw() {
96+
// clear
97+
ctx.clearRect(0, 0, canvas.width, canvas.height);
98+
// draw
99+
drawBall();
100+
drawPaddle();
101+
drawScore();
102+
drawBricks();
103+
}
104+
105+
// Animate Elements
106+
function movePaddle() {
107+
paddle.x += paddle.dx;
108+
if (paddle.x + paddle.w > canvas.width) paddle.x = canvas.width - paddle.w;
109+
if (paddle.x < 0) paddle.x = 0;
110+
}
111+
112+
function moveBall() {
113+
ball.x += ball.dx;
114+
ball.y += ball.dy;
115+
// wall collision
116+
if (ball.x + ball.size > canvas.width || ball.x - ball.size < 0) {
117+
// right and left
118+
ball.dx *= -1;
119+
}
120+
if (ball.y + ball.size > canvas.height || ball.y - ball.size < 0) {
121+
// top and bottom
122+
ball.dy *= -1;
123+
}
124+
// paddle
125+
if (
126+
ball.x - ball.size > paddle.x &&
127+
ball.x + ball.size < paddle.x + paddle.w &&
128+
ball.y + ball.size > paddle.y
129+
) {
130+
ball.dy = -ball.speed;
131+
}
132+
// bricks
133+
bricks.forEach((column) => {
134+
column.forEach((brick) => {
135+
if (brick.visible) {
136+
if (
137+
ball.x - ball.size > brick.x && // left brick side check
138+
ball.x + ball.size < brick.x + brick.w && // right brick side check
139+
ball.y + ball.size > brick.y && // top brick side check
140+
ball.y - ball.size < brick.y + brick.h // bottom brick side check
141+
) {
142+
ball.dy *= -1;
143+
brick.visible = false;
144+
increaseScore();
145+
}
146+
}
147+
});
148+
});
149+
// game over
150+
if (ball.y + ball.size > canvas.height) {
151+
showAllBricks();
152+
score = 0;
153+
}
154+
}
155+
156+
function increaseScore() {
157+
score++;
158+
if (score % (brickRowCount * brickRowCount) === 0) {
159+
// no remainder
160+
showAllBricks();
161+
}
162+
}
163+
164+
function showAllBricks() {
165+
bricks.forEach((column) => {
166+
column.forEach((brick) => (brick.visible = true));
167+
});
168+
}
169+
170+
// Handle Key Events
171+
function keyDown(e) {
172+
if (e.key === "Right" || e.key === "ArrowRight") paddle.dx = paddle.speed;
173+
else if (e.key === "Left" || e.key === "ArrowLeft") paddle.dx = -paddle.speed;
174+
}
175+
176+
function keyUp(e) {
177+
if (
178+
e.key === "Right" ||
179+
e.key === "ArrowRight" ||
180+
e.key === "Left" ||
181+
e.key === "ArrowLeft"
182+
) {
183+
paddle.dx = 0;
184+
}
185+
}
186+
187+
// Update Canvas
188+
function update() {
189+
// update
190+
movePaddle();
191+
moveBall();
192+
// draw
193+
draw();
194+
requestAnimationFrame(update);
195+
}
6196

7197
// Event Listeners
198+
document.addEventListener("keydown", keyDown);
199+
document.addEventListener("keyup", keyUp);
8200
rulesButton.addEventListener("click", () => rules.classList.add("show"));
9201
closeButton.addEventListener("click", () => rules.classList.remove("show"));
202+
203+
// Init
204+
update();

75-breakout game/style.css

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ canvas {
4040
background-color: var(--canvas-color);
4141
display: block;
4242
border-radius: 5px;
43+
width: 800px;
44+
max-width: 96%;
4345
}
4446

4547
.btn {

78-speak number guessing game/script.js

-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ const messageElement = document.getElementById("msg");
22

33
const randomNumber = getRandomNumber();
44

5-
console.log(randomNumber);
6-
75
window.SpeechRecognition =
86
window.SpeechRecognition || window.webkitSpeechRecognition;
97
let recognition = new window.SpeechRecognition();

0 commit comments

Comments
 (0)