{"manifest":{"name":"Canvas Breakout Clone","version":"1.0.0","description":"Classic Breakout arcade game with paddle physics, brick collision, and scoring. Intermediate HTML5 Canvas tutorial.","tags":["gamedev","canvas","game","breakout","intermediate"],"standard":"agentskills.io","standard_version":"1.0","content_checksum":"608051ae9355222c64bfbd977de214beb352bc348c0cddba5b8decf2b449a601","bundle_checksum":"49d752b37d81da007d10b8e721a7def63047fc8ad51ca7dccff6ccf6d8907740","metadata":{"runtime":{"language":"html","entrypoint":"breakout.html"},"compatible_agents":["claude-code","cursor","copilot"]},"files":[{"path":"breakout.html","name":"breakout.html","mime_type":"text/html","checksum":"3d302b769d3b578ec799f5c1d521f064906e40e868de2e38d96abf2584984ad4"},{"path":"README.md","name":"README.md","mime_type":"text/markdown","checksum":"2f31c9dc55e85865b88668d61d74ceaa7ed06a120c810700e4ee8d2986430f1a"}]},"files":{"SKILL.md":"# Canvas Breakout Clone\n\n> **Difficulty:** Intermediate | **Runtime:** HTML5 Canvas | **Output:** Playable game\n\nTeach an AI agent to build a classic Breakout arcade game with paddle controls, ball physics, brick collision detection, scoring, and game-over handling.\n\n## What You'll Build\n\nA self-contained HTML file implementing a fully playable Breakout clone:\n- Rows of colored bricks at the top of the screen\n- A paddle controlled by mouse movement\n- A ball that bounces off walls, paddle, and bricks\n- Score tracking and game-over state\n- Restart capability\n\n## Core Concepts\n\n### 1. Game State\n\n```javascript\n{\n  ball: { x, y, dx, dy, radius },\n  paddle: { x, y, width, height },\n  bricks: [{ x, y, width, height, color, alive }],\n  score: number,\n  lives: number,\n  running: boolean\n}\n```\n\n### 2. Game Loop Architecture\n\n```\nInput → Update Physics → Detect Collisions → Render → Repeat\n```\n\nEach frame at 60fps:\n1. Read mouse position for paddle\n2. Move ball by `(dx, dy)`\n3. Check wall bounces (reflect dx or dy)\n4. Check paddle collision (reflect dy, adjust dx by hit position)\n5. Check brick collisions (destroy brick, reflect ball, add score)\n6. Check ball-below-paddle (lose life)\n7. Clear and redraw everything\n\n### 3. Brick Layout\n\nBricks arranged in a grid:\n- **Columns:** 10 across, with gaps\n- **Rows:** 5 deep, each row a different color\n- **Colors:** Red, Orange, Yellow, Green, Cyan (top to bottom)\n\n### 4. Collision Detection\n\nFor brick collisions, use AABB (Axis-Aligned Bounding Box):\n```\nball overlaps brick if:\n  ball.x + radius > brick.x AND\n  ball.x - radius < brick.x + brick.width AND\n  ball.y + radius > brick.y AND\n  ball.y - radius < brick.y + brick.height\n```\n\n## Instructions\n\n1. Set up a fixed-size canvas (800x600)\n2. Create the brick grid with colors\n3. Implement paddle that follows mouse X position\n4. Add ball with initial diagonal velocity\n5. Handle wall bounces, paddle bounces, and brick collisions\n6. Track score (10 points per brick) and display it\n7. Detect game over (ball falls below paddle)\n8. Add click-to-restart functionality\n\n## Parameters\n\n| Parameter | Default | Description |\n|-----------|---------|-------------|\n| `BRICK_ROWS` | 5 | Number of brick rows |\n| `BRICK_COLS` | 10 | Number of brick columns |\n| `BALL_SPEED` | 5 | Initial ball speed |\n| `PADDLE_WIDTH` | 100 | Paddle width in pixels |","breakout.html":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<title>Canvas Breakout Clone</title>\n<style>\n  * { margin: 0; padding: 0; }\n  body { background: #111; display: flex; justify-content: center; align-items: center; height: 100vh; }\n  canvas { border: 2px solid #333; cursor: none; }\n</style>\n</head>\n<body>\n<canvas id=\"c\" width=\"800\" height=\"600\"></canvas>\n<script>\nconst canvas = document.getElementById('c');\nconst ctx = canvas.getContext('2d');\nconst W = 800, H = 600;\n\nconst BRICK_ROWS = 5, BRICK_COLS = 10;\nconst BRICK_W = 70, BRICK_H = 20, BRICK_PAD = 6, BRICK_TOP = 50;\nconst BRICK_LEFT = (W - (BRICK_COLS * (BRICK_W + BRICK_PAD) - BRICK_PAD)) / 2;\nconst ROW_COLORS = ['#ef4444', '#f97316', '#eab308', '#22c55e', '#06b6d4'];\n\nconst PADDLE_W = 100, PADDLE_H = 12;\nconst BALL_R = 6, BALL_SPEED = 5;\n\nlet ball, paddle, bricks, score, lives, running, gameOver;\n\nfunction init() {\n  ball = { x: W / 2, y: H - 60, dx: BALL_SPEED * 0.7, dy: -BALL_SPEED * 0.7 };\n  paddle = { x: W / 2 - PADDLE_W / 2, y: H - 30 };\n  bricks = [];\n  for (let r = 0; r < BRICK_ROWS; r++) {\n    for (let c = 0; c < BRICK_COLS; c++) {\n      bricks.push({\n        x: BRICK_LEFT + c * (BRICK_W + BRICK_PAD),\n        y: BRICK_TOP + r * (BRICK_H + BRICK_PAD),\n        w: BRICK_W, h: BRICK_H,\n        color: ROW_COLORS[r],\n        alive: true,\n      });\n    }\n  }\n  score = 0;\n  lives = 3;\n  running = true;\n  gameOver = false;\n}\n\ncanvas.addEventListener('mousemove', (e) => {\n  const rect = canvas.getBoundingClientRect();\n  paddle.x = Math.max(0, Math.min(W - PADDLE_W, e.clientX - rect.left - PADDLE_W / 2));\n});\n\ncanvas.addEventListener('click', () => {\n  if (gameOver) { init(); }\n});\n\nfunction update() {\n  if (!running) return;\n  ball.x += ball.dx;\n  ball.y += ball.dy;\n\n  // Wall bounces\n  if (ball.x - BALL_R < 0 || ball.x + BALL_R > W) ball.dx = -ball.dx;\n  if (ball.y - BALL_R < 0) ball.dy = -ball.dy;\n\n  // Paddle collision\n  if (\n    ball.dy > 0 &&\n    ball.y + BALL_R >= paddle.y &&\n    ball.y + BALL_R <= paddle.y + PADDLE_H + 4 &&\n    ball.x >= paddle.x &&\n    ball.x <= paddle.x + PADDLE_W\n  ) {\n    ball.dy = -Math.abs(ball.dy);\n    const hit = (ball.x - (paddle.x + PADDLE_W / 2)) / (PADDLE_W / 2);\n    ball.dx = hit * BALL_SPEED;\n  }\n\n  // Brick collision\n  for (const b of bricks) {\n    if (!b.alive) continue;\n    if (\n      ball.x + BALL_R > b.x && ball.x - BALL_R < b.x + b.w &&\n      ball.y + BALL_R > b.y && ball.y - BALL_R < b.y + b.h\n    ) {\n      b.alive = false;\n      ball.dy = -ball.dy;\n      score += 10;\n      break;\n    }\n  }\n\n  // Ball below paddle\n  if (ball.y > H + 20) {\n    lives--;\n    if (lives <= 0) {\n      running = false;\n      gameOver = true;\n    } else {\n      ball.x = W / 2;\n      ball.y = H - 60;\n      ball.dx = BALL_SPEED * 0.7;\n      ball.dy = -BALL_SPEED * 0.7;\n    }\n  }\n\n  // Win condition\n  if (bricks.every((b) => !b.alive)) {\n    running = false;\n    gameOver = true;\n  }\n}\n\nfunction draw() {\n  ctx.fillStyle = '#111';\n  ctx.fillRect(0, 0, W, H);\n\n  // Bricks\n  for (const b of bricks) {\n    if (!b.alive) continue;\n    ctx.fillStyle = b.color;\n    ctx.fillRect(b.x, b.y, b.w, b.h);\n    ctx.strokeStyle = 'rgba(255,255,255,0.15)';\n    ctx.strokeRect(b.x, b.y, b.w, b.h);\n  }\n\n  // Paddle\n  ctx.fillStyle = '#a855f7';\n  ctx.fillRect(paddle.x, paddle.y, PADDLE_W, PADDLE_H);\n\n  // Ball\n  ctx.fillStyle = '#fff';\n  ctx.beginPath();\n  ctx.arc(ball.x, ball.y, BALL_R, 0, Math.PI * 2);\n  ctx.fill();\n\n  // Score + Lives\n  ctx.fillStyle = '#888';\n  ctx.font = '14px monospace';\n  ctx.fillText(`Score: ${score}  Lives: ${lives}`, 10, 20);\n\n  if (gameOver) {\n    ctx.fillStyle = 'rgba(0,0,0,0.7)';\n    ctx.fillRect(0, 0, W, H);\n    ctx.fillStyle = '#fff';\n    ctx.font = 'bold 32px sans-serif';\n    ctx.textAlign = 'center';\n    const msg = bricks.every((b) => !b.alive) ? 'YOU WIN!' : 'GAME OVER';\n    ctx.fillText(msg, W / 2, H / 2 - 10);\n    ctx.font = '16px sans-serif';\n    ctx.fillText(`Score: ${score} — Click to restart`, W / 2, H / 2 + 25);\n    ctx.textAlign = 'left';\n  }\n}\n\nfunction loop() {\n  update();\n  draw();\n  requestAnimationFrame(loop);\n}\n\ninit();\nloop();\n</script>\n</body>\n</html>","README.md":"# Canvas Breakout Clone\n\nA classic Breakout arcade game built with HTML5 Canvas.\n\n## Playing\n\nOpen `breakout.html` in any modern browser. Move your mouse to control the paddle. Click to restart after game over.\n\n## Rules\n\n- Break all bricks to win\n- Each brick is worth 10 points\n- You have 3 lives\n- Ball speeds up based on where it hits the paddle"}}