View Raw Turn JSON
{
"assistant": {
"text": "Implemented checkBrickCollision() function with AABB (Axis-Aligned Bounding Box) collision detection. When ball hits brick: brick status set to 0 (destroyed), ball bounces (dy reversed), score increases by 10 points, UI updates. Only processes one brick collision per frame for performance. Ball now destroys bricks on contact and score system works.",
"type": "message"
},
"context": {
"artifacts": [
{
"content": "// Arkanoid Game - PrincipleSkinner Method (Ralph + GAIT)\n// Turn 1: Canvas foundation and game initialization\n// Turn 2: Paddle object with rendering\n// Turn 3: Paddle keyboard controls\n// Turn 4: Ball object with physics\n// Turn 5: Ball-paddle collision detection\n// Turn 6: Brick grid system\n// Turn 7: Ball-brick collision detection\n\n// Canvas setup\nconst canvas = document.getElementById('gameCanvas');\nconst ctx = canvas.getContext('2d');\n\n// Game state\nconst game = {\n score: 0,\n lives: 3,\n running: false,\n won: false,\n lost: false\n};\n\n// Paddle object\nconst paddle = {\n width: 100,\n height: 15,\n x: canvas.width / 2 - 50,\n y: canvas.height - 40,\n speed: 7,\n dx: 0\n};\n\n// Ball object\nconst ball = {\n radius: 8,\n x: canvas.width / 2,\n y: canvas.height / 2,\n dx: 4,\n dy: -4,\n speed: 4\n};\n\n// Brick configuration\nconst brickConfig = {\n rows: 5,\n cols: 10,\n width: 70,\n height: 20,\n padding: 10,\n offsetTop: 60,\n offsetLeft: 35\n};\n\n// Brick colors by row\nconst brickColors = ['#ff0000', '#ff7700', '#ffff00', '#00ff00', '#0077ff'];\n\n// Create brick grid\nconst bricks = [];\nfunction createBricks() {\n for (let row = 0; row < brickConfig.rows; row++) {\n bricks[row] = [];\n for (let col = 0; col < brickConfig.cols; col++) {\n bricks[row][col] = {\n x: col * (brickConfig.width + brickConfig.padding) + brickConfig.offsetLeft,\n y: row * (brickConfig.height + brickConfig.padding) + brickConfig.offsetTop,\n status: 1, // 1 = visible, 0 = destroyed\n color: brickColors[row]\n };\n }\n }\n}\n\n// Draw paddle\nfunction drawPaddle() {\n ctx.fillStyle = '#00ff00';\n ctx.fillRect(paddle.x, paddle.y, paddle.width, paddle.height);\n\n // Add glow effect\n ctx.shadowBlur = 10;\n ctx.shadowColor = '#00ff00';\n ctx.fillRect(paddle.x, paddle.y, paddle.width, paddle.height);\n ctx.shadowBlur = 0;\n}\n\n// Draw ball\nfunction drawBall() {\n ctx.beginPath();\n ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);\n ctx.fillStyle = '#00ffff';\n ctx.fill();\n\n // Add glow effect\n ctx.shadowBlur = 15;\n ctx.shadowColor = '#00ffff';\n ctx.fill();\n ctx.shadowBlur = 0;\n ctx.closePath();\n}\n\n// Draw bricks\nfunction drawBricks() {\n for (let row = 0; row < brickConfig.rows; row++) {\n for (let col = 0; col < brickConfig.cols; col++) {\n const brick = bricks[row][col];\n if (brick.status === 1) {\n ctx.fillStyle = brick.color;\n ctx.fillRect(brick.x, brick.y, brickConfig.width, brickConfig.height);\n\n // Add border\n ctx.strokeStyle = '#ffffff';\n ctx.lineWidth = 2;\n ctx.strokeRect(brick.x, brick.y, brickConfig.width, brickConfig.height);\n }\n }\n }\n}\n\n// Update UI\nfunction updateUI() {\n document.getElementById('score').textContent = game.score;\n document.getElementById('lives').textContent = game.lives;\n}\n\n// Update paddle position\nfunction updatePaddle() {\n paddle.x += paddle.dx;\n\n // Keep paddle within bounds\n if (paddle.x < 0) {\n paddle.x = 0;\n }\n if (paddle.x + paddle.width > canvas.width) {\n paddle.x = canvas.width - paddle.width;\n }\n}\n\n// Check ball-paddle collision\nfunction checkPaddleCollision() {\n // Ball is at paddle height\n if (ball.y + ball.radius >= paddle.y &&\n ball.y - ball.radius <= paddle.y + paddle.height) {\n // Ball is within paddle width\n if (ball.x >= paddle.x && ball.x <= paddle.x + paddle.width) {\n // Reverse ball direction\n ball.dy = -Math.abs(ball.dy);\n\n // Add spin based on where ball hits paddle\n const hitPos = (ball.x - paddle.x) / paddle.width; // 0 to 1\n ball.dx = (hitPos - 0.5) * 8; // -4 to 4 range for spin effect\n }\n }\n}\n\n// Check ball-brick collisions\nfunction checkBrickCollision() {\n for (let row = 0; row < brickConfig.rows; row++) {\n for (let col = 0; col < brickConfig.cols; col++) {\n const brick = bricks[row][col];\n if (brick.status === 1) {\n // Check if ball overlaps with brick\n if (ball.x + ball.radius > brick.x &&\n ball.x - ball.radius < brick.x + brickConfig.width &&\n ball.y + ball.radius > brick.y &&\n ball.y - ball.radius < brick.y + brickConfig.height) {\n\n // Destroy brick\n brick.status = 0;\n\n // Bounce ball\n ball.dy = -ball.dy;\n\n // Increase score\n game.score += 10;\n updateUI();\n\n return; // Only one brick per frame\n }\n }\n }\n }\n}\n\n// Update ball position and handle wall collisions\nfunction updateBall() {\n ball.x += ball.dx;\n ball.y += ball.dy;\n\n // Wall collisions (left and right)\n if (ball.x + ball.radius > canvas.width || ball.x - ball.radius < 0) {\n ball.dx = -ball.dx;\n }\n\n // Ceiling collision\n if (ball.y - ball.radius < 0) {\n ball.dy = -ball.dy;\n }\n\n // Check collisions\n checkPaddleCollision();\n checkBrickCollision();\n\n // Ball falls below paddle (lose life - will implement later)\n if (ball.y + ball.radius > canvas.height) {\n // For now, just bounce back\n ball.dy = -ball.dy;\n }\n}\n\n// Clear canvas\nfunction clearCanvas() {\n ctx.fillStyle = '#000000';\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n}\n\n// Render game\nfunction render() {\n clearCanvas();\n drawBricks();\n drawPaddle();\n drawBall();\n}\n\n// Game loop\nfunction gameLoop() {\n updatePaddle();\n updateBall();\n render();\n requestAnimationFrame(gameLoop);\n}\n\n// Keyboard controls\nfunction keyDown(e) {\n if (e.key === 'ArrowLeft' || e.key === 'a') {\n paddle.dx = -paddle.speed;\n } else if (e.key === 'ArrowRight' || e.key === 'd') {\n paddle.dx = paddle.speed;\n }\n}\n\nfunction keyUp(e) {\n if (e.key === 'ArrowLeft' || e.key === 'a' || e.key === 'ArrowRight' || e.key === 'd') {\n paddle.dx = 0;\n }\n}\n\n// Initialize game\nfunction init() {\n console.log('Arkanoid initialized - Canvas: ' + canvas.width + 'x' + canvas.height);\n createBricks();\n updateUI();\n render();\n\n // Add event listeners\n document.addEventListener('keydown', keyDown);\n document.addEventListener('keyup', keyUp);\n\n // Start game loop\n gameLoop();\n}\n\n// Start game on load\nwindow.addEventListener('load', init);",
"path": "game.js"
}
],
"pinned_context": {
"branch": "principalskinner-arkanoid",
"items": [],
"memory_id": "086e39ec4fb04bd965bcc97353b8c325dcc80d406e6b5b840ae8db97796c6775",
"pinned_items": 0,
"schema": "gait.context.v0"
}
},
"created_at": "2026-01-09T09:32:20",
"model": {
"provider": "vscode-copilot"
},
"schema": "gait.turn.v0",
"tokens": {
"by_role": {},
"estimated": true,
"input_total": 10,
"output_total": 73
},
"tools": {},
"user": {
"text": "Turn 7: Add ball-brick collision detection",
"type": "message"
},
"visibility": "private"
}