效果图 (无素材贴图)
源代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小鸟游戏</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
#gameCanvas {
border: 1px solid #000;
}
#controlButton {
position: absolute;
bottom: 20px;
padding: 10px 20px;
font-size: 16px;
color: #fff;
background-color: #ff4d4d;
border: none;
border-radius: 20px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
cursor: pointer;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="400" height="600"></canvas>
<button id="controlButton">点击飞起</button>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const button = document.getElementById('controlButton');
let bird = {
x: 50,
y: canvas.height / 2,
radius: 15,
gravity: 0.1,
lift: -15,
velocity: -1
};
let pipes = [];
let score = 0;
let frame = 0;
let gameOver = false;
function drawBird() {
ctx.beginPath();
ctx.arc(bird.x, bird.y, bird.radius, 0, Math.PI * 2);
ctx.fillStyle = 'red';
ctx.fill();
ctx.closePath();
}
function drawPipe(pipe) {
ctx.fillStyle = 'green';
ctx.fillRect(pipe.x, 0, pipe.width, pipe.top);
ctx.fillRect(pipe.x, canvas.height - pipe.bottom, pipe.width, pipe.bottom);
}
function updateBird() {
bird.velocity += bird.gravity;
bird.y += bird.velocity;
if (bird.y + bird.radius > canvas.height) {
bird.y = canvas.height - bird.radius;
bird.velocity = 0;
}
if (bird.y - bird.radius < 0) {
bird.y = bird.radius;
bird.velocity = 0;
}
}
function updatePipes() {
frame++;
if (frame % 100 === 0) {
let gap = 150;
let top = Math.random() * (canvas.height - gap);
let bottom = canvas.height - top - gap;
pipes.push({ x: canvas.width, width: 50, top: top, bottom: bottom });
}
for (let i = pipes.length - 1; i >= 0; i--) {
pipes[i].x -= 2;
if (pipes[i].x + pipes[i].width < 0) {
pipes.splice(i, 1);
score++;
}
if (bird.x + bird.radius > pipes[i].x && bird.x - bird.radius < pipes[i].x + pipes[i].width) {
if (bird.y - bird.radius < pipes[i].top || bird.y + bird.radius > canvas.height - pipes[i].bottom) {
gameOver = true;
}
}
}
}
function resetGame() {
bird.y = canvas.height / 2;
bird.velocity = 0;
pipes = [];
score = 0;
frame = 0;
gameOver = false;
}
function drawScore() {
ctx.font = '20px Arial';
ctx.fillStyle = 'black';
ctx.fillText('Score: ' + score, 10, 30);
}
function gameLoop() {
if (!gameOver) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBird();
pipes.forEach(drawPipe);
drawScore();
updateBird();
updatePipes();
requestAnimationFrame(gameLoop);
} else {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.font = '30px Arial';
ctx.fillStyle = 'black';
ctx.fillText('Game Over', canvas.width / 2 - 70, canvas.height / 2 - 30);
ctx.fillText('Final Score: ' + score, canvas.width / 2 - 90, canvas.height / 2 + 30);
}
}
button.addEventListener('click', () => {
if (!gameOver) {
bird.velocity += bird.lift;
bird.lift *= 1; // 每次弹起距离降低一点
}
});
gameLoop();
</script>
</body>
</html>