├── 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 | --------------------------------------------------------------------------------