自己动手打造html5星际迷航!

学习html5的canvas第三天,觉得还没过瘾,转眼就忘,于是趁着有空,准备弄个小游戏来玩!游戏应该需要注意性能,还有一些逻辑需要斟酌,我想还需要用户可修改性,也就是用户配置。好,开始我们简单但有趣的旅程吧——

想先看效果的,先跳转试玩一下吧!

第一步,当然需要一张画布

1 <canvas id="canvas" width="300" height="400">你的浏览器不支持Canvas</canvas>

JavaScript的总体结构如下:

var定义一些变量
planeMoveTimer飞机移动监听/计时器
attackEnemyTimer发射炮弹计时器
onkeydown监听
onkeyup监听
drawPlane画飞机
drawEnemy画敌人

首先预定义一些变量

 1 var _keyA = _keyD = _keyW = _keyS = 0,  // 存储按键状态
 2
 3     step = 8,                          // 飞机移动速率
 4     w = 34, h = 44,                  // 飞机实际大小
 5     planeX = 133, planeY = 356,      // 飞机目前位置
 6     planeSrc = "feiji.png",          // 飞机素材位置
 7     imgW = 177, imgH = 220,          // 飞机源图尺寸
 8
 9     cw = 300, ch = 400,  // 画布大小
10     canvas = document.getElementById("canvas"),
11     ctx = canvas.getContext("2d");

本游戏只用到一个外部资源,就是那张图片,获取地址请访问本文底部给出的项目GitHub位置链接。跳转

先看画图的两个方法

 1 function drawPlane(x, y) {
 2     var img = new Image();
 3     img.src = planeSrc;  // 飞机源图地址
 4     img.onload = function() {
 5         ctx.drawImage(img, 0, 0, imgW, imgH, planeX, planeY, w, h);
 6     }
 7 }
 8 function drawEnemy(){
 9     for(var a=0;a<cw;a+=10) {
10         for(var b=0;b<ch-300;b+=10) {
11             ctx.beginPath();
12             ctx.fillStyle = "orange";
13             ctx.strokeStyle = "black";
14             ctx.strokeRect(a, b, 10 ,10);
15             ctx.fillRect(a, b, 10, 10);
16             ctx.closePath();
17         }
18     }
19 }

飞机的图片一定要在onload()方法里才能把飞机画出来,目前的敌人还是一堆橙色的不会动的砖头,通过遍历在画布的顶端把它们画出来。

接着,看两个键盘事件:

 1 window.document.onkeydown = function(evt){
 2     evt = (evt) ? evt : window.event;
 3     switch(evt.keyCode) {
 4         case 65:  // A
 5             _keyA = 1;
 6             break;
 7         case 68:  // D
 8             _keyD = 1;
 9             break;
10         case 87:  // W
11             _keyW = 1;
12             break;
13         case 83:  // S
14             _keyS = 1;
15             break;
16     }
17 }
18 window.document.onkeyup = function(evt){
19     evt = (evt) ? evt : window.event;
20     switch(evt.keyCode) {
21         case 65:  // A
22             _keyA = 0;
23             break;
24         case 68:  // D
25             _keyD = 0;
26             break;
27         case 87:  // W
28             _keyW = 0;
29             break;
30         case 83:  // S
31             _keyS = 0;
32             break;
33     }
34 }

至于为什么要在两个事件里设置变量_keyA、_keyD、_keyW、_keyS,而不是直接触发画图事件,原因是——同时长按两个键时,无法同时触发事件,先按者只触发一次,只有后按者在按着键的时候才能一直触发事件,简单点来说,如果我想要向左上角移动,同时按下A和W,假设A比W慢了一点点,即时很微小,那么飞机的移动路径是先上移一步然后一直向左移动,这显然不是我想要的,我用4个变量来存储按键的状态,按下键的时候,设置其状态为1,在按键起来的时候,设置其状态为0,然后我们用计时器来不断地读这些键的状态并及时更新飞机的状态。

飞机移动计时器如下:

 1 var planeMoveTimer = window.setInterval(function(){
 2     if(_keyA||_keyD||_keyW||_keyS){
 3         ctx.clearRect(planeX, planeY, w, h);
 4         _keyA && (planeX-=step);
 5         _keyD && (planeX+=step);
 6         _keyW && (planeY-=step);
 7         _keyS && (planeY+=step);
 8         planeX>=0 || (planeX=0);
 9         planeX<=(cw-w) || (planeX=cw-w);
10         planeY>=0 || (planeY=0);
11         planeY<=(ch-h) || (planeY=ch-h);
12         drawPlane(planeX, planeY);
13     }
14 }, 10);

