[置顶] 小强的HTML5移动开发之路(9)——坦克大战游戏3
上一篇我们创建了敌人的坦克和自己的坦克,接下来就应该让坦克发子弹了,我们下面来看一下如何让我们的坦克发出子弹。
前面我们用面向对象的思想对Tank进行了封装,又利用对象冒充实现了我们的坦克和敌人的坦克,仿照这种方式我们是不是也应该封装一个Bullet,答案是肯定的。好吧,那么我们再想想这个Bullet"类“都应该封装什么东西呢?位置应该有吧、子弹飞行的方向应该有吧、飞行的速度也应该有吧、自己飞出去的动作应该有吧。好啦,大概就这些,封装后的Bulle”t类“如下:
//子弹类
function Bullet(x,y,direct,speed){
this.x=x;
this.y=y;
this.speed=speed;
this.direct=direct;
this.timer=null;
this.run=function(){
switch(this.direct){
case 0:
this.y-=this.speed;
break;
case 1:
this.x+=this.speed;
break;
case 2:
this.y+=this.speed;
break;
case 3:
this.x-=this.speed;
break;
} }
}
我们已经创建好子弹的模型了,下面就用我们的坦克创造子弹将子弹发出去,在Hero类中添加shotEnemy方法。
//定义一个Hero类
function Hero(x,y,direct,color){
//下面两句话的作用是通过对象冒充达到继承的效果
this.tank=Tank;
this.tank(x,y,direct,color);
//射击敌人函数
this.shotEnemy=function(){
switch(this.direct){
case 0:
heroBullet=new Bullet(this.x+10,this.y,this.direct,1);
break;
case 1:
heroBullet=new Bullet(this.x+30-4,this.y+10+4,this.direct,1);
break;
case 2:
heroBullet=new Bullet(this.x+10,this.y+30,this.direct,1);
break;
case 3:
heroBullet=new Bullet(this.x-4,this.y+10+4,this.direct,1);
break;
}
//把这个子弹放入数组中——》push函数
//调用我们子弹的run
//var timer=window.setInterval("heroBullet.run()",50);
//heroBullet.timer=timer;
heroBullets.push(heroBullet);
var timer=window.setInterval("heroBullets["+(heroBullets.length-1)+"].run()",50);
heroBullets[heroBullets.length-1].timer=timer; }
}
再在按键监听函数中添加一个监听发射子弹的键“J"
case 74: //J :发子弹
hero.shotEnemy();
break;
好了我们来试着发射一下子弹吧!
子弹怎么只能发一颗,而且越发越快,这是怎么回事呢?再看看我们上面写的代码,原来我们的子弹一旦发出去就不能停止了,虽然跑出了我们的”战场“但是还是在朝一个方向跑,一旦发第二颗子弹第一颗子弹就会由于重新刷新界面没有重绘子弹而消失。好了既然知道原因了下面我们判断一下子弹是否出界,然后给子弹一个状态isLive(这个状态标记子弹是否存在,如果不存在则在重绘子弹的时候不再重绘),修改后的代码如下:
//子弹类
function Bullet(x,y,direct,speed){
this.x=x;
this.y=y;
this.speed=speed;
this.direct=direct;
this.timer=null;
this.isLive=true;
this.run=function(){
//判断子弹是否已经到边界了
if(this.x<=0||this.x>=400||this.y<=0||this.y>=300){
//子弹要停止
window.clearInterval(this.timer);
//子弹死亡
this.isLive=false;
}else{
//可以去修改坐标
switch(this.direct){
case 0:
this.y-=this.speed;
break;
case 1:
this.x+=this.speed;
break;
case 2:
break;
}
}
}
}
如果子弹超出了canvas的范围则将isLive属性该为false
然后我们在前面的刷新界面函数中添加一个刷新子弹函数
//定时刷新我们的作战区(定时重绘)
//自己的坦克,敌人坦克,子弹,炸弹,障碍物
function flashTankMap(){
//把画布清理
cxt.clearRect(0,0,400,300);
//我的坦克
drawTank(hero);
//我的子弹
drawHeroBullet();
//敌人的坦克
for(var i=0;i<3;i++){
drawTank(enemyTanks[i]);
}
}
//画出自己的子弹
function drawHeroBullet(){
for(var i=0;i<heroBullets.length;i++){
var heroBullet=heroBullets[i];
if(heroBullet!=null&&heroBullet.isLive){
cxt.fillStyle="#FEF26E";
cxt.fillRect(heroBullet.x,heroBullet.y,2,2);
}
}
}
可以看到上面的drawHeroBullet中判断了子弹的isLive属性。
看看运行结果吧

