之前,我们完成了坦克的移动和地图的绘制,这次我们来完成碰撞检测和炮弹的发射。

  上代码前来张最新的类图:

3. 碰撞检测

    前面我们已经完成了坦克的移动和地图的绘制,下面我们开始写碰撞检测。

3.1    创建碰撞检测对象

        我们创建一个对象来做碰撞检测,由于碰撞检测都是在对象移动的时候进行的所以我们让Mover继承我们的碰撞对象。
 
HitTestObject.js:
 
 // 碰撞检测对象 继承自顶级对象
HitTestObject = function () { } HitTestObject.prototype = new TankObject();
// 碰撞检测 参数为地图对象 返回true则不能移动
HitTestObject.prototype.HitTest = function (battleField) { var nextObj = this.GetNextBattleFieldCell(battleField);
if (nextObj == null) {
return true;// 场景越界
}
// 检测是否是障碍物
if (nextObj.obj instanceof Barrier) { if (nextObj.obj instanceof EmptyB) {
// 判断是否被其他坦克占用 Tank继承自Mover
return nextObj.occupier instanceof Mover;
}
return !nextObj.obj.CanAcross;
} } // 返回对象移动下个位置的地图对象
HitTestObject.prototype.GetNextBattleFieldCell = function (battleField) { if (this.Direction == EnumDirection.Up && this.YPosition == 0 ||
this.Direction == EnumDirection.Down && this.YPosition == 12 ||
this.Direction == EnumDirection.Left && this.XPosition == 0 ||
this.Direction == EnumDirection.Right && this.XPosition == 12
) {
return null;/* 场景越界 */
} var y = this.YPosition;
var x = this.XPosition;
var nextAxes = this.GetNextAxes(x, y);
return battleField[nextAxes.y][nextAxes.x];
} // 得到对象的下个位置的坐标
HitTestObject.prototype.GetNextAxes = function (x, y) {
var point = { x: x, y: y };
switch (this.Direction + "") { // 加空字符转换为字符串类型
case EnumDirection.Up:
point.y--; break;
case EnumDirection.Right:
point.x++; break;
case EnumDirection.Down:
point.y++; break;
case EnumDirection.Left:
point.x--; break;
}
return point;
} HitTestObject.prototype.OnHitTest = function (battleField) {
// 预留给炮弹对象重写
}
  这里我们把之前写的地图二维数组对象充分利用上了。通过对象x,y坐标取对应的地图对象,再根据属性判断是否可被穿过,是否已被占用。

3.2   调用碰撞检测

  这里需要我们在之前的代码做一系列的更改了。

更改 Mover.js

  1、继承碰撞检测对象
 
Mover.prototype = new HitTestObject();

  

  2、在Mover方法中调用碰撞检测
// 碰撞检测
if (this.HitTest(battleField)) { return this.OnHitTest(battleField); }

  

 
  3、移动完成后占用新地图对象,清空原对象地图占用。
 
battleField[nextPoint.y][nextPoint.x].occupier = This;  /*占用新位置*/

// 清空对象原来位置占有
battleField[yp][xp].occupier = null;

  

还有一些更改就不一一列出了,大家可以下载源码查看。
 
更改    Frame.js 给方法加上参数。
更改 tank.js  UpdateUi方法
初始化坦克时,占有当前位置。
  

4.   发射炮弹

炮弹可以移动,所以继承自我们的Mover对象。炮弹击中障碍物时会有爆炸效果,所以我们先写爆炸对象。

 

4.1 爆炸效果对象

  Explode.js:

 // 爆炸效果类
Explode = function () {
this.container = document.getElementById("divMap");
this.UI = null;
this.step = 8; // 共8张图
this.speed = 50; // 动画播放速度
} // 播放爆炸效果
Explode.prototype.Play = function (x,y) {
this.UI = UtilityClass.CreateE("div", "", "explode", this.container);
this.MoveTo(x, y); var i = 0;
var This = this;
var FxTimer = setInterval(function () {
This.UI.style.backgroundPosition = '0 -' + i * 60 + 'px';
i++;
if (i==This.step) {
clearInterval(FxTimer);
This.Stop();
}
},this.speed);
} // 播放位置
Explode.prototype.MoveTo = function (x,y) { if (this.UI != null) {
this.UI.style.left = x * 40 - 10 + "px";
this.UI.style.top = y * 40 - 10 + "px";
} } // 移除dom元素
Explode.prototype.Stop = function () {
UtilityClass.RemoveE(this.UI, this.container);
}

