精华内容
下载资源
问答
  • canvas小游戏
    千次阅读
    2021-04-12 10:44:38

    知识点
    canvas
    JavaScript

    开发准备
    代码获取

    $ wget https://labfile.oss.aliyuncs.com/courses/361/simple_canvas_game.zip

    在 IDE 的 Terminal 中:使用wget获取小游戏所需要的图片:

    $ wget https://labfile.oss.aliyuncs.com/courses/361/games.zip

    解压,在命令行执行:

    unzip games.zip

    得到games/文件夹之后, 就可以进行开发了。我们后续的代码都是写在game.js中。

    你可以看到在game.html里面有以下几行简单的 HTML 代码:

    Simple Canvas Game 接下来,从画布开始,逐步完成整个小游戏的代码编写。请跟随下面步骤一步一步的补充代码并思考每段代码的作用,完成学习。

    创建画布
    在 game.js 里面,我们首先需要为游戏的舞台创建一张画布 (canvas):

    var canvas = document.createElement(‘canvas’);
    var ctx = canvas.getContext(‘2d’);
    canvas.width = 512;
    canvas.height = 480;
    document.body.appendChild(canvas);

    这里通过 js 来创建了一个 元素并设置 canvas 的宽和高,最后将其添加到 标签后。var ctx = canvas.getContext(“2d”);中的 ctx 变量是我们后面会用到的,具体的 canvas 用法查看这里的链接:

    https://developer.mozilla.org/en/canvas_tutorial

    准备图片
    游戏需要加载我们之前存放在 images 文件夹下面的三张图片:

    // Background image
    var bgReady = false;
    var bgImage = new Image();
    bgImage.onload = function () {
    bgReady = true;
    };
    bgImage.src = ‘images/background.png’;

    // Hero image
    var heroReady = false;
    var heroImage = new Image();
    heroImage.onload = function () {
    heroReady = true;
    };
    heroImage.src = ‘images/hero.png’;

    // Monster image
    var monsterReady = false;
    var monsterImage = new Image();
    monsterImage.onload = function () {
    monsterReady = true;
    };
    monsterImage.src = ‘images/monster.png’;
    copy
    以上三张图片都是通过创建简单的图片对象来实现加载的,类似 bgReady 的三个变量用来标识图片是否已经加载完成,如果在图片加载未完成情况下进行绘制是会报错的。如果这段代码中的 new Image() 你无法理解,你可以在bgImage.src = “images/background.png”;之后使用console.log(bgImage); 来查看,你看到的将是类似:

    copy

    游戏对象
    我们需要定义一些对象,以便我们在后面会用到:

    var hero = {
    speed: 256, // movement in pixels per second
    };
    var monster = {};
    var monstersCaught = 0;
    copy
    既然是英雄抓获怪物,我们得要有一个英雄和怪物的对象。而英雄有一个speed属性用来控制他每秒移动多少像素。怪物游戏过程中不会移动,所以暂时不用设置属性。monstersCaught 则用来存储怪物被捉住的次数,初始值当然为 0 了。

    处理用户的输入
    游戏是提供给人们玩耍的,那么我们如何获取用户在游戏过程中的输入呢?按了键盘?点了鼠标?这些都是用户在玩游戏的时候的输入,我们一旦捕获到这些输入,就可以根据游戏的逻辑对用户的输入进行处理了:

    // Handle keyboard controls
    var keysDown = {};

    addEventListener(
    ‘keydown’,
    function (e) {
    keysDown[e.keyCode] = true;
    },
    false
    );

    addEventListener(
    ‘keyup’,
    function (e) {
    delete keysDown[e.keyCode];
    },
    false
    );
    copy
    这里我们只是监听两个用户的输入:

    keydown
    keyup
    然后我们将用户的输入先保存起来,并没有立即响应。为此,我们用keysDown这个对象来保存用户按下的键值(keyCode),如果按下的键值在这个对象里,那么我们就做相应处理,稍后,我们会看到如何进行相应处理。

    在前端开发中,一般是用户触发了点击事件然后才会去执行动画或发起异步请求等操作

    开始一轮游戏
    游戏在结束的时候,我们需要开始新的一轮游戏,所以在game.js添加reset函数

    // Reset the game when the player catches a monster
    var reset = function () {
    hero.x = canvas.width / 2;
    hero.y = canvas.height / 2;

    // Throw the monster somewhere on the screen randomly
    monster.x = 32 + Math.random() * (canvas.width - 64);
    monster.y = 32 + Math.random() * (canvas.height - 64);
    };
    copy
    reset()函数用于开始新一轮和游戏,在这个方法里我们将英雄放回画布中心同时将怪物放到一个随机的地方。

    更新对象
    在游戏的过程中,不管是用户在玩(有正确输入的状态)还是游戏结束,我们都是需要及时更新游戏的对象:

    var update = function (modifier) {
    if (38 in keysDown) {
    // Player holding up
    hero.y -= hero.speed * modifier;
    }
    if (40 in keysDown) {
    // Player holding down
    hero.y += hero.speed * modifier;
    }
    if (37 in keysDown) {
    // Player holding left
    hero.x -= hero.speed * modifier;
    }
    if (39 in keysDown) {
    // Player holding right
    hero.x += hero.speed * modifier;
    }

    // Are they touching?
    if (
    hero.x <= monster.x + 32 &&
    monster.x <= hero.x + 32 &&
    hero.y <= monster.y + 32 &&
    monster.y <= hero.y + 32
    ) {
    ++monstersCaught;
    reset();
    }
    };
    copy
    update函数负责更新游戏的各个对象,会被规律地重复调用。首先它负责检查用户当前按住的是哪一个方向键,然后将英雄往相应方向移动。

    有点费脑力的或许是这个传入的modifier 变量。你可以在后面将要实现的main 方法里看到它的来源,但这里还是有必要详细解释一下。它是基于 1 开始并随时间变化的一个因子。例如 1 秒过去了,它的值就是 1,英雄的速度将会乘以 1,也就是每秒移动 256 像素;如果半秒钟则它的值为 0.5,英雄的速度就乘以 0.5 也就是说这半秒内英雄以正常速度一半的速度移动。理论上说因为这个update函数被调用的非常快且频繁,所以modifier的值会很小,但有了这一因子后,不管我们的代码跑得快慢,都能够保证英雄的移动速度是恒定的。

    这里需要说明一下下面的判断怪物和英雄是什么根据:

    if (
    hero.x <= (monster.x + 32)
    && monster.x <= (hero.x + 32)
    && hero.y <= (monster.y + 32)
    && monster.y <= (hero.y + 32)
    )
    copy
    上面的32是由hero和monster图片的大小决定的,我们的 hero 图片是32x32,monster 图片是30x32,所以根据坐标的位于图片中心的法制,就可以得到上面的判断条件。

    执行函数 update(),首先是实现基于用户的输入(按下上,下,左,右键)的英雄的移动,接下来判断英雄与怪物是否相遇。如果相遇,就是本游戏的胜利点,monstersCaught +1然后重新开始新一轮。

    渲染物体
    之前写的代码都是在准备前期工作和处理一些游戏的状态等,下面将进入正题:我们需要将所有的东西画出来

    // Draw everything
    var render = function () {
    if (bgReady) {
    ctx.drawImage(bgImage, 0, 0);
    }

    if (heroReady) {
    ctx.drawImage(heroImage, hero.x, hero.y);
    }

    if (monsterReady) {
    ctx.drawImage(monsterImage, monster.x, monster.y);
    }

    // Score
    ctx.fillStyle = ‘rgb(250, 250, 250)’;
    ctx.font = ‘24px Helvetica’;
    ctx.textAlign = ‘left’;
    ctx.textBaseline = ‘top’;
    ctx.fillText('Goblins caught: ’ + monstersCaught, 32, 32);
    };
    copy
    这里的ctx就是最前面我们创建的变量。然后利用canvas的drawImage()先把背景图画出来。然后如法炮制将英雄和怪物也画出来。这个过程中的顺序是有讲究的,因为后画的物体会覆盖之前的物体。

    这之后我们改变了一下Canvas的绘图上下文的样式并调用fillText来绘制文字,也就是记分板那一部分。本游戏没有其他复杂的动画效果和打斗场面,绘制部分大功告成。

    主循环函数
    我们将画面画出来以后,紧接着需要实现的就是游戏的循环结构,将它放在main函数里:

    // The main game loop
    var main = function () {
    var now = Date.now();

    var delta = now - then;
    //console.log(delta);
    update(delta / 1000);
    render();

    then = now;

    // Request to do this again ASAP
    requestAnimationFrame(main);
    };
    copy
    上面的主函数控制了整个游戏的流程。先是拿到当前的时间用来计算时间差(距离上次主函数被调用时过了多少毫秒)。得到modifier后除以 1000(也就是 1 秒中的毫秒数)再传入update函数。最后调用render 函数并且将本次的时间保存下来。

    设置 requestAnimationFrame()
    在上面的main函数中,我们通过requestAnimationFrame()调用了main函数,所以我们需要声明:

    var w = window;
    requestAnimationFrame =
    w.requestAnimationFrame ||
    w.webkitRequestAnimationFrame ||
    w.msRequestAnimationFrame ||
    w.mozRequestAnimationFrame;
    copy
    上述代码是浏览器兼容性的解决。

    最后启动游戏
    万事具备,只欠东风。到此,所有的游戏代码基本就写完了,我们现在需要做的就是调用相应的函数来启动游戏:

    // Let’s play this game!
    var then = Date.now();
    reset();
    main();
    copy
    到这里代码就写完了。先是设置一个初始的时间变量then用于首先运行main函数使用。然后调用 reset 函数来开始新一轮游戏(如果你还记得的话,这个函数的作用是将英雄放到画面中间同时将怪物放到随机的地方以方便英雄去捉它)

    用浏览器打开game.html,开始玩游戏吧!

    实验总结
    本实验基于 canvas 实现了一个简单的小游戏,或者说是一个小 DEMO。本课程的重点不是在于做一个游戏出来,而是让你了解开发一个 canvas 设计到的东西,如开发流程,图片处理,事件处理等。

    参考链接
    本实验课程文档基于以下博文进行改编,感谢原作者及译者贡献了优秀的文档:

    【译】http://www.cnblogs.com/Wayou/p/how-to-make-a-simple-html5-canvas-game.html 【原】http://www.lostdecadegames.com/how-to-make-a-simple-html5-canvas-game/

    更多相关内容
  • canvas小游戏开发

    2021-12-30 15:59:40
    利用canvas画布,进行撞击,消除操作的小游戏
  • 个人练手用的,很多东西都是瞎写的,看看就好
  • canvas小游戏-连连看

    2016-12-02 16:04:58
    js 小游戏 canvas版连连看 内置20张地图 图片素材来源于网络 仅限学习使用 js 小游戏 canvas版连连看 内置20张地图 图片素材来源于网络 仅限学习使用
  • H5 的canvas小游戏实例

    2019-01-07 18:34:55
    html5 开发技术 游戏.很好玩的html5+canvas技术实现的拼图游戏
  • canvas小游戏

    2018-03-26 20:29:59
    canvas制作的小游戏,全面实现教学效果,公司自己研发框架,欢迎各位下载.
  • Canvas仿切水果小游戏代码是一款通过鼠标移动切中圆圈计一分,未切中也会统计显示。
  • js H5 canvas投篮小游戏

    2020-10-21 17:37:54
    主要为大家详细介绍了JavaScript结合H5 canvas实现投篮小游戏的具体代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • H5 Canvas实现经典扫雷小游戏,原创无注释,300行代码。鼠标左键扫雷,右键标记,按住滚轮可预览可点击的格子(同windows版本鼠标左右键同时按住)。主要功能都正常,可能有小bug,大家可以自行修改完善。
  • canvas小游戏 启动 clone项目到本地,执行node server.js打开 localhost:8899 查看 直接访问 操作 上下左右方向键移动 点击【提示】答案可以查看答案路线 点击【重来】可以重新游戏
  • JS+canvas实现弹球打砖块小游戏。弹球打砖块是可以有丰富拓展的小游戏,这里面有详细的碰撞检测逻辑,可以实现基础的弹球打砖块,适合新手在此基础上写出自己的玩法。
  • H5 canvas 实现小游戏

    2018-06-25 20:37:10
    H5 canvas 实现小游戏 H5 canvas 实现小游戏 H5 canvas 实现小游戏 H5 canvas 实现小游戏
  • 试验性质的一个微信小程序,用canvas做的一个类似flappy-bird的小游戏。 包含一些基本的功能:躲避障碍物、计分、排行榜等等。后端的工程也一并上传了,在java目录中,很简单的一个SpringMVC工程。 游戏原型见这里。...
  • canvas小游戏-爱心鱼

    2018-02-27 11:30:35
    前端canvas小游戏-爱心鱼,大鱼吃到水中的浮游生物后喂给小鱼吃,维持小鱼生存。
  • 整个游戏过程比较简单,玩家只需要点击手机屏幕来使中间粉红的那个小方块跳动起来便可,如果小方块被带到了屏幕的左边,那么游戏结束;在屏幕的最中>间有一个时间计数器,每隔10s,计数器上的数字变换一次颜色,玩家...
  • 图形和形状支持渲染支持内置图像加载器内置跨平台运动库微信游戏演示演示版微信应用演示文件入门通过npm或CDN获取cax: npm i cax 用法: import cax from 'cax'const stage = new cax . Stage ( 200 , 200 , 'body'...
  • 类似下红包雨,接红包的小游戏,使用html js canvas开发
  • HTML5 canvas趣味飞船捡金币小游戏
  • HTML5 Canvas射箭小游戏

    2021-06-24 12:59:52
    HTML5 Canvas射箭小游戏源码是一款简单实用的HTML5小游戏代码。
  • 利用html5 canvas制作的小游戏
  • HTML5 canvas乒乓球小游戏代码,按任意键开始游戏,键盘方向键控制游戏,挡击对方小球,先得到5分获得胜利。
  • canvas拼图小游戏

    2022-01-19 15:16:32
    canvas拼图小游戏
  • canvas简单射击游戏

    2018-10-15 10:10:08
    业余时间制作了一个简单射击小游戏,包括几个怪物,可以显示血条,不同属性的怪物,怪物出生位置还可以再随机一点,各位可以自行修改。
  • canvasGame 使用canvas制作的一些小游戏 技术需求 基于JavaScript基础 ,canvas基础 游戏列表
  • canvas 飞机大战小游戏

    2022-01-19 15:12:34
    canvas 飞机大战小游戏
  • 想要快速上手HTML5 Canvas小游戏开发?下面通过一个例子来进行手把手教学。(如果你怀疑我的资历, A Wizard's Lizard这个游戏的半数以上开发是由我完成的) 我们直接来看源码里的game.js,当然你也可以在线体验...

    原文:How to make a simple HTML5 Canvas game

    想要快速上手HTML5 Canvas小游戏开发?下面通过一个例子来进行手把手教学。(如果你怀疑我的资历, A Wizard's Lizard这个游戏的半数以上开发是由我完成的)

    我们直接来看源码里的game.js,当然你也可以在线体验一下游戏先。

    游戏截图

    游戏截图

    创建画布

    // Create the canvas
    var canvas = document.createElement("canvas");
    var ctx = canvas.getContext("2d");
    canvas.width = 512;
    canvas.height = 480;
    document.body.appendChild(canvas);

    首先我们需要创建一张画布作为游戏的舞台。这里通过JS代码而不是直接在HTML里写一个<canvas>元素目的是要说明代码创建也是很方便的。有了画布后就可以获得它的上下文来进行绘图了。然后我们还设置了画布大小,最后将其添加到页面上。

    准备图片

    // 背景图片
    var bgReady = false;
    var bgImage = new Image();
    bgImage.onload = function () {
        bgReady = true;
    };
    bgImage.src = "images/background.png";

    游戏嘛少不了图片的,所以我们先加载一些图片先。简便起见,这里仅创建简单的图片对象,而不是专门写一个类或者Helper来做图片加载。bgReady这个变量用来标识图片是否已经加载完成从而可以放心地使用了,因为如果在图片加载未完成情况下进行绘制是会报错的。

    整个游戏中需要用到的三张图片:背景英雄怪物我们都用上面的方法来处理。

    游戏对象

    // 游戏对象
    var hero = {
        speed: 256, // 每秒移动的像素
        x: 0,
        y: 0
    };
    var monster = {
        x: 0,
        y: 0
    };
    var monstersCaught = 0;

    现在定义一些对象将在后面用到。我们的英雄有一个speed属性用来控制他每秒移动多少像素。怪物游戏过程中不会移动,所以只有坐标属性就够了。monstersCaught则用来存储怪物被捉住的次数。

    处理用户的输入

    // 处理按键
    var keysDown = {};
    
    addEventListener("keydown", function (e) {
        keysDown[e.keyCode] = true;
    }, false);
    
    addEventListener("keyup", function (e) {
        delete keysDown[e.keyCode];
    }, false);

    现在开始处理用户的输入(对初次接触游戏开发的前端同学来说,这部分开始可能就需要一些脑力了)。在前端开发中,一般是用户触发了点击事件然后才去执行动画或发起异步请求之类的,但这里我们希望游戏的逻辑能够更加紧凑同时又要及时响应输入。所以我们就把用户的输入先保存下来而不是立即响应。

    为此,我们用keysDown这个对象来保存用户按下的键值(keyCode),如果按下的键值在这个对象里,那么我们就做相应处理。

    开始一轮游戏

    // 当用户抓住一只怪物后开始新一轮游戏
    var reset = function () {
        hero.x = canvas.width / 2;
        hero.y = canvas.height / 2;
    
        // 将新的怪物随机放置到界面上
        monster.x = 32 + (Math.random() * (canvas.width - 64));
        monster.y = 32 + (Math.random() * (canvas.height - 64));
    };

    reset方法用于开始新一轮和游戏,在这个方法里我们将英雄放回画布中心同时将怪物放到一个随机的地方。

    更新对象

    // 更新游戏对象的属性
    var update = function (modifier) {
        if (38 in keysDown) { // 用户按的是↑
            hero.y -= hero.speed * modifier;
        }
        if (40 in keysDown) { // 用户按的是↓
            hero.y += hero.speed * modifier;
        }
        if (37 in keysDown) { // 用户按的是←
            hero.x -= hero.speed * modifier;
        }
        if (39 in keysDown) { // 用户按的是→
            hero.x += hero.speed * modifier;
        }
    
        // 英雄与怪物碰到了么?
        if (
            hero.x <= (monster.x + 32)
            && monster.x <= (hero.x + 32)
            && hero.y <= (monster.y + 32)
            && monster.y <= (hero.y + 32)
        ) {
            ++monstersCaught;
            reset();
        }
    };

    这就是游戏中用于更新画面的update函数,会被规律地重复调用。首先它负责检查用户当前按住的是中方向键,然后将英雄往相应方向移动。

    有点费脑力的或许是这个传入的modifier 变量。你可以在main 方法里看到它的来源,但这里还是有必要详细解释一下。它是基于1开始且随时间变化的一个因子。例如1秒过去了,它的值就是1,英雄的速度将会乘以1,也就是每秒移动256像素;如果半秒钟则它的值为0.5,英雄的速度就乘以0.5也就是说这半秒内英雄以正常速度一半的速度移动。理论上说因为这个update 方法被调用的非常快且频繁,所以modifier的值会很小,但有了这一因子后,不管我们的代码跑得快慢,都能够保证英雄的移动速度是恒定的。

    现在英雄的移动已经是基于用户的输入了,接下来该检查移动过程中所触发的事件了,也就是英雄与怪物相遇。这就是本游戏的胜利点,monstersCaught +1然后重新开始新一轮。

    渲染物体

    // 画出所有物体
    var render = function () {
        if (bgReady) {
            ctx.drawImage(bgImage, 0, 0);
        }
    
        if (heroReady) {
            ctx.drawImage(heroImage, hero.x, hero.y);
        }
    
        if (monsterReady) {
            ctx.drawImage(monsterImage, monster.x, monster.y);
        }
    
        // 计分
        ctx.fillStyle = "rgb(250, 250, 250)";
        ctx.font = "24px Helvetica";
        ctx.textAlign = "left";
        ctx.textBaseline = "top";
        ctx.fillText("Monsterrs caught: " + monstersCaught, 32, 32);
    };

    之前的工作都是枯燥的,直到你把所有东西画出来之后。首先当然是把背景图画出来。然后如法炮制将英雄和怪物也画出来。这个过程中的顺序是有讲究的,因为后画的物体会覆盖之前的物体。

    这之后我们改变了一下Canvas的绘图上下文的样式并调用fillText来绘制文字,也就是记分板那一部分。本游戏没有其他复杂的动画效果和打斗场面,绘制部分大功告成!

    主循环函数

    // 游戏主函数
    var main = function () {
        var now = Date.now();
        var delta = now - then;
    
        update(delta / 1000);
        render();
    
        then = now;
    
        // 立即调用主函数
        requestAnimationFrame(main);
    };

    上面的主函数控制了整个游戏的流程。先是拿到当前的时间用来计算时间差(距离上次主函数被调用时过了多少毫秒)。得到modifier后除以1000(也就是1秒中的毫秒数)再传入update函数。最后调用render 函数并且将本次的时间保存下来。

    关于游戏中循环更新画面的讨论可参见「Onslaught! Arena Case Study」。

    关于循环的进一步解释

    // requestAnimationFrame 的浏览器兼容性处理
    var w = window;
    requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;

    如果你不是完全理解上面的代码也没关系,我只是觉得拿出来解释一下总是极好的

    为了循环地调用main函数,本游戏之前用的是setInterval。但现今已经有了更好的方法那就是requestAnimationFrame。使用新方法就不得不考虑浏览器兼容性。上面的垫片就是出于这样的考虑,它是Paul Irish 博客原版的一个简化版本。

    启动游戏!

    // 少年,开始游戏吧!
    var then = Date.now();
    reset();
    main();

    总算完成了,这是本游戏最后一段代码了。先是设置一个初始的时间变量then用于首先运行main函数使用。然后调用 reset 函数来开始新一轮游戏(如果你还记得的话,这个函数的作用是将英雄放到画面中间同时将怪物放到随机的地方以方便英雄去捉它)。

    到此,相信你已经掌握了开发一个简单H5小游戏需要的基本功了。玩玩这个游戏或者下载代码自己研究研究吧 :)

    展开全文
  • canvas打砖块小游戏

    2022-01-19 15:13:34
    canvas打砖块小游戏
  • canvas画布写的一个小游戏,通过点击鼠标来控制小鸟的高度,通过一个柱子得一分,碰到柱子或者鸟掉出画布游戏结束。
  • canvas简单游戏

    2018-08-03 10:30:32
    canvas 实现2d 简单小游戏,点击出现蓝色攻击方块,攻击黑色方块得分,触碰红色方块游戏结束,黑色方块想灭完,游戏等级提升
  • 本文介绍了H5 canvas实现贪吃蛇小游戏,分享给大家,具体如下: 实现效果如下 实现思路: ps:这个只是思路,详细可看代码注释 一、先把蛇画出来 定义一下蛇的结构,用一个数组保存一堆矩形,包含蛇头(红)和蛇身...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 32,683
精华内容 13,073
关键字:

canvas小游戏

友情链接: fluxbb-1.5.11.zip