全部源代码如下:
tankGame06.js
//为了编程方便,我们定义两个颜色数组
var heroColor=new Array("#BA9658","#FEF26E");
var enemyColor=new Array("#00A2B5","#00FEFE"); //子弹类
function Bullet(x,y,direct,speed){
this.x=x;
this.y=y;
this.speed=speed;
this.direct=direct;
this.timer=null;
this.isLive=true;
this.run=function(){
//判断子弹是否已经到边界了
if(this.x<=0||this.x>=400||this.y<=0||this.y>=300){
//子弹要停止
window.clearInterval(this.timer);
//子弹死亡
this.isLive=false;
}else{
//可以去修改坐标
switch(this.direct){
case 0:
this.y-=this.speed;
break;
case 1:
this.x+=this.speed;
break;
case 2:
this.y+=this.speed;
break;
case 3:
this.x-=this.speed;
break;
}
}
}
} //定义一个Tank类(基类)
function Tank(x,y,direct,color){
this.x=x;
this.y=y;
this.speed=1;
this.direct=direct;
this.color=color;
//上移
this.moveUp=function(){
this.y-=this.speed;
this.direct=0;
}
//右移
this.moveRight=function(){
this.x+=this.speed;
this.direct=1;
}
//下移
this.moveDown=function(){
this.y+=this.speed;
this.direct=2;
}
//左移
this.moveLeft=function(){
this.x-=this.speed;
this.direct=3;
}
} //定义一个Hero类
function Hero(x,y,direct,color){
//下面两句话的作用是通过对象冒充达到继承的效果
this.tank=Tank;
this.tank(x,y,direct,color);
//设计敌人函数
this.shotEnemy=function(){
switch(this.direct){
case 0:
heroBullet=new Bullet(this.x+10,this.y,this.direct,1);
break;
case 1:
heroBullet=new Bullet(this.x+30-4,this.y+10+4,this.direct,1);
break;
case 2:
heroBullet=new Bullet(this.x+10,this.y+30,this.direct,1);
break;
case 3:
heroBullet=new Bullet(this.x-4,this.y+10+4,this.direct,1);
break;
}
//把这个子弹放入数组中——》push函数
//调用我们子弹的run
//var timer=window.setInterval("heroBullet.run()",50);
//heroBullet.timer=timer;
heroBullets.push(heroBullet);
var timer=window.setInterval("heroBullets["+(heroBullets.length-1)+"].run()",50);
heroBullets[heroBullets.length-1].timer=timer; }
} //定义一个EnemyTank类
function EnemyTank(x,y,direct,color){
this.tank=Tank;
this.tank(x,y,direct,color);
} //绘制坦克
function drawTank(tank){
//考虑方向
switch(tank.direct){
case 0: //向上
case 2: //向下
//设置颜色
cxt.fillStyle=tank.color[0];
//左边的矩形
cxt.fillRect(tank.x,tank.y,5,30);
//右边的矩形
cxt.fillRect(tank.x+17,tank.y,5,30);
//画中间的矩形
cxt.fillRect(tank.x+6,tank.y+5,10,20);
//画出坦克的盖子
cxt.fillStyle=tank.color[1];
cxt.arc(tank.x+11,tank.y+15,5,0,Math.PI*2,true);
cxt.fill();
//画出炮筒
cxt.strokeStyle=tank.color[1];
cxt.lineWidth=1.5;
cxt.beginPath();
cxt.moveTo(tank.x+11,tank.y+15);
if(tank.direct==0){ //只是炮筒的方向不同
cxt.lineTo(tank.x+11,tank.y);
}else{
cxt.lineTo(tank.x+11,tank.y+30);
}
cxt.closePath();
cxt.stroke();
break;
case 1:
case 3:
//设置颜色
cxt.fillStyle="#BA9658";
//上边的矩形
cxt.fillRect(tank.x-4,tank.y+4,30,5);
//下边的矩形
cxt.fillRect(tank.x-4,tank.y+17+4,30,5);
//画中间的矩形
cxt.fillRect(tank.x+5-4,tank.y+6+4,20,10);
//画出坦克的盖子
cxt.fillStyle="#FEF26E";
cxt.arc(tank.x+15-4,tank.y+11+4,5,0,Math.PI*2,true);
cxt.fill();
//画出炮筒
cxt.strokeStyle="#FEF26E";
cxt.lineWidth=1.5;
cxt.beginPath();
cxt.moveTo(tank.x+15-4,tank.y+11+4);
if(tank.direct==1){ //只是炮筒的方向不同
cxt.lineTo(tank.x+30-4,tank.y+11+4);
}else{
cxt.lineTo(tank.x-4,tank.y+11+4);
}
cxt.closePath();
cxt.stroke();
break;
} }
坦克大战.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<body onkeydown="getCommand();">
<h1>html5-坦克大战</h1>
<!--坦克大战的战场-->
<canvas id="tankMap" width="400px" height="300px" style="background-color:black"></canvas>
<!--将tankGame04.js引入-->
<script type="text/javascript" src="tankGame06.js"></script>
<script type="text/javascript">
//得到画布
var canvas1=document.getElementById("tankMap");
//得到绘图上下文
var cxt=canvas1.getContext("2d"); //我的tank
//规定0向上、1向右、2向下、3向左
var hero=new Hero(40,40,0,heroColor);
//定义子弹数组
var heroBullets=new Array();
//敌人的tank
var enemyTanks=new Array();
for(var i=0;i<3;i++){
var enemyTank = new EnemyTank((i+1)*50,0,2,enemyColor);
enemyTanks[i]=enemyTank;
} //画出自己的子弹
function drawHeroBullet(){
for(var i=0;i<heroBullets.length;i++){
var heroBullet=heroBullets[i];
if(heroBullet!=null&&heroBullet.isLive){
cxt.fillStyle="#FEF26E";
cxt.fillRect(heroBullet.x,heroBullet.y,2,2);
}
}
} //定时刷新我们的作战区(定时重绘)
//自己的坦克,敌人坦克,子弹,炸弹,障碍物
function flashTankMap(){
//把画布清理
cxt.clearRect(0,0,400,300);
//我的坦克
drawTank(hero);
//我的子弹
drawHeroBullet();
//敌人的坦克
for(var i=0;i<3;i++){
drawTank(enemyTanks[i]);
}
}
flashTankMap();
//接收用户按键的函数
function getCommand(){
var code = event.keyCode; //键盘上字幕的ASCII码
switch(code){
case 87: //W :上
hero.moveUp();
break;
case 68: //D :右
hero.moveRight();
break;
case 83: //S :下
hero.moveDown();
break;
case 65: //A :左
hero.moveLeft();
break;
case 74: //J :发子弹
hero.shotEnemy();
break;
}
flashTankMap();
}
//每隔100毫秒去刷新一次作战区
window.setInterval("flashTankMap()",100);
</script>
</body>
</html>
[置顶] 小强的HTML5移动开发之路(9)——坦克大战游戏3的更多相关文章
- 小强的HTML5移动开发之路(18)——HTML5地理定位
来自:http://blog.csdn.net/dawanganban/article/details/18192091 在前面的<小强的HTML5移动开发之路(2)--HTML5的新特性> ...
- 小强的HTML5移动开发之路(14)——Video标签详解
来自:http://blog.csdn.net/dawanganban/article/details/18180605 在前面的小强的HTML5移动开发之路(5)--制作一个漂亮的视频播放器中制作了 ...
- 小强的HTML5移动开发之路(13)——HTML5中的全局属性
来自:http://blog.csdn.net/dawanganban/article/details/18179483 一.accssskey 快捷键 <!DOCTYPE HTML> ...
- 小强的HTML5移动开发之路(11)——链接,图片,表格,框架
来自:http://blog.csdn.net/dawanganban/article/details/18098193 一.HTML是什么? HTML(hypertext mark-uplangua ...
- 小强的HTML5移动开发之路(42)——HTML4与HTML5文档结构比较
一般来说,人们在书写包括HTML在内的文档时,习惯上按照类似于"章--节--小节"这样的层次结构来进行. 在HTML4中的描述方式: <html> <head&g ...
- 小强的HTML5移动开发之路(37)——jqMobi快速入门
在<小强的HTML5移动开发之路(33)-- jqMobi基础>中我们了解了什么是jqMobi,并从官方下载了jqMobi开发包,下载后解压目录如下: 拷贝上面的/css目录./plugi ...
- 小强的HTML5移动开发之路(2)——HTML5的新特性
来自:http://blog.csdn.net/dawanganban/article/details/17592787 一.画布(Canvas) 画布是网页中的一块区域,可所以用JavaScript ...
- 小强的HTML5移动开发之路(7)——坦克大战游戏1
来自:http://blog.csdn.net/dawanganban/article/details/17693145 上一篇中我们介绍了关于Canvas的基础知识,用Canvas绘制各种图形和图片 ...
- 小强的HTML5移动开发之路(12)——从一个多媒体标签说起
来自:http://blog.csdn.net/dawanganban/article/details/18136813 一.视频播放 <html> <head> <ti ...
随机推荐
- Python argparse
http://songpengfei.iteye.com/blog/1440158 https://docs.python.org/2/library/argparse.html http://sta ...
- ecshop 更新首页flash样式
未测试 ECSHOP默认的只有几种很普通的FLASH图片切换样式,想不想自己也换一种呢? 今天摸索了下,算是弄懂了,和大家分享下 首先在网上找到你想要的FLASH切换样式[google一下],把那个S ...
- 为什么Jquery对input file控件的onchange事件只生效一次
今天在做jquery对input file控件的onchange事件进行监听,就一直只生效一次,不知道Jquery为什么对file控件没有做到每次改变触发onchange事件的效果,但是还是有好几种解 ...
- HUD 2717 Catch That Cow
Catch That Cow Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- selenium python (六)定位一组对象
checkbox源码: <html><head><meta http-equiv="content-type" content="text/ ...
- Loadrunner 性能指标定位系统瓶颈
判断CPU瓶颈 1, %processor time 平均值大于95 2, processor queue length大于2 (大于处理器个数+1).可以确定CPU瓶颈 3, CPU空闲时间为零(z ...
- HTML和URL比较
1.录制脚本的基本原则 2.HTML和URL based script介绍 3.选择录制方式原则 4.HTML based script设置
- erase() 返回的是删除此元素之后的下一个元素的迭代器 .xml
pre{ line-height:1; color:#f0caa6; background-color:#2d161d; font-size:16px;}.sysFunc{color:#e54ae9; ...
- Epic - Spiral Matrix
Given aNXN matrix, starting from the upper right corner of the matrix start printingvalues in a coun ...
- Leetcode: Length of Last Word in python
Length of Last Word Total Accepted: 47690 Total Submissions: 168587 Given a string s consists of ...