4.2 炮弹对象

   Bomb.js:
 
 //  炮弹对象,这个对象需要放在TANK对象前面,有先后顺序
Bomb = function () {
this.Owner = null;
this.Power = 1;
this.Speed = 7;
} Bomb.prototype = new Mover();
Bomb.prototype.Load = function (x,y) {
// 创建炮弹对象,初始化位置
this.UI = UtilityClass.CreateE("div", "", "bomb", document.getElementById("divMap"))
this.SetPosition(x * 40, y * 40); /*父类方法*/ } // 重写HitTest方法
Bomb.prototype.HitTest = function (battleField) {
var nextObj = this.GetNextBattleFieldCell(battleField);
if (nextObj == null) {
return true;
}
// 检测是否是障碍物
if (nextObj.obj instanceof Barrier) {
// 河流穿过
if (this instanceof Bomb && nextObj.obj instanceof RiverB) {
return false;
} return !nextObj.obj.CanAcross;
} } // 重写OnHitTest方法 当炮弹碰撞到不可穿过对象时调用
Bomb.prototype.OnHitTest = function (battleField) { // 播放爆炸效果
var ex = new Explode();
ex.Play(this.XPosition, this.YPosition);
this.Owner.BombUsed--; /*已用弹药数减一*/
// 清空地图占有位置,移除元素
battleField[this.YPosition][this.XPosition].occupier = null;
UtilityClass.RemoveE(this.UI, document.getElementById("divMap")); var nextObj = this.GetNextBattleFieldCell(battleField);
if (nextObj == null) { return; }
// 炮弹打到了障碍物
if (nextObj.obj instanceof Barrier) {
if (nextObj.obj.CanBeAttacked) {
nextObj.obj.DefenVal -= this.Power;
// 障碍物防御值降到0,把障碍物变为空地
if (nextObj.obj.DefenVal <= 0) {
var to = new EmptyB();
to.UI = nextObj.obj.UI;
to.XPosition = nextObj.obj.XPosition;
to.YPosition = nextObj.obj.YPosition;
nextObj.obj = to;
to.UI.className = "";
battleField[this.YPosition][this.XPosition].obj.UI.className = "";
}
}
} }
   主要的对象完成了,调用就是水到渠成了,我们需要给坦克添加一个发射炮弹的方法,并在玩家按下空格键时调用就可以了。  大家可以试着自己写下实现。  
 
TankV3.0 下载地址:
 
 

