怎样用HTML5 Canvas制作一个简单的游戏

为了让大家清楚HTML5制作游戏的简单流程,所以先了制作一个非常简单的游戏,来看一看这个过程。

游戏非常简单,无非就是英雄抓住怪物就得分,然后游戏重新开始,怪物出现在地图的随机位置,英雄初始化在地图的中间。点击这里,我们可以直接先玩玩这个游戏

1. 创建一个Canvas对象

这里相信大家都知道,当然代码里面是通过JS动态创建的画布,大家也可以直接在HTML页面上先创建画布,然后再通过document.getELementById()来获取,这两种方法没有什么区别,只是看你更习惯哪一种。

// 创建画布canvas,并获取画布上下文环境

var canvas = document.createElement("canvas");

var ctx = canvas.getContext("2d");

canvas.width = 512;

canvas.height = 480;

document.body.appendChild(canvas);

2. 载入图片

游戏需要图像,所以让我们载入一些图片吧。我想尽量简单化,所以只用了Image对象来做,当然,还可以将载入图像的功能封装成一个类或别的任何形式。代码中的bgReady用来标识图片是否已完全载入,只有当图片载入完成后,我们才能使用它,如果在载入完成前就对其进行绘制或渲染,JS将会报一个DOM error的错误。

我们会用到三张图片(背景、英雄、怪物),每张图片都需要这样处理。

// 背景图片 bgImage

var bgReady = false;

var bgImage = new Image();

bgImage.onload = function () {

bgReady = true;

};

bgImage.src = "images/background.png";

这里需要注意的一点,把bgImage.src写在bgImage.onload之后是为了解决IE显示的bug,所以建议大家都这么么写。

3. 定义游戏要使用的对象

// 游戏对象

var hero = {

speed: 256, // 英雄每秒移动的速度,即256px/s

x: 0,

y: 0

};

var monster = {

x: 0,

y: 0

};

var monstersCaught = 0;

定义一些变量,稍后会用到。hero对象的speed属性表示英雄的移动速度(像素/秒);monster对象不会移动,所以仅仅具有一对坐标;monstersCaught表示玩家抓住的怪物数量。

4. 处理玩家输入

// 键盘 输入处理

var keysDown = {};

addEventListener("keydown", function (e) {

keysDown[e.keyCode] = true;

}, false);

addEventListener("keyup", function (e) {

delete keysDown[e.keyCode];

}, false);

用户到底按下了哪个键,通过键盘事件来处理,将按下的键的keyCode保存在空对象KeysDown中。如果该变量中具有某个键编码,就表示用户目前正按下这个键。

5. 新游戏

// 当英雄捉住怪物之后重新开始游戏,英雄的位置在画布中间,怪物位置随机

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函数来开始新游戏。该函数将英雄(即玩家角色)放到屏幕中间,然后随机选择一个位置来安置怪物。

6. 更新对象

// 更新游戏对象

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函数中看到它,不过我在这儿先解释一下。modifier参数是一个从1开始的与时间相关的数。如果间隔刚好为1秒时,它的值就会为1,英雄移动的距离即为256像素(英雄的速度为256像素/秒);而如果间隔是0.5秒,它的值就为0.5,即英雄移动的距离为其速度的一半,以此类推。通常update函数调用的间隔很短,所以modifier的值很小,但用这种方式能够确保不管代码执行的速度怎么样,英雄的移动速度都是相同的。

这和我们之前的做法是不一样的,我们之前的做法经常是向右移动 x += spped,向左移动 x -= speed,之前的这种做法,相当于已经给定了物体移动的速度,无论是什么机器,都必须保证,每次移动的距离是speed的长度。

我们已经实现了根据用户的输入来移动英雄,但我们还可以在移动英雄时对其进行检查,以确定是否有其他事件发生。例如:英雄是否与怪物发生了碰撞——当英雄与怪物发生碰撞时,我们为玩家进行计分(monstersCaught加1)并重置游戏(调用reset函数)。

7. 渲染对象

// 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);

};

update函数相当于只是改变的值,而render函数则是绘制图案,当你能够看到你的行动时游戏才会变得更有趣,所以让我们在屏幕上绘制吧。首先我们将背景图片绘制到canvas,然后是英雄和怪物。注意顺序很重要,因为任何位于表层的图片都会将其下面的像素覆盖掉。

想一想,每次如果英雄的位置改变,那么我们会把所有的场景包括背景都重新绘制一次,那么你在界面上看到的就好像是英雄走了一步

接下来是文字,这有些不同,我们调用fillText函数显示玩家的分数。因为不需要复杂的动画或者对文字进行移动,所以只是绘制一下就ok了。

8. 游戏主循环

// 游戏主循环

var main = function () {

var now = Date.now();

var delta = now - then;

update(delta / 1000);

render();

then = now;

requestAnimationFrame(main);

};

var w = window;

requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;

游戏的主循环用来控制游戏流程。首先我们要获得当前的时间,这样我们才能计算时间差(自上次循环以来经过的时间)。然后计算modifier的值并交给update(需要将delta除以1000以将其转换为毫秒)。最后调用render并更新记录的时间。

游戏主循环是游戏中最重要的概念,无论游戏怎么变化,无非就是移动,消失。而移动消失,无非又是画布的重画,所以把移动或者消失的位置放在update函数里面,把画布重画放在render函数里面。而随着时间的变化,无非就是这两个函数函数一直在执行而已。

