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

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

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

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

JavaScript的总体结构如下:

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

首先预定义一些变量

 var _keyA = _keyD = _keyW = _keyS = 0,  // 存储按键状态

     step = 8,                          // 飞机移动速率
w = 34, h = 44, // 飞机实际大小
planeX = 133, planeY = 356, // 飞机目前位置
planeSrc = "feiji.png", // 飞机素材位置
imgW = 177, imgH = 220, // 飞机源图尺寸 cw = 300, ch = 400, // 画布大小
canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");

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

先看画图的两个方法

 function drawPlane(x, y) {
var img = new Image();
img.src = planeSrc; // 飞机源图地址
img.onload = function() {
ctx.drawImage(img, 0, 0, imgW, imgH, planeX, planeY, w, h);
}
}
function drawEnemy(){
for(var a=0;a<cw;a+=10) {
for(var b=0;b<ch-300;b+=10) {
ctx.beginPath();
ctx.fillStyle = "orange";
ctx.strokeStyle = "black";
ctx.strokeRect(a, b, 10 ,10);
ctx.fillRect(a, b, 10, 10);
ctx.closePath();
}
}
}

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

接着,看两个键盘事件:

 window.document.onkeydown = function(evt){
evt = (evt) ? evt : window.event;
switch(evt.keyCode) {
case 65: // A
_keyA = 1;
break;
case 68: // D
_keyD = 1;
break;
case 87: // W
_keyW = 1;
break;
case 83: // S
_keyS = 1;
break;
}
}
window.document.onkeyup = function(evt){
evt = (evt) ? evt : window.event;
switch(evt.keyCode) {
case 65: // A
_keyA = 0;
break;
case 68: // D
_keyD = 0;
break;
case 87: // W
_keyW = 0;
break;
case 83: // S
_keyS = 0;
break;
}
}

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

飞机移动计时器如下:

 var planeMoveTimer = window.setInterval(function(){
if(_keyA||_keyD||_keyW||_keyS){
ctx.clearRect(planeX, planeY, w, h);
_keyA && (planeX-=step);
_keyD && (planeX+=step);
_keyW && (planeY-=step);
_keyS && (planeY+=step);
planeX>=0 || (planeX=0);
planeX<=(cw-w) || (planeX=cw-w);
planeY>=0 || (planeY=0);
planeY<=(ch-h) || (planeY=ch-h);
drawPlane(planeX, planeY);
}
}, 10);

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

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