用javascript 面向对象制作坦克大战(三)的更多相关文章

  1. javascript 面向对象制作坦克大战 (一)

    PS:这个坦克大战是在网上下的一段源码之后,自己进行的重写.   写这个的目的是为了巩固自己这段时间对js的学习.整理到博客上,算是对自己近端时间学习js的一个整理. 同时也希望可以帮助到学习js的园 ...

  2. 用javascript 面向对象制作坦克大战(四)

    我们现在还差一个重要的功能,没错,敌人坦克的创建以及子弹击中敌人坦克时的碰撞检测功能. 5.  创建敌人坦克完成炮弹碰撞检测 5.1   创建敌人坦克对象 敌人坦克和玩家坦克一样,同样继承自我们的坦克 ...

  3. 用javascript 面向对象制作坦克大战(二)

    2.   完善地图 我们的地图中有空地,墙,钢,草丛,水,总部等障碍物. 我们可以把这些全部设计为对象. 2.1  创建障碍物对象群       对象群保存各种地图上的对象,我们通过对象的属性来判断对 ...

  4. javascript面向对象精要第三章对象整理精要

    什么是对象的数据属性?什么是对象的访问器属性?[put]方法是默认创建数据属性的,访 问器属性不包含值而是定义了一个单属性被读取时调用的函数(getter)和当一个属性被写入时 调用的函数(sette ...

  5. Java坦克大战 (三) 之可完全控制坦克朝八个方向运动

    本文来自:小易博客专栏.转载请注明出处:http://blog.csdn.net/oldinaction 在此小易将坦克大战这个项目分为几个版本,以此对J2SE的知识进行回顾和总结,希望这样也能给刚学 ...

  6. html5制作坦克大战

    全部html5都采用绘图技术完成.坦克是画出来的.(坦克,子弹,墙,水,草坪) 首先我们画出坦克. 坦克是两边两个矩形,中间一个大矩形,矩形了有一个圆,还有一根线. 画出坦克的思路是以坦克的左上角为参 ...

  7. JavaScript 面向对象的编程(三) 类的继承

    定义父类和子类的继承关系 //声明父类 function SuperClass(){ this.superValue = true; } //为父类添加共有方法 SuperClass.prototyp ...

  8. 【blade04】用面向对象的方法写javascript坦克大战

    前言 javascript与程序的语言比如C#或者java不一样,他并没有“类”的概念,虽然最新的ECMAScript提出了Class的概念,我们却没有怎么用 就单以C#与Java来说,要到真正理解面 ...

  9. 汉顺平html5课程分享:6小时制作经典的坦克大战!

    记起自己去年參加的一次面试,在做过Java多年的面试官面前发挥的并不好,但他一听说我会html5,立刻眼睛发亮.无论不顾的想要和我签约.. .所以.如今为工作犯愁的朋友们,学好html5,绝对会为你找 ...

随机推荐

  1. 使用ajax()方法加载服务器数据

    使用ajax()方法加载服务器数据 使用ajax()方法是最底层.功能最强大的请求服务器数据的方法,它不仅可以获取服务器返回的数据,还能向服务器发送请求并传递数值,它的调用格式如下: jQuery.a ...

  2. Openfire 服务端在Eclipse上部署

    http://blog.csdn.net/chexitianxia/article/details/9371169 结合: http://blog.csdn.net/ares1201/article/ ...

  3. IE11兼容IE9问题

    注意如果<head>标签里加<meta http-equiv="X-UA-Compatible"content="IE=EmulateIE9" ...

  4. 【Linux高频命令专题(22)】gzip

    概述 减少文件大小有两个明显的好处,一是可以减少存储空间,二是通过网络传输文件时,可以减少传输的时间.gzip是在Linux系统中经常使用的一个对文件进行压缩和解压缩的命令,既方便又好用.gzip不仅 ...

  5. LR_问题_脚本运行时提示没有参数化

    问题描述 将loadrunner中的参数删除,并且删除脚本目录下对应的bak,执行脚本,出现下面的错误: “错误: 表“XX\phonenumbser.dat”不存在.         [MsgId: ...

  6. LR_问题_运行场景时提示scripts you are running in invalid

    问题描述 脚本在virtual user generator中运行正常. 在Controller中运行场景时报错: the target you defined cannot be reached. ...

  7. 62. Unique Paths

    题目: A robot is located at the top-left corner of a m x ngrid (marked 'Start' in the diagram below). ...

  8. Bitmap 和Drawable 的区别

    Bitmap - 称作位图,一般位图的文件格式后缀为bmp,当然编码器也有很多如RGB565.RGB888.作为一种逐像素的显示对象执行效率高,但是缺点也很明显存储效率低.我们理解为一种存储对象比较好 ...

  9. hive学习笔记——表的基本的操作

    1.hive的数据加载方式 1.1.load data 这中方式一般用于初始化的时候 load data [local] inpath '...' [overwrite] into table t1 ...

  10. 面试题_82_to_87_Date、Time 及 Calendar 的面试题

    82)在多线程环境下,SimpleDateFormat 是线程安全的吗?(答案)不是,非常不幸,DateFormat 的所有实现,包括 SimpleDateFormat 都不是线程安全的,因此你不应该 ...