├── sudoCode.txt
├── .vscode
└── settings.json
├── index.html
├── main.css
└── app.js
/sudoCode.txt:
--------------------------------------------------------------------------------
1 | // ====== SUDO CODE (Game play)
2 |
3 | Steps:
4 |
5 | 1. Create canvas context
6 |
7 | 2. Create and draw ball
8 |
9 | 3. Create and draw paddle
10 |
11 | 4. Create bricks
12 |
13 | 5. Draw score
14 |
15 | 6. Add update() - Animate - requestAnimationFrame(cb)
16 |
17 | 7. Move paddle
18 |
19 | 8. Keyboard events handlers to move paddle
20 |
21 | 9. Move ball
22 |
23 | 10. Add wall bounderies
24 |
25 | 11. Increase score when brinks break
26 |
27 | 12. Lose - redraw bricks, reset score
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "yaml.customTags": [
3 | "!encrypted/pkcs1-oaep scalar",
4 | "!vault scalar",
5 | "!And",
6 | "!And sequence",
7 | "!If",
8 | "!If sequence",
9 | "!Not",
10 | "!Not sequence",
11 | "!Equals",
12 | "!Equals sequence",
13 | "!Or",
14 | "!Or sequence",
15 | "!FindInMap",
16 | "!FindInMap sequence",
17 | "!Base64",
18 | "!Join",
19 | "!Join sequence",
20 | "!Cidr",
21 | "!Ref",
22 | "!Sub",
23 | "!Sub sequence",
24 | "!GetAtt",
25 | "!GetAZs",
26 | "!ImportValue",
27 | "!ImportValue sequence",
28 | "!Select",
29 | "!Select sequence",
30 | "!Split",
31 | "!Split sequence"
32 | ]
33 | }
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Breakout Game
10 |
11 |
12 | Destroy
13 |
14 |
15 |
16 |
17 |
How to Play
18 |
19 | use your right and left keys to move the paddle to bounce the ball up and break the blocks.
20 |
21 |
If you miss the ball, your score and the blocks will reset.
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/main.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | body {
6 | background-color: #0095dd;
7 | /* background-image: url('https://apod.nasa.gov/apod/image/2108/NGC6726_6723_2panel.jpg'); */
8 | display: flex;
9 | flex-direction: column;
10 | align-items: center;
11 | justify-content: center;
12 | font-family: Arial, Helvetica, sans-serif;
13 | min-height: 100vh;
14 | margin: 0;
15 | }
16 |
17 | h1 {
18 | font-size: 45px;
19 | color: #fff;
20 | }
21 |
22 | canvas {
23 | background-color: #f0f0f0;
24 | display: block;
25 | border-radius: 5px;
26 | }
27 |
28 | .btn {
29 | cursor: pointer;
30 | border: 0;
31 | padding: 10px 20px;
32 | background: #000;
33 | color: #fff;
34 | border-radius: 5px;
35 | }
36 |
37 | .btn:focus {
38 | outline: 0;
39 | }
40 |
41 | .btn:hover {
42 | background: #222;
43 | }
44 |
45 | .btn:active {
46 | transform: scale(0.98);
47 | }
48 |
49 | .rules-btn {
50 | position: absolute;
51 | top: 30px;
52 | left: 30px;
53 | }
54 |
55 | .rules {
56 | position: absolute;
57 | top: 0;
58 | left: 0;
59 | background: #333;
60 | color: #fff;
61 | min-height: 1100vh;
62 | width: 400px;
63 | padding: 20px;
64 | line-height: 1.5;
65 | transform: translateX(-400px);
66 | transition: transform 1s ease-in-out;
67 | }
68 |
69 | .rules.show {
70 | transform: translateX(0);
71 | }
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | //* Variables
2 | const showRulesBtn = document.getElementById("rules-btn");
3 | const closeBtn = document.getElementById("close-btn");
4 | const rules = document.getElementById("rules");
5 |
6 | let score = 0;
7 |
8 | const brickRowCount = 9;
9 | const brickColumnCount = 5;
10 |
11 | //* ========== Canvas
12 | // gets canvas container
13 | const canvas = document.getElementById("canvas");
14 | // inits canvas context
15 | const ctx = canvas.getContext("2d");
16 |
17 | //* =========== Ball Props
18 | const ball = {
19 | x: canvas.width / 2,
20 | y: canvas.height / 2,
21 | size: 10,
22 | speed: 4,
23 | dx: 4,
24 | dy: -4,
25 | visible: true
26 | };
27 |
28 | //* ========== Draw ball on canvas
29 | const drawBall = () => {
30 | ctx.beginPath(); // drawing path
31 | // ctx.arc(75, 75, 50, 0, Math.PI * 2, true); // Outer circle
32 | ctx.arc(ball.x, ball.y, ball.size, 0, Math.PI * 2); //create circle (ball)
33 | ctx.fillStyle = "#0095dd"; // color to fill the circle
34 | ctx.fill(); // fills the circle
35 | ctx.closePath();
36 | };
37 |
38 | //* ========== Paddle Props
39 | const paddle = {
40 | x: canvas.width / 2 - 40,
41 | y: canvas.height - 20,
42 | w: 80,
43 | h: 10,
44 | speed: 8,
45 | dx: 0,
46 | visible: true
47 | };
48 |
49 | //* ============ Draw Paddle
50 | const drawPaddle = () => {
51 | ctx.beginPath();
52 | ctx.rect(paddle.x, paddle.y, paddle.w, paddle.h);
53 | ctx.fillStyle = "#0095dd"; // color to fill the circle
54 | ctx.fill(); // fills the circle
55 | ctx.closePath();
56 | };
57 |
58 | //* ========== Create brick Props
59 | const brinkProps = {
60 | w: 70,
61 | h: 20,
62 | padding: 10,
63 | offsetX: 45,
64 | offsetY: 60,
65 | visible: true,
66 | };
67 |
68 | //* ============ Create Bricks
69 | const bricks = [];
70 | for (let i = 0; i < brickRowCount; i++) {
71 | bricks[i] = []; // create 9 (rows) arrays inside bricks array [ [], [], ...]
72 | for (let j = 0; j < brickColumnCount; j++) {
73 | // create 5 columns
74 | // create x value; i = row iteration
75 | const x = i * (brinkProps.w + brinkProps.padding) + brinkProps.offsetX;
76 | // create y value
77 | const y = j * (brinkProps.h + brinkProps.padding) + brinkProps.offsetY;
78 | // brick array + [current iteration] + [column] = to an object
79 | bricks[i][j] = { x, y, ...brinkProps }; // array with columns and bricks inside
80 | }
81 | }
82 | console.log(bricks);
83 |
84 | const drawBricks = () => {
85 | bricks.forEach((column) => {
86 | column.forEach((brick) => {
87 | ctx.beginPath();
88 | ctx.rect(brick.x, brick.y, brick.w, brick.h);
89 | ctx.fillStyle = brick.visible ? "#0095dd" : "transparent";
90 | ctx.fill();
91 | ctx.closePath();
92 | });
93 | });
94 | };
95 |
96 | //* ========= Draw score on canvas
97 | const drawScore = () => {
98 | ctx.font = "20px Arial";
99 | ctx.fillText(`Score: ${score}`, canvas.width - 100, 30);
100 | };
101 |
102 | //* ========= Move paddle on canvas
103 | const movePaddle = () => {
104 | paddle.x += paddle.dx;
105 |
106 | // wall detection
107 | if (paddle.x + paddle.w > canvas.width) {
108 | paddle.x = canvas.width - paddle.w;
109 | }
110 |
111 | if (paddle.x < 0) {
112 | paddle.x = 0;
113 | }
114 | };
115 |
116 | //* ========= Move Ball on canvas
117 | const moveBall = () => {
118 | //take the x value and adds the dx value
119 | ball.x += ball.dx;
120 | ball.y += ball.dy;
121 |
122 | // Wall collision (X axis)
123 | // right side and left size of the X axis
124 | if (ball.x + ball.size > canvas.width || ball.x - ball.size < 0) {
125 | // make the value negative
126 | ball.dx *= -1; // multiply by negative value to make it go back
127 | }
128 |
129 | // Wall collision (Y axis)
130 | if (
131 | ball.y + ball.size > canvas.height ||
132 | ball.y - ball.size < 0
133 | ) {
134 | ball.dy *= -1;
135 | }
136 | // console.log(ball.x , ball.y)
137 |
138 | // Paddle
139 | if (
140 | ball.x - ball.size > paddle.x &&
141 | ball.x + ball.size < paddle.x + paddle.w &&
142 | ball.y + ball.size > paddle.y
143 | ) {
144 | ball.dy = -ball.speed;
145 | }
146 | };
147 |
148 |
149 | //* ========== Draw game board
150 | const drawGame = () => {
151 | ctx.clearRect(0, 0, canvas.width, canvas.height); // clear canvas
152 | drawBall();
153 | drawPaddle();
154 | drawScore();
155 | drawBricks();
156 | };
157 |
158 | //* Update canvas drawing and animation
159 | const update = () => {
160 | movePaddle();
161 | moveBall();
162 | // Draw
163 | drawGame();
164 | requestAnimationFrame(update)
165 | };
166 | update();
167 |
168 | //* ========================================= Events Listeners for
169 |
170 | // Adds event listener to the show rules
171 | showRulesBtn.addEventListener("click", () => {
172 | rules.classList.add("show");
173 | });
174 |
175 | // Adds event listener to the close button
176 | closeBtn.addEventListener("click", () => {
177 | rules.classList.remove("show");
178 | });
179 |
180 | //* ====== Keyboard Events
181 | const keyDown = (e) => {
182 | if (e.key === "Right" || e.key === "ArrowRight") {
183 | paddle.dx = paddle.speed;
184 |
185 | } else if (e.key === "Left" || e.key === "ArrowLeft") {
186 | paddle.dx =- paddle.speed;
187 | }
188 | };
189 |
190 | const keyUp = (e) => {
191 | if (
192 | e.key === "Right" ||
193 | e.key === "ArrowRight" ||
194 | e.key === "Left" ||
195 | e.key === "ArrowLeft"
196 | ) {
197 | paddle.dx = 0;
198 | }
199 | };
200 |
201 | //* ======== Keyboard event listeners
202 | document.addEventListener("keydown", keyDown);
203 | document.addEventListener("keyup", keyUp);
204 |
--------------------------------------------------------------------------------