ctx.clearRect()用来清除原来位置的飞机,为绘制飞机的下一状态做准备,但是有一个很大的问题,它是直接清除整块的,要是游戏有背景,有交叠,那不是要把这些不是飞机的东西也一并清空了?恕我愚昧,暂时不考虑这个问题。

通过判断按键状态,每次移动的步距为预先设置的step,并做好边界处理。

然后是攻击计时器:

 1 var attackEnemyTimer = window.setInterval(function(){
 2     var cannonX = planeX+Math.floor(w/2);  // 炮口X轴位置
 3     var cannonY = planeY;  // 炮口Y轴位置
 4     var tmpTimer = window.setInterval(function(){  // 每颗炮弹的移动计时器
 5         ctx.clearRect(cannonX-1, cannonY-3, 2, 3);
 6         cannonY -= 3;  // 炮弹步距
 7         if(cannonY<0){
 8             // 炮弹的贯透效果
 9             ctx.beginPath();
10             ctx.moveTo(cannonX, 100);  // 100为enemy的最低位置
11             ctx.strokeStyle = "white";
12             ctx.lineWidth = "4";  // 模拟不规则毁坏,暂时尚未没实现
13             ctx.lineTo(cannonX, 0);
14             ctx.stroke();
15             ctx.closePath();
16             window.clearInterval(tmpTimer);  // 清除该炮弹的计时器
17         }
18         ctx.clearRect(cannonX-1, cannonY-3, 2, 3);
19         ctx.beginPath();
20         ctx.fillStyle="red";
21         ctx.fillRect(cannonX-1, cannonY-3, 2, 3);  // 炮弹大小:2X3
22         ctx.closePath();
23     }, 0);
24 }, 500);

每0.5s发射一颗炮弹,每颗炮弹又单独设置一个计时器,以便控制,炮弹的移动我也是采用先擦后画的方式,由于炮弹移动也有步距,所谓炮弹贯透效果就是直接画一条颜色跟背景色一样的直线而已。试着修改炮弹步距可以调节炮弹的移动速度,也可以调节炮弹的尺寸。

最后一步了,还差点什么,一开始就要画好敌人和飞机啦!

1 drawPlane();
2 drawEnemy();

大功告成!还想继续优化增加可玩性的,但实在是没时间弄了,还有很多其他的东西要学,所以这个游戏就先这样啦!是不是很简单!哈哈,囧了吧,标题太诱惑人,没办法!

其他:

在线试玩:http://xzh-loop.github.io/Manji/lab/html5game/Plane.html

访问这个项目的GitHub位置:https://github.com/xzh-loop/Manji/tree/gh-pages/lab/html5game

访问我的GitHub Pages:http://xzh-loop.github.io/

时间: 2025-01-07 18:39:41

自己动手打造html5星际迷航!的相关文章

自给自足:动手打造html5俄罗斯方块

时间:凌晨2:36 历时:两晚+半个下午 代码:约300行 这两天发烧,头痛脑壳昏的,没想到竟然还能有动力去做小游戏,其实这不是我第一次想要弄个俄罗斯方块,前几个星期的时候就尝试着去弄一个,然后被凌乱的代码带进了无尽的深渊,最后忍痛把几天的代码一键删除.这次从头梳理思路,重新设计,结果也正好印证了某人的一句话:有时候重新开始比修bug更省事. 在正文开始之前还要啰嗦一下,标题中所谓自给自足,是在没有参考任何设计思路的前提下去开发这游戏的,你可能会不解,如果参考优秀的思路,岂不是事半功倍,当然,参

自己动手打造属于自己的智能家居(二)

上篇讲完了手机如何连接智能主机,这篇开始讲解智能主机如何去控制家中各个设备.这篇会写的比较详细,涉及到的基本知识也会讲解,意在让大家明白里面的原理. 下面我们把家里的设备分一下类:(这里写的一些典型的设备,等明白原理后对于其他的设备,也可以自己去添加了) 第一类:电视.空调 第二类:家里的各种灯 第三类:热水器.电饭煲 第四类:台灯 第五类:窗帘 ================================详细讲解分割线============================== 一.第一类

