您好,登录后才能下订单哦!
Flappy Bird 是一款非常经典的休闲游戏,玩家通过点击屏幕控制小鸟的飞行高度,避开管道,尽可能飞得更远。本文将详细介绍如何使用 JavaScript 和 HTML5 的 Canvas 元素来实现一个简单的 Flappy Bird 游戏。
在开始编写代码之前,我们需要准备一些基本的工具和资源:
首先,我们需要在 HTML 文件中创建一个 Canvas 元素,用于绘制游戏画面。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flappy Bird</title>
<style>
body {
margin: 0;
overflow: hidden;
}
canvas {
display: block;
margin: 0 auto;
background-color: #70c5ce;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="288" height="512"></canvas>
<script src="game.js"></script>
</body>
</html>
在上面的代码中,我们创建了一个 canvas
元素,并设置了其宽度和高度。game.js
是我们将要编写的 JavaScript 文件。
接下来,我们将在 game.js
中编写代码来绘制游戏的背景。
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// 加载背景图片
const bgImage = new Image();
bgImage.src = 'background.png';
function drawBackground() {
ctx.drawImage(bgImage, 0, 0, canvas.width, canvas.height);
}
function draw() {
drawBackground();
requestAnimationFrame(draw);
}
draw();
在上面的代码中,我们首先获取了 canvas
元素和其 2D 上下文 ctx
。然后加载了背景图片,并在 drawBackground
函数中绘制背景。最后,我们使用 requestAnimationFrame
来不断调用 draw
函数,实现动画效果。
接下来,我们将绘制小鸟。首先,我们需要加载小鸟的图片。
const birdImage = new Image();
birdImage.src = 'bird.png';
const bird = {
x: 50,
y: 150,
width: 34,
height: 24,
gravity: 0.6,
lift: -10,
velocity: 0
};
function drawBird() {
ctx.drawImage(birdImage, bird.x, bird.y, bird.width, bird.height);
}
function draw() {
drawBackground();
drawBird();
requestAnimationFrame(draw);
}
draw();
在上面的代码中,我们定义了一个 bird
对象,包含了小鸟的位置、大小、重力、升力和速度等属性。然后,我们在 drawBird
函数中绘制小鸟。
为了让小鸟能够上下移动,我们需要实现简单的物理运动。
function updateBird() {
bird.velocity += bird.gravity;
bird.y += bird.velocity;
if (bird.y + bird.height > canvas.height) {
bird.y = canvas.height - bird.height;
bird.velocity = 0;
}
if (bird.y < 0) {
bird.y = 0;
bird.velocity = 0;
}
}
function draw() {
drawBackground();
updateBird();
drawBird();
requestAnimationFrame(draw);
}
draw();
在上面的代码中,我们添加了 updateBird
函数,用于更新小鸟的位置和速度。小鸟的速度会不断增加,模拟重力效果。当小鸟碰到地面或顶部时,速度会被重置。
接下来,我们需要让小鸟在点击屏幕时上升。
document.addEventListener('click', () => {
bird.velocity = bird.lift;
});
function draw() {
drawBackground();
updateBird();
drawBird();
requestAnimationFrame(draw);
}
draw();
在上面的代码中,我们添加了一个事件监听器,当用户点击屏幕时,小鸟的速度会被设置为 lift
,从而实现上升效果。
接下来,我们将绘制管道。管道是 Flappy Bird 游戏中的障碍物,玩家需要控制小鸟避开管道。
const pipeImage = new Image();
pipeImage.src = 'pipe.png';
const pipes = [];
function drawPipes() {
for (let i = 0; i < pipes.length; i++) {
const pipe = pipes[i];
ctx.drawImage(pipeImage, pipe.x, pipe.y, pipe.width, pipe.height);
}
}
function updatePipes() {
if (frames % 90 === 0) {
const gap = 100;
const pipeHeight = Math.floor(Math.random() * (canvas.height - gap));
pipes.push({
x: canvas.width,
y: 0,
width: 52,
height: pipeHeight
});
pipes.push({
x: canvas.width,
y: pipeHeight + gap,
width: 52,
height: canvas.height - pipeHeight - gap
});
}
for (let i = 0; i < pipes.length; i++) {
const pipe = pipes[i];
pipe.x -= 2;
if (pipe.x + pipe.width < 0) {
pipes.splice(i, 1);
i--;
}
}
}
let frames = 0;
function draw() {
drawBackground();
updateBird();
drawBird();
updatePipes();
drawPipes();
frames++;
requestAnimationFrame(draw);
}
draw();
在上面的代码中,我们定义了一个 pipes
数组,用于存储所有的管道。每隔 90 帧,我们会在屏幕右侧生成一对新的管道,并将其添加到 pipes
数组中。然后,我们通过 updatePipes
函数更新管道的位置,并在 drawPipes
函数中绘制管道。
为了让游戏更加完整,我们需要实现碰撞检测。当小鸟碰到管道或地面时,游戏结束。
function collisionDetection() {
for (let i = 0; i < pipes.length; i++) {
const pipe = pipes[i];
if (
bird.x < pipe.x + pipe.width &&
bird.x + bird.width > pipe.x &&
bird.y < pipe.y + pipe.height &&
bird.y + bird.height > pipe.y
) {
return true;
}
}
if (bird.y + bird.height > canvas.height) {
return true;
}
return false;
}
function draw() {
drawBackground();
updateBird();
drawBird();
updatePipes();
drawPipes();
if (collisionDetection()) {
return;
}
frames++;
requestAnimationFrame(draw);
}
draw();
在上面的代码中,我们添加了 collisionDetection
函数,用于检测小鸟是否与管道或地面发生碰撞。如果发生碰撞,游戏将停止。
为了让游戏更加流畅,我们需要优化游戏循环。
let gameOver = false;
function draw() {
if (gameOver) {
return;
}
drawBackground();
updateBird();
drawBird();
updatePipes();
drawPipes();
if (collisionDetection()) {
gameOver = true;
ctx.fillStyle = 'black';
ctx.font = '30px Arial';
ctx.fillText('Game Over', canvas.width / 2 - 70, canvas.height / 2);
return;
}
frames++;
requestAnimationFrame(draw);
}
draw();
在上面的代码中,我们添加了一个 gameOver
变量,用于判断游戏是否结束。如果游戏结束,我们将在屏幕上显示 “Game Over” 的提示。
为了让游戏更加有趣,我们可以添加分数系统。每当小鸟成功通过一对管道时,分数加一。
let score = 0;
function drawScore() {
ctx.fillStyle = 'white';
ctx.font = '20px Arial';
ctx.fillText(`Score: ${score}`, 10, 30);
}
function updateScore() {
for (let i = 0; i < pipes.length; i++) {
const pipe = pipes[i];
if (pipe.x + pipe.width < bird.x && !pipe.passed) {
pipe.passed = true;
score++;
}
}
}
function draw() {
if (gameOver) {
return;
}
drawBackground();
updateBird();
drawBird();
updatePipes();
drawPipes();
updateScore();
drawScore();
if (collisionDetection()) {
gameOver = true;
ctx.fillStyle = 'black';
ctx.font = '30px Arial';
ctx.fillText('Game Over', canvas.width / 2 - 70, canvas.height / 2);
return;
}
frames++;
requestAnimationFrame(draw);
}
draw();
在上面的代码中,我们添加了 score
变量,并在 updateScore
函数中更新分数。每当小鸟通过一对管道时,分数加一。然后,我们在 drawScore
函数中绘制分数。
为了让游戏更加完整,我们可以添加游戏结束后的逻辑,比如重新开始游戏。
document.addEventListener('click', () => {
if (gameOver) {
gameOver = false;
bird.y = 150;
bird.velocity = 0;
pipes.length = 0;
score = 0;
frames = 0;
draw();
} else {
bird.velocity = bird.lift;
}
});
function draw() {
if (gameOver) {
ctx.fillStyle = 'black';
ctx.font = '30px Arial';
ctx.fillText('Game Over', canvas.width / 2 - 70, canvas.height / 2);
return;
}
drawBackground();
updateBird();
drawBird();
updatePipes();
drawPipes();
updateScore();
drawScore();
if (collisionDetection()) {
gameOver = true;
return;
}
frames++;
requestAnimationFrame(draw);
}
draw();
在上面的代码中,我们修改了点击事件监听器,当游戏结束时,点击屏幕可以重新开始游戏。
为了让游戏更加完善,我们可以进行一些优化和改进:
通过本文的介绍,我们使用 JavaScript 和 HTML5 的 Canvas 元素实现了一个简单的 Flappy Bird 游戏。我们从创建 Canvas 元素开始,逐步实现了背景绘制、小鸟的物理运动、管道的生成与移动、碰撞检测、分数系统以及游戏结束逻辑。希望本文能够帮助你理解如何使用 Canvas 制作简单的 2D 游戏,并激发你进一步探索游戏开发的兴趣。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。