接着上一篇(http://www.cnblogs.com/zhouhuan/p/H5_tankgame3.html),这一篇建造敌人的坦克。
  思路是,基于可扩展性和性能等方面的考虑,用构造函数改造之前的部分代码,再在这个基础上,实例化出来不同的坦克。
 
  1.一开始的两个步骤不变
//封装一个获取绘图环境的函数
function getCxt(){
var myCanvas = document.getElementById('floor'),
myContext = myCanvas.getContext('2d');
return myContext;
}
//为了防止重复地获取节点影响性能,我们将获取到的绘图环境(也就是画笔对象)存起来
var oCxt = getCxt();
  2.接下来对画坦克的函数进行适当改写,因为函数里重复代码过多,同时,增加两个颜色的参数,方便后面画出不同的坦克:
//封装一个画坦克的函数,传两个参数x,y,分别代表左上角的横纵坐标
//再增加一个参数dir来表示方向 上下左右分别传"u" "d" "l" "r"
//再增加两个参数color1与color2,用来表示坦克身上的两种颜色,方便造出不同的坦克
function drawTank(x,y,dir,color1,color2){
switch(dir){
case "u":
case "d":
oCxt.fillStyle = color1;
oCxt.fillRect(x,y,20,65);
oCxt.fillRect(x+70,y,20,65);
oCxt.fillRect(x+23,y+10,44,50);
oCxt.fillStyle = color2;
oCxt.beginPath();
oCxt.arc(x+45,y+35,16,0,2*Math.PI,false);
oCxt.closePath();
oCxt.fill();
oCxt.strokeStyle = color2;
oCxt.lineWidth = "8.0";
oCxt.moveTo(x+45,y+35);
if(dir == "u"){
oCxt.lineTo(x+45,y-25);
}else if(dir == "d"){
oCxt.lineTo(x+45,y+95);
}
oCxt.stroke();
break;
case "l":
case "r":
oCxt.fillStyle = color1;
oCxt.fillRect(x,y,65,20);
oCxt.fillRect(x,y+70,65,20);
oCxt.fillRect(x+10,y+23,50,44);
oCxt.fillStyle = color2;
oCxt.beginPath();
oCxt.arc(x+35,y+45,16,0,2*Math.PI,false);
oCxt.closePath();
oCxt.fill();
oCxt.strokeStyle = color2;
oCxt.lineWidth = "8.0";
oCxt.moveTo(x+35,y+45);
if(dir == "l"){
oCxt.lineTo(x-25,y+45);
}else if(dir == "r"){
oCxt.lineTo(x+95,y+45);
}
oCxt.stroke();
}
}
  3.又考虑到函数传参过多,使用函数的话比较麻烦,所以对函数进行进一步的封装,干脆传一个对象进去,就成了下面这样:
function drawTank(tankName){
switch(tankName.dir){
case "u":
case "d":
oCxt.fillStyle = tankName.color1;
oCxt.fillRect(tankName.x,tankName.y,20,65);
oCxt.fillRect(tankName.x+70,tankName.y,20,65);
oCxt.fillRect(tankName.x+23,tankName.y+10,44,50);
oCxt.fillStyle = tankName.color2;
oCxt.beginPath();
oCxt.arc(tankName.x+45,tankName.y+35,16,0,2*Math.PI,false);
oCxt.closePath();
oCxt.fill();
oCxt.strokeStyle = tankName.color2;
oCxt.lineWidth = "8.0";
oCxt.moveTo(tankName.x+45,tankName.y+35);
if(tankName.dir == "u"){
oCxt.lineTo(tankName.x+45,tankName.y-25);
}else if(tankName.dir == "d"){
oCxt.lineTo(tankName.x+45,tankName.y+95);
}
oCxt.stroke();
break;
case "l":
case "r":
oCxt.fillStyle = tankName.color1;
oCxt.fillRect(tankName.x,tankName.y,65,20);
oCxt.fillRect(tankName.x,tankName.y+70,65,20);
oCxt.fillRect(tankName.x+10,tankName.y+23,50,44);
oCxt.fillStyle = tankName.color2;
oCxt.beginPath();
oCxt.arc(tankName.x+35,tankName.y+45,16,0,2*Math.PI,false);
oCxt.closePath();
oCxt.fill();
oCxt.strokeStyle = tankName.color2;
oCxt.lineWidth = "8.0";
oCxt.moveTo(tankName.x+35,tankName.y+45);
if(tankName.dir == "l"){
oCxt.lineTo(tankName.x-25,tankName.y+45);
}else if(tankName.dir == "r"){
oCxt.lineTo(tankName.x+95,tankName.y+45);
}
oCxt.stroke();
}
}
  4.接下来不再专门创建一个myTank对象来存储相关的属性和方法,而是采用构造函数的方法,写好构造函数之后,创建对象的时候new出来并传参即可,如下:
//使用构造函数来创建对象
function Tank(x,y,dir,color1,color2){
this.x = x;
this.y = y;
this.dir = dir;
this.step = 3,
this.color1 = color1;
this.color2 = color2;
this.turnUp = function(){
if((this.y-25) >= 0){
this.y -= this.step;
this.dir = "u";
}
};
this.turnDown = function(){
if((this.y+90) <= 500){
this.y += this.step;
this.dir = "d";
}
};
this.turnLeft = function(){
if((this.x-25) >= 0){
this.x -= this.step;
this.dir = "l";
}
};
this.turnRight = function(){
if((this.x+90) <= 800){
this.x += this.step;
this.dir = "r";
}
};
}
//创建我的坦克时new出来并传参
var myTank = new Tank(350,400,"u","#542174","#FCB827");
  5.接下来创建敌人的坦克,我的想法是,敌人的坦克是多个,如果一个一个地new出来会比较麻烦,而且可扩展性比较差,因为如果要增加几个或者减少几个的话就要大面积地改动代码,所以可以做成一个数组,这里先做三个:
//创建敌人的坦克,有多个所以做成数组,再将数组每一项new出来并传参即可
//这里以骑士队的主色建造坦克
var enemyTank = new Array();
for(var i=0; i<3; i++){
enemyTank[i] = new Tank(240*(i+0.45),60,"d","#EBB227","#780910");
}
  前两个参数x和y也是一点点试出来的,将坦克调整到合适的位置即可。
  其实接下来也可以不用先画一个坦克出来,因为间歇调用的间隔时间是100ms,很短,几乎看不出来,所以可以只在更新战场的函数里画坦克,外面就不用了:
//封装一个更新战场的函数
function updateFloor(){
oCxt.clearRect(0,0,800,500); //更新之前先清除画布
drawTank(myTank);
for(var i=0; i<enemyTank.length; i++){
drawTank(enemyTank[i]); //循环一下把每一个敌人造出来
}
}
//设置一个间歇调用的函数,每隔100ms更新一下战场
setInterval(function(){
updateFloor();
},100);
  6.响应玩家的操作指令一步也没有变化:
//响应玩家的操作指令
window.onkeydown = function(eve){
switch(eve.keyCode){
case 38:
case 87:
myTank.turnUp();
break;
case 40:
case 83:
myTank.turnDown();
break;
case 37:
case 65:
myTank.turnLeft();
break;
case 39:
case 68:
myTank.turnRight();
}
};
  到这一步就已经可以建造出敌人的坦克(并自由控制自己的坦克)了,运行之后结果如下:

  7.最终代码:
//封装一个获取绘图环境的函数
function getCxt(){
var myCanvas = document.getElementById('floor'),
myContext = myCanvas.getContext('2d');
return myContext;
}
//为了防止重复地获取节点影响性能,我们将获取到的绘图环境(也就是画笔对象)存起来
var oCxt = getCxt(); //封装一个画坦克的函数,传两个参数x,y,分别代表左上角的横纵坐标
//再增加一个参数dir来表示方向 上下左右分别传"u" "d" "l" "r"
//再增加两个参数color1与color2,用来表示坦克身上的两种颜色,方便造出不同的坦克
//对函数进一步封装,尽量让使用变得简单
function drawTank(tankName){
switch(tankName.dir){
case "u":
case "d":
oCxt.fillStyle = tankName.color1;
oCxt.fillRect(tankName.x,tankName.y,20,65);
oCxt.fillRect(tankName.x+70,tankName.y,20,65);
oCxt.fillRect(tankName.x+23,tankName.y+10,44,50);
oCxt.fillStyle = tankName.color2;
oCxt.beginPath();
oCxt.arc(tankName.x+45,tankName.y+35,16,0,2*Math.PI,false);
oCxt.closePath();
oCxt.fill();
oCxt.strokeStyle = tankName.color2;
oCxt.lineWidth = "8.0";
oCxt.moveTo(tankName.x+45,tankName.y+35);
if(tankName.dir == "u"){
oCxt.lineTo(tankName.x+45,tankName.y-25);
}else if(tankName.dir == "d"){
oCxt.lineTo(tankName.x+45,tankName.y+95);
}
oCxt.stroke();
break;
case "l":
case "r":
oCxt.fillStyle = tankName.color1;
oCxt.fillRect(tankName.x,tankName.y,65,20);
oCxt.fillRect(tankName.x,tankName.y+70,65,20);
oCxt.fillRect(tankName.x+10,tankName.y+23,50,44);
oCxt.fillStyle = tankName.color2;
oCxt.beginPath();
oCxt.arc(tankName.x+35,tankName.y+45,16,0,2*Math.PI,false);
oCxt.closePath();
oCxt.fill();
oCxt.strokeStyle = tankName.color2;
oCxt.lineWidth = "8.0";
oCxt.moveTo(tankName.x+35,tankName.y+45);
if(tankName.dir == "l"){
oCxt.lineTo(tankName.x-25,tankName.y+45);
}else if(tankName.dir == "r"){
oCxt.lineTo(tankName.x+95,tankName.y+45);
}
oCxt.stroke();
}
}
//使用构造函数来创建对象
function Tank(x,y,dir,color1,color2){
this.x = x;
this.y = y;
this.dir = dir;
this.step = 3,
this.color1 = color1;
this.color2 = color2;
this.turnUp = function(){
if((this.y-25) >= 0){
this.y -= this.step;
this.dir = "u";
}
};
this.turnDown = function(){
if((this.y+90) <= 500){
this.y += this.step;
this.dir = "d";
}
};
this.turnLeft = function(){
if((this.x-25) >= 0){
this.x -= this.step;
this.dir = "l";
}
};
this.turnRight = function(){
if((this.x+90) <= 800){
this.x += this.step;
this.dir = "r";
}
};
}
//实例化我的坦克时new出来并传参
var myTank = new Tank(350,400,"u","#542174","#FCB827");
//实例化敌人的坦克,有多个所以做成数组,再将数组每一项new出来并传参即可
//这里以骑士队的主色画坦克
var enemyTank = new Array();
for(var i=0; i<3; i++){
enemyTank[i] = new Tank(240*(i+0.45),60,"d","#EBB227","#780910");
} //封装一个更新战场的函数
function updateFloor(){
oCxt.clearRect(0,0,800,500); //更新之前先清除画布
drawTank(myTank);
for(var i=0; i<enemyTank.length; i++){
drawTank(enemyTank[i]); //循环一下把每一个敌人造出来
}
} //设置一个间歇调用的函数,每隔100ms更新一下战场
setInterval(function(){
updateFloor();
},100); //响应玩家的操作指令
window.onkeydown = function(eve){
switch(eve.keyCode){
case 38:
case 87:
myTank.turnUp();
break;
case 40:
case 83:
myTank.turnDown();
break;
case 37:
case 65:
myTank.turnLeft();
break;
case 39:
case 68:
myTank.turnRight();
}
};
 

H5 canvas建造敌人坦克的更多相关文章

  1. 使用H5 canvas画一个坦克

      具体步骤如下:   1. 首先做出绘图区,作为坦克的战场   <canvas id="floor" width="800px" height=&quo ...

  2. H5坦克大战之【建造敌人的坦克】

      公司这几天在准备新版本的上线,今天才忙里偷闲来写这篇博客.接着上一篇的"H5坦克大战之[玩家控制坦克移动2]"(http://www.cnblogs.com/zhouhuan/ ...

  3. H5 canvas绘制出现模糊的问题

    在之前做移动端小游戏幸运转盘.九宫格转盘,使用到了 canvas ,也是第一次在项目中使用 canvas 来实现. 近期测试人员反应 canvas 绘制的内容太模糊,心想着用 canvas 绘制出来的 ...

  4. h5 canvas 小球移动

    h5 canvas 小球移动 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  5. h5 canvas 画图

    h5 canvas 画图 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...

  6. H5 canvas控制坦克移动2

    接着上一篇(http://www.cnblogs.com/zhouhuan/p/H5_tankgame2.html),这篇主要修复两个bug,第一,玩家按下方向键时,坦克的炮筒应该指向相应的方向,并向 ...

  7. H5 canvas控制坦克移动

    接着上一篇(http://www.cnblogs.com/zhouhuan/p/H5_tankgame.html),这一篇研究一下怎么响应玩家的操作让坦克进行相应的移动.   1. 了解keydown ...

  8. HTML5-坦克大战一画出敌人坦克并让自己的坦克可以发子弹的功能(二)

    上一篇博客只画出了,一个坦克,并让其可以上下左右移动,这篇博客将画出敌人的坦克,并让自己的坦克可以发子弹,但是还不是尽善尽美,还有一些问题,将会在下篇博客说明: html代码: <!DOCTYP ...

  9. H5 canvas填充文字自动换行

    canvas是H5中非常重要,非常常用,也是非常强大的一个新标签,美中不足的事,canvas中没没有自动换行的属性,我的第一反应是,字符串截取,然后计算每行的距离来实现自动换行.. 然后百度了一下,已 ...

随机推荐

  1. BFS+状态压缩DP+二分枚举+TSP

    http://acm.hdu.edu.cn/showproblem.php?pid=3681 Prison Break Time Limit: 5000/2000 MS (Java/Others)   ...

  2. [ASP.NET 大牛之路]03 - C#高级知识点概要(2) - 线程和并发

    目录: 1.线程简单使用 2.并发和异步的区别 3.并发控制—锁 4.线程的通信机制 5.线程池中的线程 6.案例:支持并发的异步日志组件 7.结束 1.线程的简单使用---------------- ...

  3. 6.IIs部署与发布

    A.网站的发布步骤: 1.首先要选择要发布的网站(即项目里的网站)也就是代码. 2.左键选择发布. 3.配置文件:Web.congig. 4.连接:publis method:File System, ...

  4. 转载:隐式Intent

    一.隐式意图介绍 显式意图我们前面已经提到,形如: Intent intent = new Intent(); intent.setClass(this,Other.class); //此句表示显式意 ...

  5. 小米范工具系列之四:小米范HTTP批量发包器

    最新版本1.3,下载地址:http://pan.baidu.com/s/1c1NDSVe  文件名httpsender . 此工具使用java 1.8以上版本运行. 小米范HTTP批量发包器的主要功能 ...

  6. java-mybaits-00103-入门程序原生的【查、增、删、改】

    一.需求 实现以下功能: 根据用户id查询一个用户信息 根据用户名称模糊查询用户信息列表 添加用户 更新用户 删除用户 二.具体步骤 1.增加pom引用 2.增加log4j.properties # ...

  7. java 多线程 day18 ThreadPoolExecutor

    http://blog.csdn.net/lipc_/article/details/52025993 https://www.cnblogs.com/trust-freedom/p/6681948. ...

  8. python模块之xlrd(excl调用模块)

    一.安装xlrd模块 到python官网下载http://pypi.python.org/pypi/xlrd模块安装,前提是已经安装了python 环境. 二.使用介绍 1.导入模块 import x ...

  9. python多线程为什么不能利用多核cpu

    GIL 与 Python 线程的纠葛 GIL 是什么东西?它对我们的 python 程序会产生什么样的影响?我们先来看一个问题.运行下面这段 python 程序,CPU 占用率是多少? # 请勿在工作 ...

  10. Centos7 Zabbix3.2安装

    实验环境: 阿里云 [zabbix@miyan ~]$ cat /etc/redhat-release CentOS Linux release (Core) 不得不说,官方文档确实强大 1.官方文档 ...