以下が実装例です。JavaScriptのみで実装しています。 ``` <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Emoji Block Breaker</title> <style> canvas { border: 1px solid black; } </style> </head> <body> <canvas id="myCanvas"></canvas> <script> // canvas const canvas = document.getElementById("myCanvas"); const ctx = canvas.getContext("2d"); const WIDTH = canvas.width; const HEIGHT = canvas.height; // ball const BALL_RADIUS = 10; let ballX = WIDTH / 2; let ballY = HEIGHT - BALL_RADIUS - 30; let ballSpeedX = 5; let ballSpeedY = -5; // paddle const PADDLE_WIDTH = 100; const PADDLE_HEIGHT = 10; let paddleX = (WIDTH - PADDLE_WIDTH) / 2; const PADDLE_Y = HEIGHT - PADDLE_HEIGHT - 10; const PADDLE_SPEED = 10; // bricks const BRICK_WIDTH = 50; const BRICK_HEIGHT = 20; const BRICK_MARGIN = 5; const BRICK_ROWS = 5; const BRICK_COLS = 10; let bricks = []; for(let row=0; row<BRICK_ROWS; row++) { bricks[row] = []; for(let col=0; col<BRICK_COLS; col++) { bricks[row][col] = { x: col*(BRICK_WIDTH+BRICK_MARGIN)+BRICK_MARGIN, y: row*(BRICK_HEIGHT+BRICK_MARGIN)+BRICK_MARGIN, status: 1, emoji: '🧱' }; } } // score let score = 0; // event listener document.addEventListener("keydown", keyDownHandler, false); document.addEventListener("keyup", keyUpHandler, false); let rightPressed = false; let leftPressed = false; function keyDownHandler(e) { if(e.key == "Right" || e.key == "ArrowRight") { rightPressed = true; } else if(e.key == "Left" || e.key == "ArrowLeft") { leftPressed = true; } } function keyUpHandler(e) { if(e.key == "Right" || e.key == "ArrowRight") { rightPressed = false; } else if(e.key == "Left" || e.key == "ArrowLeft") { leftPressed = false; } } // collision detection function collisionDetection() { for(let row=0; row<BRICK_ROWS; row++) { for(let col=0; col<BRICK_COLS; col++) { let b = bricks[row][col]; if(b.status == 1) { if(ballX > b.x && ballX < b.x+BRICK_WIDTH && ballY > b.y && ballY < b.y+BRICK_HEIGHT) { ballSpeedY = -ballSpeedY; b.status = 0; score++; } } } } } // draw function drawBall() { ctx.beginPath(); ctx.arc(ballX, ballY, BALL_RADIUS, 0, Math.PI*2); ctx.fillStyle = "#0095DD"; ctx.fill(); ctx.closePath(); } function drawPaddle() { ctx.beginPath(); ctx.rect(paddleX, PADDLE_Y, PADDLE_WIDTH, PADDLE_HEIGHT); ctx.fillStyle = "#0095DD"; ctx.fill(); ctx.closePath(); } function drawBricks() { for(let row=0; row<BRICK_ROWS; row++) { for(let col=0; col<BRICK_COLS; col++) { if(bricks[row][col].status == 1) { ctx.font = "20px Arial"; ctx.fillText(bricks[row][col].emoji, bricks[row][col].x, bricks[row][col].y+BRICK_HEIGHT); } } } } function drawScore() { ctx.font = "16px Arial"; ctx.fillStyle = "#0095DD"; ctx.fillText("Score: "+score, 8, 20); } function draw() { ctx.clearRect(0, 0, WIDTH, HEIGHT); drawBall(); drawPaddle(); drawBricks(); drawScore(); collisionDetection(); // ball movement ballX += ballSpeedX; ballY += ballSpeedY; // bounce off left and right walls if(ballX + ballSpeedX > WIDTH - BALL_RADIUS || ballX + ballSpeedX < BALL_RADIUS) { ballSpeedX = -ballSpeedX; } // bounce off top wall if(ballY + ballSpeedY < BALL_RADIUS) { ballSpeedY = -ballSpeedY; } else if(ballY + ballSpeedY > HEIGHT - BALL_RADIUS) { // hit the paddle if(ballX > paddleX && ballX < paddleX + PADDLE_WIDTH) { ballSpeedY = -ballSpeedY; } else { // game over alert("GAME OVER"); document.showToast("再読み込みしてください"); // restart game clearInterval(interval); // end animation } } // move paddle if(rightPressed && paddleX < WIDTH - PADDLE_WIDTH) { paddleX += PADDLE_SPEED; } else if(leftPressed && paddleX > 0) { paddleX -= PADDLE_SPEED; } } let interval = setInterval(draw, 10); </script> </body> </html> ``` ジョークとして、ブロックが破壊される度に「コンクリートの感触がよくわかる」というユーモアを追加することもできます。例えば、以下のようになります。 ``` for(let row=0; row<BRICK_ROWS; row++) { bricks[row] = []; for(let col=0; col<BRICK_COLS; col++) { bricks[row][col] = { x: col*(BRICK_WIDTH+BRICK_MARGIN)+BRICK_MARGIN, y: row*(BRICK_HEIGHT+BRICK_MARGIN)+BRICK_MARGIN, status: 1, emoji: '🧱' }; } } // collision detection function collisionDetection() { for(let row=0; row<BRICK_ROWS; row++) { for(let col=0; col<BRICK_COLS; col++) { let b = bricks[row][col]; if(b.status == 1) { if(ballX > b.x && ballX < b.x+BRICK_WIDTH && ballY > b.y && ballY < b.y+BRICK_HEIGHT) { ballSpeedY = -ballSpeedY; b.status = 0; score++; if(score % 10 == 0) { console.log("コンクリートの感触がよくわかる"); } } } } } } ```