宇宙ブロック崩し
by AtomicOwl82586 lines9.0 KB
```html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>宇宙ブロック崩し</title>
<style>
* {
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
body {
background: #05051a;
color: white;
font-family: sans-serif;
text-align: center;
}
h1 {
margin: 6px 0;
font-size: clamp(20px, 4vw, 28px);
}
#info {
font-size: clamp(14px, 3vw, 18px);
margin: 4px;
}
#game {
background: linear-gradient(#08082b, #15154a);
border: 3px solid white;
display: block;
margin: 0 auto;
width: min(800px, calc(100vw - 20px));
height: auto;
aspect-ratio: 4 / 3;
}
#help {
margin: 4px;
font-size: clamp(12px, 2.5vw, 16px);
}
button {
font-size: 16px;
padding: 6px 16px;
cursor: pointer;
}
</style>
</head>
<body>
<h1>👽 宇宙ブロック崩し 🚀</h1>
<div id="info">
❤️ 残機: <span id="lives">3</span>
🎁 復活: <span id="revive">0</span>
</div>
<canvas id="game" width="800" height="600"></canvas>
<p id="help">
← → キーでパドルを動かそう! 宇宙人の攻撃にも注意!
</p>
<button onclick="location.reload()">もう一度遊ぶ</button>
<script>
const canvas = document.getElementById("game");
const ctx = canvas.getContext("2d");
let paddle = {
x: 350,
y: 550,
width: 100,
height: 15,
speed: 8
};
let balls = [
{
x: 400,
y: 530,
dx: 4,
dy: -4,
radius: 8
}
];
let keys = {};
let lives = 3;
let revive = 0;
let gameOver = false;
let clear = false;
let alien = {
x: 380,
y: 40,
width: 40,
height: 30,
dx: 2
};
let alienShots = [];
let blocks = [];
const rows = 5;
const cols = 10;
const blockWidth = 70;
const blockHeight = 25;
const blockGap = 7;
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
blocks.push({
x: 20 + c * (blockWidth + blockGap),
y: 90 + r * (blockHeight + blockGap),
width: blockWidth,
height: blockHeight,
alive: true
});
}
}
document.addEventListener("keydown", function(e) {
keys[e.key] = true;
if (
e.key === "ArrowLeft" ||
e.key === "ArrowRight"
) {
e.preventDefault();
}
});
document.addEventListener("keyup", function(e) {
keys[e.key] = false;
});
function randomItem(ball) {
let chance = Math.floor(Math.random() * 5);
if (chance === 0) {
balls.push({
x: ball.x,
y: ball.y,
dx: -ball.dx,
dy: ball.dy,
radius: 8
});
}
else if (chance === 1) {
revive = 1;
document.getElementById("revive").textContent = revive;
}
else if (chance === 2) {
// 何もなし
}
else if (chance === 3) {
ball.dx *= 1.7;
ball.dy *= 1.7;
setTimeout(function() {
ball.dx *= 0.59;
ball.dy *= 0.59;
}, 5000);
}
else if (chance === 4) {
ball.dx *= 0.6;
ball.dy *= 0.6;
setTimeout(function() {
ball.dx *= 1.67;
ball.dy *= 1.67;
}, 10000);
}
}
function loseBall(index) {
if (balls.length > 1) {
balls.splice(index, 1);
return;
}
if (revive > 0) {
revive = 0;
document.getElementById("revive").textContent = revive;
balls[0].x =
paddle.x + paddle.width / 2;
balls[0].y =
paddle.y - 15;
balls[0].dx = 4;
balls[0].dy = -4;
return;
}
lives--;
document.getElementById("lives").textContent = lives;
if (lives <= 0) {
gameOver = true;
}
else {
balls[0].x =
paddle.x + paddle.width / 2;
balls[0].y =
paddle.y - 15;
balls[0].dx = 4;
balls[0].dy = -4;
}
}
function update() {
if (gameOver || clear) {
return;
}
// パドル
if (keys["ArrowLeft"]) {
paddle.x -= paddle.speed;
}
if (keys["ArrowRight"]) {
paddle.x += paddle.speed;
}
if (paddle.x < 0) {
paddle.x = 0;
}
if (
paddle.x + paddle.width >
canvas.width
) {
paddle.x =
canvas.width - paddle.width;
}
// 宇宙人
alien.x += alien.dx;
if (
alien.x < 0 ||
alien.x + alien.width >
canvas.width
) {
alien.dx *= -1;
}
// 宇宙人の攻撃
if (Math.random() < 0.015) {
alienShots.push({
x:
alien.x +
alien.width / 2,
y:
alien.y +
alien.height,
dy: 5
});
}
for (
let i = alienShots.length - 1;
i >= 0;
i--
) {
let shot = alienShots[i];
shot.y += shot.dy;
if (
shot.x > paddle.x &&
shot.x < paddle.x + paddle.width &&
shot.y > paddle.y &&
shot.y < paddle.y + paddle.height
) {
alienShots.splice(i, 1);
lives--;
document.getElementById("lives")
.textContent = lives;
if (lives <= 0) {
gameOver = true;
}
continue;
}
if (shot.y > canvas.height) {
alienShots.splice(i, 1);
}
}
// ボール
for (
let i = balls.length - 1;
i >= 0;
i--
) {
let ball = balls[i];
ball.x += ball.dx;
ball.y += ball.dy;
// 左右の壁
if (
ball.x - ball.radius < 0 ||
ball.x + ball.radius >
canvas.width
) {
ball.dx *= -1;
}
// 上の壁
if (ball.y - ball.radius < 0) {
ball.dy *= -1;
}
// パドル
if (
ball.y + ball.radius >= paddle.y &&
ball.y + ball.radius <=
paddle.y + paddle.height &&
ball.x >= paddle.x &&
ball.x <=
paddle.x + paddle.width &&
ball.dy > 0
) {
ball.dy =
-Math.abs(ball.dy);
let hitPosition =
(ball.x - paddle.x) /
paddle.width - 0.5;
ball.dx =
hitPosition * 10;
}
// ボールが落ちた
if (
ball.y - ball.radius >
canvas.height
) {
loseBall(i);
continue;
}
// ブロック
for (let block of blocks) {
if (!block.alive) {
continue;
}
if (
ball.x + ball.radius >
block.x &&
ball.x - ball.radius <
block.x + block.width &&
ball.y + ball.radius >
block.y &&
ball.y - ball.radius <
block.y + block.height
) {
block.alive = false;
ball.dy *= -1;
randomItem(ball);
break;
}
}
}
// 全ブロック破壊
if (
blocks.every(
block => !block.alive
)
) {
clear = true;
}
}
function draw() {
ctx.clearRect(
0,
0,
canvas.width,
canvas.height
);
// 星
ctx.fillStyle = "white";
for (let i = 0; i < 50; i++) {
let x =
(i * 157) %
canvas.width;
let y =
(i * 83) %
canvas.height;
ctx.fillRect(
x,
y,
2,
2
);
}
// ブロック
for (let block of blocks) {
if (!block.alive) {
continue;
}
ctx.fillStyle =
"#39d9ff";
ctx.fillRect(
block.x,
block.y,
block.width,
block.height
);
}
// パドル
ctx.fillStyle = "white";
ctx.fillRect(
paddle.x,
paddle.y,
paddle.width,
paddle.height
);
// ボール
for (let ball of balls) {
ctx.beginPath();
ctx.arc(
ball.x,
ball.y,
ball.radius,
0,
Math.PI * 2
);
ctx.fillStyle =
"#ffff00";
ctx.fill();
ctx.closePath();
}
// 宇宙人
ctx.fillStyle =
"#72ff72";
ctx.fillRect(
alien.x,
alien.y,
alien.width,
alien.height
);
ctx.fillStyle = "black";
ctx.fillRect(
```
Game Source: 宇宙ブロック崩し
Creator: AtomicOwl82
Libraries: none
Complexity: complex (586 lines, 9.0 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: game-atomicowl82" to link back to the original. Then publish at arcadelab.ai/publish.