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

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

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. Android 使用系统的Activity播放音频文件 intent

    Intent intent = new Intent(); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setAction(Inten ...

  2. MySQL数据导出导入【转】

    MySQL基础 关于MySQL数据导出导入的文章,目的有二: 1.备忘 2.供开发人员测试 工具 mysqlmysqldump 应用举例 导出 导出全库备份到本地的目录 mysqldump -u$US ...

  3. [转]数据结构之Trie树

    1. 概述 Trie树,又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构,如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树. Trie一词来自retrieve,发音为/tr ...

  4. Git命令参考手册(转)

    git init # 初始化本地git仓库(创建新仓库) git config --global user.name "xxx" # 配置用户名 git config --glob ...

  5. Project Euler 96:Su Doku 数独

    Su Doku Su Doku (Japanese meaning number place) is the name given to a popular puzzle concept. Its o ...

  6. PCB工艺镀金(电金)和沉金(化金)的区别

    1.镀金和沉金的别名分别是什么?   镀金:硬金,电金(镀金也就是电金) 沉金:软金,化金 (沉金也就是化金) 2.别名的由来:  镀金:通过电镀的方式,使金粒子附着到pcb板上,所以叫电金,因为附着 ...

  7. Android给listview的item设定高度

    在item的layout文件中,用android:layout_height设置item的高度.运行,高度设置无效. 解决办法: 给item设定minHeight,即可. -------------- ...

  8. apache&nginx资料汇总

    http://liudaoru.iteye.com/blog/336338 aquid:http://os.51cto.com/art/201009/225813.htm 数据库各种讲座:http:/ ...

  9. 高难度(3)RenderScript

    RenderScript RenderScript is a framework for running computationally intensive tasks at high perform ...

  10. oracle Instance status: READY–lsnrctl status|start|stop

    监听器启动,并不一定会认识数据库实例,启动监听器,请判别相关实例是否 READY [oracle@redhat4 ~]$ lsnrctl status LSNRCTL for Linux: Versi ...