JavaScript怎么使用canvas实现flappy bird

发布时间:2023-03-09 15:12:38 作者:iii
来源:亿速云 阅读:108

JavaScript怎么使用canvas实现flappy bird

目录

  1. 引言
  2. 准备工作
  3. 创建Canvas元素
  4. 绘制背景
  5. 绘制小鸟
  6. 小鸟的物理运动
  7. 绘制管道
  8. 碰撞检测
  9. 游戏循环
  10. 添加分数
  11. 游戏结束逻辑
  12. 优化与改进
  13. 总结

引言

Flappy Bird 是一款非常经典的休闲游戏,玩家通过点击屏幕控制小鸟的飞行高度,避开管道,尽可能飞得更远。本文将详细介绍如何使用 JavaScript 和 HTML5 的 Canvas 元素来实现一个简单的 Flappy Bird 游戏。

准备工作

在开始编写代码之前,我们需要准备一些基本的工具和资源:

  1. 文本编辑器:如 VS Code、Sublime Text 等。
  2. 浏览器:推荐使用 Chrome 或 Firefox,因为它们对 HTML5 和 JavaScript 的支持较好。
  3. 图像资源:小鸟和管道的图片,可以从网上下载或自己绘制。

创建Canvas元素

首先,我们需要在 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();

在上面的代码中,我们修改了点击事件监听器,当游戏结束时,点击屏幕可以重新开始游戏。

优化与改进

为了让游戏更加完善,我们可以进行一些优化和改进:

  1. 添加音效:可以在小鸟跳跃、碰撞和得分时播放音效。
  2. 增加难度:随着分数的增加,可以逐渐加快管道的移动速度或减小管道之间的间隙。
  3. 美化界面:可以使用更精美的图片和动画效果来提升游戏的视觉效果。
  4. 移动端适配:可以通过调整 Canvas 的大小和触摸事件来适配移动设备。

总结

通过本文的介绍,我们使用 JavaScript 和 HTML5 的 Canvas 元素实现了一个简单的 Flappy Bird 游戏。我们从创建 Canvas 元素开始,逐步实现了背景绘制、小鸟的物理运动、管道的生成与移动、碰撞检测、分数系统以及游戏结束逻辑。希望本文能够帮助你理解如何使用 Canvas 制作简单的 2D 游戏,并激发你进一步探索游戏开发的兴趣。

推荐阅读:
  1. JSBinding + SharpKit如何生成JavaScript绑定
  2. JS Binding跟SharpKit或JavaScript的加载流程是怎样的

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

javascript canvas

上一篇:Python怎么遍历字典的键和值

下一篇:Oracle存储过程怎么理解

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》