From 4cb5204fa552ed29f96296d5dec08d156cb8e1f5 Mon Sep 17 00:00:00 2001 From: Calamariclam <76179328+Calamariclam@users.noreply.github.com> Date: Wed, 17 Jun 2026 22:04:54 -0700 Subject: [PATCH 1/8] Update block-blast.js separated ball-paddle bouncing into a separate function for easier editing --- scripts/block-blast.js | 50 ++++++++++++++---------------------------- 1 file changed, 17 insertions(+), 33 deletions(-) diff --git a/scripts/block-blast.js b/scripts/block-blast.js index bfba9a6..7ad6279 100644 --- a/scripts/block-blast.js +++ b/scripts/block-blast.js @@ -381,6 +381,20 @@ return dist <= colDist } + function hitBall(thePaddle, ball){ + // Calculate bounce angle based on relative hit position on the paddle + const relativeY = (ball.y - (thePaddle.y + thePaddle.h / 2)) / (thePaddle.h / 2) + const bounceAngle = relativeY * (Math.PI / 3) // Max angle of +/- 60 degrees + + // Set velocity and reset state + ball.vx = Math.cos(bounceAngle) * BALL_SPEED + ball.vy = Math.sin(bounceAngle) * BALL_SPEED + ball.x = thePaddle.x + thePaddle.w + ball.r + 0.1 // Reposition ball to prevent sticking + ball.isDisabled = false + ball.blocksHitCount = ball.type === 'piercing' ? 0 : Infinity // Reset block hit count + ball.ballsHitCount = ball.type === 'blocking' ? 0 : Infinity // Reset ball hit count + } + // Helper to draw a rounded rectangle function drawRoundRect(x, y, w, h, r, fillStyle) { ctx.fillStyle = fillStyle @@ -1203,17 +1217,7 @@ if(diamondPaddle.bonus > 0) { // Diamond Paddle collision if (rectCircleColliding(diamondPaddle, ball)) { - // Calculate bounce angle based on relative hit position on the diamondPaddle - const relativeY = (ball.y - (diamondPaddle.y + diamondPaddle.h / 2)) / (diamondPaddle.h / 2) - const bounceAngle = relativeY * (Math.PI / 3) // Max angle of +/- 60 degrees - - // Set velocity and reset state - ball.vx = Math.cos(bounceAngle) * BALL_SPEED - ball.vy = Math.sin(bounceAngle) * BALL_SPEED - ball.x = diamondPaddle.x + diamondPaddle.w + ball.r + 0.1 // Reposition ball to prevent sticking - ball.isDisabled = false - ball.blocksHitCount = ball.type === 'piercing' ? 0 : Infinity // Reset block hit count - ball.ballsHitCount = ball.type === 'blocking' ? 0 : Infinity // Reset ball hit count + hitBall(diamondPaddle, ball) if (ball.type === 'projectile') { // Projectile hits diamondPaddle: diamondPaddle damage @@ -1256,17 +1260,7 @@ } // Paddle collision else if (rectCircleColliding(paddle, ball)) { - // Calculate bounce angle based on relative hit position on the paddle - const relativeY = (ball.y - (paddle.y + paddle.h / 2)) / (paddle.h / 2) - const bounceAngle = relativeY * (Math.PI / 3) // Max angle of +/- 60 degrees - - // Set velocity and reset state - ball.vx = Math.cos(bounceAngle) * BALL_SPEED - ball.vy = Math.sin(bounceAngle) * BALL_SPEED - ball.x = paddle.x + paddle.w + ball.r + 0.1 // Reposition ball to prevent sticking - ball.isDisabled = false - ball.blocksHitCount = ball.type === 'piercing' ? 0 : Infinity // Reset block hit count - ball.ballsHitCount = ball.type === 'blocking' ? 0 : Infinity // Reset ball hit count + hitBall(paddle, ball) if (ball.type === 'projectile') { // Projectile hits paddle: paddle damage and self-destruction @@ -1310,17 +1304,7 @@ if (rectCircleColliding(pinkPaddle, ball)) { //pink paddle ignores certain balls if(ball.type !== 'projectile') { - // Calculate bounce angle based on relative hit position on the pink paddle - const relativeY = (ball.y - (pinkPaddle.y + pinkPaddle.h / 2)) / (pinkPaddle.h / 2) - const bounceAngle = relativeY * (Math.PI / 3) // Max angle of +/- 60 degrees - - // Set velocity and reset state - ball.vx = Math.cos(bounceAngle) * BALL_SPEED - ball.vy = Math.sin(bounceAngle) * BALL_SPEED - ball.x = pinkPaddle.x + pinkPaddle.w + ball.r + 0.1 // Reposition ball to prevent sticking - ball.isDisabled = false - ball.blocksHitCount = ball.type === 'piercing' ? 0 : Infinity // Reset block hit count - ball.ballsHitCount = ball.type === 'blocking' ? 0 : Infinity // Reset ball hit count + hitBall(pinkPaddle, ball) if (ball.type === 'pink') { let greaterPaddle = Math.max(paddle.h, diamondPaddle.h) From aa7c40f68393baf3a262bc8f093c3e16059385e1 Mon Sep 17 00:00:00 2001 From: Calamariclam <76179328+Calamariclam@users.noreply.github.com> Date: Wed, 17 Jun 2026 22:11:34 -0700 Subject: [PATCH 2/8] Update block-blast.js changed ball-paddle bouncing function to bounce balls back at their original speed instead of the universal ball default speed --- scripts/block-blast.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/block-blast.js b/scripts/block-blast.js index 7ad6279..c90475a 100644 --- a/scripts/block-blast.js +++ b/scripts/block-blast.js @@ -44,7 +44,7 @@ const PINK_SPEED = 240 const BLOCKING_RADIUS_MAX = 32 const BLOCKING_RADIUS_MIN = 8 - const BLOCKING_SPEED = 120 + const BLOCKING_SPEED = 240 /* --- COLORS --- */ const COLORS = { @@ -387,8 +387,8 @@ const bounceAngle = relativeY * (Math.PI / 3) // Max angle of +/- 60 degrees // Set velocity and reset state - ball.vx = Math.cos(bounceAngle) * BALL_SPEED - ball.vy = Math.sin(bounceAngle) * BALL_SPEED + ball.vx = Math.cos(bounceAngle) * ball.speed + ball.vy = Math.sin(bounceAngle) * ball.speed ball.x = thePaddle.x + thePaddle.w + ball.r + 0.1 // Reposition ball to prevent sticking ball.isDisabled = false ball.blocksHitCount = ball.type === 'piercing' ? 0 : Infinity // Reset block hit count @@ -704,6 +704,7 @@ this.y + this.h / 2, BALL_RADIUS, 'piercing', + BALL_SPEED, true, ) piercingBall.vx = BALL_SPEED * Math.cos(piercingAngle) @@ -790,6 +791,7 @@ this.y + this.h / 2, DIAMOND_RADIUS, 'diamond', + DIAMOND_SPEED, ) diamond.vx = DIAMOND_SPEED * Math.cos(angle) diamond.vy = DIAMOND_SPEED * Math.sin(angle) @@ -818,6 +820,7 @@ BLOCKING_RADIUS_MIN, 'blocking', true, + BLOCKING_SPEED ) blockingBall.vx = BLOCKING_SPEED * Math.cos(blockingAngle) blockingBall.vy = BLOCKING_SPEED * Math.sin(blockingAngle) @@ -953,7 +956,7 @@ generateBlocks() // BALL OBJECT - function Ball(x, y, radius, type, isDisabled = false) { + function Ball(x, y, radius, type, speed = BALL_SPEED, isDisabled = false) { this.x = x this.y = y this.r = radius @@ -964,6 +967,7 @@ this.isDestroyed = false // Corresponds to `dead` in original this.vx = 0 this.vy = 0 + this.speed = speed this.spawnTime = performance.now() + Math.random() * 1000 // For bomb pulse timing this.update = function (dt) { //the ball updates function From d4c51d7021af26fcafafe2c46811be393a434a7d Mon Sep 17 00:00:00 2001 From: Calamariclam <76179328+Calamariclam@users.noreply.github.com> Date: Wed, 17 Jun 2026 22:38:27 -0700 Subject: [PATCH 3/8] Update block-blast.js blocking ball adjustment --- scripts/block-blast.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/block-blast.js b/scripts/block-blast.js index c90475a..973f0d9 100644 --- a/scripts/block-blast.js +++ b/scripts/block-blast.js @@ -389,10 +389,12 @@ // Set velocity and reset state ball.vx = Math.cos(bounceAngle) * ball.speed ball.vy = Math.sin(bounceAngle) * ball.speed - ball.x = thePaddle.x + thePaddle.w + ball.r + 0.1 // Reposition ball to prevent sticking ball.isDisabled = false ball.blocksHitCount = ball.type === 'piercing' ? 0 : Infinity // Reset block hit count ball.ballsHitCount = ball.type === 'blocking' ? 0 : Infinity // Reset ball hit count + if(ball.type === 'blocking') + ball.r = BLOCKING_RADIUS_MAX + ball.x = thePaddle.x + thePaddle.w + ball.r + 0.1 // Reposition ball to prevent sticking } // Helper to draw a rounded rectangle From 89382698d735b4a2533c44f136f7d32f2376ce74 Mon Sep 17 00:00:00 2001 From: Calamariclam <76179328+Calamariclam@users.noreply.github.com> Date: Wed, 17 Jun 2026 22:44:49 -0700 Subject: [PATCH 4/8] Update block-blast.js decrease blocking ball max size --- scripts/block-blast.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/block-blast.js b/scripts/block-blast.js index 973f0d9..0798c8d 100644 --- a/scripts/block-blast.js +++ b/scripts/block-blast.js @@ -42,7 +42,7 @@ const DIAMOND_DAMAGE = 20 // Amount of additional paddle height given by diamonds const PINK_RADIUS = 8 const PINK_SPEED = 240 - const BLOCKING_RADIUS_MAX = 32 + const BLOCKING_RADIUS_MAX = 24 const BLOCKING_RADIUS_MIN = 8 const BLOCKING_SPEED = 240 From d4b3cdaada04baca282e814bf60321c1cb2e9a44 Mon Sep 17 00:00:00 2001 From: Calamariclam <76179328+Calamariclam@users.noreply.github.com> Date: Wed, 17 Jun 2026 22:49:26 -0700 Subject: [PATCH 5/8] Update block-blast.js adjust you died text again --- scripts/block-blast.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/block-blast.js b/scripts/block-blast.js index 0798c8d..4240955 100644 --- a/scripts/block-blast.js +++ b/scripts/block-blast.js @@ -1545,7 +1545,7 @@ ctx.fillText( 'YOU DIED', VIRTUAL_WIDTH / 2, - VIRTUAL_HEIGHT / 2 - 42, + VIRTUAL_HEIGHT / 2 - 32, ) ctx.fillStyle = COLORS.WHITE @@ -1553,13 +1553,13 @@ ctx.fillText( `You got a score of ${currentScore}!`, VIRTUAL_WIDTH / 2, - VIRTUAL_HEIGHT / 2 + 9, + VIRTUAL_HEIGHT / 2 + 19, ) ctx.font = '18px system-ui, sans-serif' ctx.fillText( 'Click Restart to play again.', VIRTUAL_WIDTH / 2, - VIRTUAL_HEIGHT / 2 + 45, + VIRTUAL_HEIGHT / 2 + 55, ) } From 9dafcc76528a40aa2d208fbe48c26ea660e599c8 Mon Sep 17 00:00:00 2001 From: Calamariclam <76179328+Calamariclam@users.noreply.github.com> Date: Tue, 23 Jun 2026 20:05:49 -0700 Subject: [PATCH 6/8] Update block-blast.js adds button function and rewires the menuButton to use it. also adds the hotkey function. --- scripts/block-blast.js | 107 ++++++++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 33 deletions(-) diff --git a/scripts/block-blast.js b/scripts/block-blast.js index 4240955..e492a2d 100644 --- a/scripts/block-blast.js +++ b/scripts/block-blast.js @@ -97,8 +97,59 @@ PINK_BLOCK_WEIGHT + BLOCKING_BLOCK_WEIGHT + /* --- BUTTON --- */ + function button(x, y, w, h, text, operation){ + this.x = x + this.y = y + this.w = w + this.h = h + this.text = text + this.operation = operation + this.isHovering = false + + this.update() = { + // Check if the mouse is inside the button's boundaries + this.isHovering = + this.x >= this.x && + this.x <= this.x + this.w && + this.y >= this.y && + this.y <= this.y + this.h + + // Start the game if the button is clicked + if (this.isHovering && isMouseClicked) { + this.operation() + } + } + this.display() = { + // Button + const btnColor = this.isHovering ? COLORS.WHITE : COLORS.WHITE_D + drawRoundRect( + this.x, + this.y, + this.w, + this.h, + 10, + btnColor, + ) + + // Button text + ctx.fillStyle = COLORS.BLACK + ctx.font = '28px system-ui, sans-serif' + ctx.textAlign = 'center' + ctx.textBaseline = 'middle' + ctx.fillText( + this.text, + this.x + this.w / 2, + this.y + this.h / 2, + ) + } + } + /* --- GAME STATE VARIABLES --- */ - const menuButton = { x: 500, y: 350, w: 200, h: 60, isHovering: false } + // const menuButton = { x: 500, y: 350, w: 200, h: 60, isHovering: false } + let menuButton = new button(500, 350, 200, 60, 'Start Game', reset) + let resumeButton = new button(500 - 110, 350, 200, 60, 'Cancel', resume) + let resetButton = new button(500 + 110, 350, 200, 60, 'Restart', reset) let currentScene = GAME_SCENE_NAME let livesLostCount = 0 let currentScore = 0 @@ -132,6 +183,13 @@ diamondPaddle.bonus = INITIAL_DIAMOND_BONUS projectileTimer = 0 } + function reset(){ + startGame() + currentScene = 'game' + } + function resume(){ + currentScene = 'game' + } function die() { //Clear all balls and reset paddle and serving ball, but maintain blocks paddle.y = (VIRTUAL_HEIGHT - PADDLE_HEIGHT_INITIAL) / 2 @@ -160,6 +218,12 @@ lastTime = performance.now() } + function hotkey(key, effect){ + if(releasedKeys[key]){ + effect() + } + } + // Function to generate angles that are not too horizontal function generateAngle(minAngle, direction) { let dir = Math.random() < 0.5 ? 1 : -1 @@ -251,10 +315,12 @@ }) const keys = {} + const releasedKeys = {} window.addEventListener('keydown', (e) => { keys[e.key.toLowerCase()] = true // Use toLowerCase for consistent key checking }) window.addEventListener('keyup', (e) => { + releasedKeys[e.key.toLowerCase()] = true //just gotta add a thing that sets everything to false at the end keys[e.key.toLowerCase()] = false }) @@ -1150,7 +1216,7 @@ drawGame() break } - + releasedKeys = {} isMouseClicked = false requestAnimationFrame(gameLoop) } @@ -1429,6 +1495,7 @@ if (livesLostCount >= MAX_LIVES) { isGameOver = true } + } //stop when paused, not when game over function updateText(dt) { @@ -1445,17 +1512,10 @@ function updateMenu() { // Check if the mouse is inside the button's boundaries - menuButton.isHovering = - mousePosition.x >= menuButton.x && - mousePosition.x <= menuButton.x + menuButton.w && - mousePosition.y >= menuButton.y && - mousePosition.y <= menuButton.y + menuButton.h - - // Start the game if the button is clicked - if (menuButton.isHovering && isMouseClicked) { - startGame() - currentScene = 'game' - } + menuButton.update() + } + function updateReset() { + } /* --- DISPLAY FUNCTIONS --- */ @@ -1598,26 +1658,7 @@ // Button - const btnColor = menuButton.isHovering ? COLORS.WHITE : COLORS.WHITE_D - drawRoundRect( - menuButton.x, - menuButton.y, - menuButton.w, - menuButton.h, - 10, - btnColor, - ) - - // Button text - ctx.fillStyle = COLORS.BLACK - ctx.font = '28px system-ui, sans-serif' - ctx.textAlign = 'center' - ctx.textBaseline = 'middle' - ctx.fillText( - 'Start Game', - menuButton.x + menuButton.w / 2, - menuButton.y + menuButton.h / 2, - ) + menuButton.display() } function pauseGame() { From f55fa8515695c9696c2f6991bb6f54aa3045b40c Mon Sep 17 00:00:00 2001 From: Calamariclam <76179328+Calamariclam@users.noreply.github.com> Date: Tue, 23 Jun 2026 20:22:44 -0700 Subject: [PATCH 7/8] Update block-blast.js adds hotkey support for buttons --- scripts/block-blast.js | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/scripts/block-blast.js b/scripts/block-blast.js index e492a2d..2b3e39f 100644 --- a/scripts/block-blast.js +++ b/scripts/block-blast.js @@ -98,7 +98,7 @@ BLOCKING_BLOCK_WEIGHT /* --- BUTTON --- */ - function button(x, y, w, h, text, operation){ + function button(x, y, w, h, text, operation, hotKey){ this.x = x this.y = y this.w = w @@ -106,6 +106,7 @@ this.text = text this.operation = operation this.isHovering = false + this.key = hotKey this.update() = { // Check if the mouse is inside the button's boundaries @@ -114,11 +115,17 @@ this.x <= this.x + this.w && this.y >= this.y && this.y <= this.y + this.h + if(this.key !== undefined && keys[this.key]){ + this.isHovering = true + } // Start the game if the button is clicked if (this.isHovering && isMouseClicked) { this.operation() } + if(this.key !== undefined){ + hotKey(this.key, this.operation) + } } this.display() = { // Button @@ -147,9 +154,9 @@ /* --- GAME STATE VARIABLES --- */ // const menuButton = { x: 500, y: 350, w: 200, h: 60, isHovering: false } - let menuButton = new button(500, 350, 200, 60, 'Start Game', reset) - let resumeButton = new button(500 - 110, 350, 200, 60, 'Cancel', resume) - let resetButton = new button(500 + 110, 350, 200, 60, 'Restart', reset) + let menuButton = new button(500, 350, 200, 60, 'Start Game', reset, 32) //32 is the key code for space + let resumeButton = new button(500 - 110, 350, 200, 60, 'Cancel', resume, 32) + let resetButton = new button(500 + 110, 350, 200, 60, 'Restart', reset, 13) //13 is the key code for enter let currentScene = GAME_SCENE_NAME let livesLostCount = 0 let currentScore = 0 @@ -183,6 +190,9 @@ diamondPaddle.bonus = INITIAL_DIAMOND_BONUS projectileTimer = 0 } + function considerReset() { + currentScene = 'maybeReset' + } function reset(){ startGame() currentScene = 'game' @@ -1215,6 +1225,8 @@ } drawGame() break + case 'maybeReset': + break } releasedKeys = {} isMouseClicked = false @@ -1654,7 +1666,7 @@ 275, ) ctx.textAlign = 'left' - ctx.fillText('Last updated: June 17, 2026', 20, VIRTUAL_HEIGHT - 30) + ctx.fillText('Last updated: June 23, 2026', 20, VIRTUAL_HEIGHT - 30) // Button From fcb9edfe031b479e3817e838b040af8cf0eaa951 Mon Sep 17 00:00:00 2001 From: Calamariclam <76179328+Calamariclam@users.noreply.github.com> Date: Tue, 23 Jun 2026 20:41:05 -0700 Subject: [PATCH 8/8] Update block-blast.js added space hotkey for pausing and R hotkey for restarting the game. Also added a restart confirmation screen for the R key. These work separately from the standard pause and reset buttons outside of the canvas. They restart confirmation screen does not apply to the external restart button. --- scripts/block-blast.js | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/scripts/block-blast.js b/scripts/block-blast.js index 2b3e39f..763e0ba 100644 --- a/scripts/block-blast.js +++ b/scripts/block-blast.js @@ -1219,13 +1219,21 @@ case 'game': if (!isPaused && !isGameOver) { updateGame(dt) + hotkey('r', considerReset) } if (!isPaused) { updateText(dt) } + if(!isGameOver){ + hotkey(32, togglePause) + } else{ + hotkey('r', reset) + } drawGame() break case 'maybeReset': + updateReset() + drawReset() break } releasedKeys = {} @@ -1527,7 +1535,8 @@ menuButton.update() } function updateReset() { - + resumeButton.update() + resetButton.update() } /* --- DISPLAY FUNCTIONS --- */ @@ -1629,7 +1638,7 @@ ) ctx.font = '18px system-ui, sans-serif' ctx.fillText( - 'Click Restart to play again.', + 'Click Restart or press R to play again.', VIRTUAL_WIDTH / 2, VIRTUAL_HEIGHT / 2 + 55, ) @@ -1673,6 +1682,22 @@ menuButton.display() } + function drawReset() { + // Background + ctx.fillStyle = COLORS.BLACK + ctx.fillRect(0, 0, VIRTUAL_WIDTH, VIRTUAL_HEIGHT) + + // Title + ctx.fillStyle = COLORS.WHITE_D + ctx.font = '60px system-ui, sans-serif' + ctx.textAlign = 'center' + ctx.fillText('Confirm Reset?', VIRTUAL_WIDTH / 2, 200) + + // Button + resumeButton.display() + resetButton.display() + } + function pauseGame() { isPaused = true }