自己动手打造ajax图片上传

今天笔者需要一款图片上传插件,但是网上没有提供一款符合自己需求且好用的.于是就自己动手写了一个. 方法1,仅使用jquery代码,不用第三方插件.代码如下 <p> <label>上传图片</label> <input class="ke-input-text" type="text" id="url" value="" readonly="readonly" /&g

自己动手打造属于自己的智能家居--答疑篇(四)

前面写了三篇关于智能家居的文章,真的没有想到这么多的人对这个感兴趣,对于大家的留言本来准备一一回复的,后来想了想,还是再专门写一篇答疑篇吧,以表达对大家辛勤回复浓浓的爱意吧. 疑问一:什么技术都会有缺陷,这个撇开不谈.只是想问,如果客厅.卧室都有电视空调要控制怎么实现遥控? 答:由于电视和空调都是红外控制的,红外无法穿墙,所以要实现控制只能再增加一个智能主机,或者用射频转红外的装置(不推荐,第一这种装置不太稳定,第二是买这种装置还需要花钱,不合算啊) 疑问二:搂主没有说具体如何做啊?求截图!!求

自己动手打造工具系列之自动刷新简历

0×00 背景 话说搞安全的大佬们都非常忙,自己在一步一步成长中无暇顾及其他琐碎的事情,比如让猎头注意到各位大佬.如何让猎头和大厂注意到自己呢?第一.提高自己在整个行业的曝光度:第二.定时刷新自己的简历:还有第三,第四等等,各位发挥脑洞.针对第一点,很多大佬各有自己的办法,但是针对第二点其实我们有全自动化的解决方案,可以为自己相对地节约点时间.小弟今天就带来自己动手打造工具系列之自动刷新简历.本文主要是针对喜欢写工具的童鞋提供一些思路,并一步一步地分析思路和方法,起一个抛砖引玉的作用吧. 0×0

扔掉windows,一起动手打造个人娱乐级linux,我们不用盗版系统了!

我们使用电脑,一直以来用的都是盗版windows,对于想不用盗版的人来说有两种方法,1.土豪直接花钱买,2.对于我这种屌丝学生党,尝试一下linux是一个不错的选择.说到linux,许多人可能都没听过,或者知道的人对它印象是这样的: 然而,linux发展这么久,桌面应用也已经发展得非常成熟了,现在我们linux可以是这样的: ubuntu 16.04 archlinux gentoo linux fedora 很炫有木有,其实这样的linux已经是很普通的了,只需要我们动手去做,大胆去做,就能弄

自己动手打造WEB服务器 Windows + Apache + PHP + MySQL

XWAMP并不打算打造一个多功能,零配置,方便调试的工具.XWAMP只是把原程序简单的组合在一起,利用CMD命令控制,真正的绿色版,只为了多学习点Windows + Apache + PHP + MySQL相关的知识. 官方网站:http://www.xwamp.com/. Windows下的Apache+Mysql/MariaDB+Perl/PHP/Python,一组常用来搭建动态网站或者服务器的开源软件,本身都是各自独立的程序,但是因为常被放在一起使用,拥有了越来越高的兼容度,共同组成了一个

动手打造自己的跨语言异构模块通信解决方案

目前主流的跨语言异构模块通信方案有很多种,比如: 1.跨语言的RPC调用(Apache Thrift):它是Facebook贡献给Apache基金会的开源项目,旨在构建跨语言平台的通信方案.目前它支持非常多种语言,其中当然包括C/C++和Java.Thrift内置一个语言编译器,可以根据Thrift的语法规范,编译生成指定语言的RPC调用模块,功能也是非常的强大.Thrift的语法规范里面定义了数据类型.数据模块结构,有点类似WebService里面的WSDL文件.通过Thrift,我们就可以实

用CSS3打造HTML5的Logo

本文将向大家介绍如何利用CSS3的新样式属性制作一个HTML5的Logo.我们先来看看最终的效果: 不要怀疑,上面的logo完全由HTML+CSS实现.我们将logo划分为盾形.数字5和辐射背景三大部分,下面将分别实现每个部分. 盾形 盾形在外形上是左右对称的,因此我们可先完成左半边,右半边可复制过来再修改一些参数.左半边准备用三个div实现,其中有两个div需要倾斜一定的角度来实现盾形的左边和底边,这里使用transform的skew来完成.代码如下(注意,这里只使用了webkit前缀的样式,