9. 开始游戏

var then = Date.now();

reset();

main();

快完成了,这是最后一段代码。首先调用reset来开始新游戏。(还记得吗,这会将英雄置中并随机安放怪物)。然后将起始时间保存到变量then中并启动游戏的主循环。

原文:http://www.cnblogs.com/18200345061-hjl/p/4120719.html

html游戏怎么做,HTML5 制做“游戏”的一个基本流程相关推荐

  1. 网页内置html5游戏,爽爆HTML5网页游戏!教你怎么精选浏览器

    HTML5的超强性能给人们提供了无尽的可能,首当其冲发挥HTML5性能的必然是网页游戏.在告别笨重的Flash之后,HTML5网页游戏会带给玩家不一样的体验,特别是HTML5可允许网页与硬件直接交互, ...

  2. html5社交游戏,怦怦:HTML5小游戏与社交的完美结合

    原标题:怦怦:HTML5小游戏与社交的完美结合 有一天,好朋友分享我一个好玩的小游戏,我一看就是现在很流行的H5小游戏,我打开他分享给我的链接进去游戏,还有排行榜的,就这样,这款叫"见缝插针 ...

  3. 菜鸟做HTML5小游戏 - 翻翻乐

    记录下开放过程.做小游戏开发,又要跨平台,flash又不支持iPhone,html5是最好的选择. 先看看最后效果: 好了,开始demo. 1.准备工作: 图片素材(省略...最后代码一起打包) 了解 ...

  4. 菜鸟做HTML5小游戏 - 刮刮乐

    继上篇翻翻乐之后,又来刮刮乐.还是先上效果图: 开始demo的世界: 1.css去绘制界面效果.(源码提供) 2.原理:要实现刮刮卡内容的出现,我用div做了背景层去显示刮出的内容结果[重点].中间C ...

  5. cs做html5网页游戏,《CS:GO》nexa:我终于领悟到该做些什么来让队伍取得胜利了...

    nexa在Minor结束后接受了StarLadder的采访.他领导的队伍CR4ZY在欧洲Minor败者决赛当中击败North,成功晋级即将到来的StarLadder Major Berlin 2019 ...

  6. Html5 Egret游戏开发 成语大挑战(一)开篇

    最近接触了Egret白鹭引擎,感觉非常好用,提供了各种各样的开发工具让开发者和设计者更加便捷,并且基于typescript语言开发省去了很多学习成本,对于我们这种掉微软坑许久的童鞋来说,确实很有吸引力 ...

  7. HTML5 2D游戏引擎研发系列 第五章

    HTML5 2D游戏引擎研发系列 第五章 <Canvas技术篇-画布技术-纹理集复杂动画> 作者:HTML5游戏开发者社区-白泽 转载请注明出处:http://html5gamedev.o ...

  8. HTML5 2D游戏引擎研发系列 第四章 Canvas技术篇-画布技术-基于手动切片动画

    作者:HTML5游戏开发者社区-白泽 转载请注明出处:http://html5gamedev.or HTML5 2D游戏引擎研发系列 第四章 <Canvas技术篇-画布技术-基于手动切片动画&g ...

  9. HTML5 2D游戏引擎研发系列 第一章

     HI,大家好,我是白泽,一名游戏设计师,一直专注各平台的2D游戏引擎研发,HTML5是我准备进入的新领域,我有个习惯,刚接触的新领域我都会习惯自己写一套游戏引擎,而不用第三方提供的,为了方便自己学习 ...

最新文章

  1. 「AutoML」激活函数如何进行自动学习和配置
  2. php ftp 分块下载,php ftp下载文件
  3. how does {accountID} binding work?
  4. .NET 6新特性试用 | System.Text.Json序列化代码自动生成
  5. Oracle不连续的值,如何实现查找上一条、下一条
  6. 数据结构与算法分析c++第四版_数据结构与算法 - 时空复杂度分析
  7. 手机端滚动屏幕加载更多
  8. mysql field id doesnt have a default value_为什么出现“Field ID'doesn't have a default value”?...
  9. Ubuntu18.04关闭zeitgeist-datahub自启动
  10. 浅谈React Hooks
  11. wordpress上传图片按时间重命名
  12. 基于Spark的电影推荐系统(推荐系统~3)
  13. Android 动画 Kotlin 教程
  14. 聚观早报 | 苏宁易购入驻美团外卖;今日头条接入抖音电商
  15. POJ Curling 2.0
  16. 计算机核心期刊的终审环节,7 本中文核心期刊投稿经验分享 总有一款适合你
  17. Snap 2020年第三季度收益电话会议记录
  18. 怎样阅读论文(台湾彭明辉)
  19. Faster R-CNN文章详细解读
  20. 那些年啊,那些事——一个程序员的奋斗史 ——92

热门文章

  1. eShopOnContainers 知多少[7]:Basket microservice
  2. Build 2018大会:.NET概述和路线图
  3. 处理ASP.NET Core中的HTML5客户端路由回退
  4. .NET 使用 RabbitMQ 图文简介
  5. .NET Core 跨平台发布(dotnet publish)
  6. goldengate mysql_使用GoldenGate实现MySQL到Oracle的数据实时同步
  7. mysql中局部变量说法正确的是_mysql全局变量和局部变量
  8. 将WebApiTestClient添加到ASP.NET Web API帮助页面
  9. Android之如何让Android studio编译更快
  10. linux之tmp文件夹