然后是攻击计时器:

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

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

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

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

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

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

    时间:凌晨2:36 历时:两晚+半个下午 代码:约300行 这两天发烧,头痛脑壳昏的,没想到竟然还能有动力去做小游戏,其实这不是我第一次想要弄个俄罗斯方块,前几个星期的时候就尝试着去弄一个,然后被凌乱 ...

  2. 青瓷引擎之纯JavaScript打造HTML5游戏第二弹——《跳跃的方块》Part 10(排行榜界面&界面管理)

    继上一次介绍了<神奇的六边形>的完整游戏开发流程后(可点击这里查看),这次将为大家介绍另外一款魔性游戏<跳跃的方块>的完整开发流程. (点击图片可进入游戏体验) 因内容太多,为 ...

  3. 动手打造轻量web服务器(二)路由

    tomcat启动慢?自己动手打造轻量web服务器(一) 上篇讲了怎么做一个最简单的web服务器,这篇就是在上篇加上URL路由功能(什么是路由?) 首先,根据http获得请求行 val scanner ...

  4. 打造 html5 文件上传组件,实现进度显示及拖拽上传,支持秒传+分片上传+断点续传,兼容IE6+及其它标准浏览器

    老早就注册了博客园帐号,昨天才发现,连博客都没开,Github也是一样,深觉惭愧,赶紧潜个水压压惊`(*∩_∩*)′ 言归正传.大概许多人都会用到文件上传的功能,上传的库貌似也不少,比如(jQuery ...

  5. 一起动手打造个人娱乐级linux

    我们使用电脑,一直以来用的都是windows,但是对于像我这种爱折腾的人来说,尝试使用linux系统应该是一种不错的体验.说到linux,许多人可能都没听过,或者知道的人对它印象是这样的: 然而,li ...

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

    XWAMP并不打算打造一个多功能,零配置,方便调试的工具.XWAMP只是把原程序简单的组合在一起,利用CMD命令控制,真正的绿色版,只为了多学习点Windows + Apache + PHP + My ...

  7. 全栈开发——动手打造属于自己的直播间(Vue+SpringBoot+Nginx)

    前言 大学的学习时光临近尾声,感叹时光匆匆,三年一晃而过.同学们都忙着找工作,我也在这里抛一份简历吧,欢迎各位老板和猎手诚邀.我们进入正题.直播行业是当前火热的行业,谁都想从中分得一杯羹,直播养活了一 ...

  8. tomcat启动慢?自己动手打造轻量web服务器(一)

    废话少说,直接上代码. 编程语言:kotlin import java.net.ServerSocketimport java.net.Socket fun main(args:Array<St ...

  9. 自己动手打造基于 WKWebView 的混合开发框架(一)WKWebView 上手

    http://www.cocoachina.com/ios/20150911/13301.html 代码示例:https://github.com/johnlui/Swift-On-iOS/tree/ ...

随机推荐

  1. jQuery模糊选择

    属性字头选择器(Attribute Contains Prefix Selector) jQuery 属性字头选择器的使用格式是 jQuery(‘[attribute|=value]‘) ,例如 jQ ...

  2. [原]此程序专用来说明C++模板的用法

    #include using namespace std; //此程序专用来说明模版的使用 template void swap1(T& a,T& b){     T temp=a; ...

  3. wordpress教程之在非single.php页面调用文章的信息

    使用Wordpress的朋友可能遇到这样的问题,在非single.php页面中我们有时候想要调用当前文章的标题.内容等信息,而Wordpress在生成文章页的时候在各个页面中唯一不变的只有当前的文章I ...

  4. 安卓手机用-----Exchange Activesync---同步Gmail日历联系人

    微软Exchange Activesync是一个跨平台的移动设备同步协议 支持很多手机操作系统,比如诺基亚的塞班.黑莓的palm.WindowsMobile.Iphone.安卓等.这些手机上都可以用这 ...

  5. Keil C51汉字显示的bug问题(0xFD问题)

    一.缘起 这两天改进MCU的液晶显示方法,采用“即编即显”的思路,编写了一个可以直接显示字符串的程序.如程序调用disstr("我是你老爸");液晶屏上就会显示“我是你老爸”. 二 ...

  6. T-SQL 基于列的逻辑表达式 (CASE)

    CASE简介 基于列的逻辑表达式,其实就是CASE表达式.可以用在SELECT,UPDATE,DELETE,SET以及IN,WHERE,ORDER BY和HAVING子句之后.由于这里讲的是T-SQL ...

  7. SQL Server 2005中的分区表(五):添加一个分区

    所谓天下大事,分久必合,合久必分,对于分区表而言也一样.前面我们介绍过如何删除(合并)分区表中的一个分区,下面我们介绍一下如何为分区表添加一个分区. 为分区表添加一个分区,这种情况是时常会 发生的.比 ...

  8. CSS基础-引入方法,选择器,继承

    一.CSS引入方法:行内式.嵌入式.导入式.链接式. 1.行内式. 即:在标签的style属性中设定CSS样式. 例子:<div style="行内式</div> 2.嵌入 ...

  9. Linux系统编程(6)——文件系统

    计算机的文件系统是一种存储和组织计算机数据的方法,它使得对其访问和查找变得容易,文件系统使用文件和树形目录的抽象逻辑概念代替了硬盘和光盘等物理设备使用数据块的概念,用户使用文件系统来保存数据不必关心数 ...

  10. UESTC_树上战争 CDOJ 32

    给一棵树,如果树上的某个节点被某个人占据,则它的所有儿子都被占据,lxh和pfz初始时分别站在两个节点上,谁当前所在的点被另一个人占据,他就输了比赛,问谁能获胜. Input 输入包含多组数据 每组第 ...