我们现在还差一个重要的功能,没错,敌人坦克的创建以及子弹击中敌人坦克时的碰撞检测功能。

5.  创建敌人坦克完成炮弹碰撞检测

5.1   创建敌人坦克对象

  敌人坦克和玩家坦克一样,同样继承自我们的坦克对象。所以我们在Tank.js中写入以下代码:

 // 敌人坦克对象
EnimyTank = function () {
this.Direction = EnumDirection.Down;
this.BombNum = 1;
this.UI = UtilityClass.CreateE("div", "", "etank", document.getElementById("divMap"));
this.UI.style.backgroundPosition = "0 -" + this.Direction * 40 + "px"; } EnimyTank.prototype = new Tank;

  然后在我们的游戏装载对象初始化游戏时创建敌人坦克。

   var enimyT1 = new EnimyTank();
enimyT1.XPosition = 0;
enimyT1.YPosition = 0;
enimyT1.UpdateUI(this._battleField);
this._enimyTanks.push(enimyT1);

5.2   敌人坦克移动和发射炮弹

  坦克创建好了,我们怎么让他动起来呢? 很简单,只需要在我们的游戏装载对象中添加一个敌人坦克移动并发射的方法,并且在Run主循环中进行调用就可以了。

代码:

     for (var i = 0; i < this._enimyTanks.length; i++) {

             if (this._enimyTanks[i] instanceof Mover) {
this._enimyTanks[i].Move(this._battleField);
if (Math.random() * 100 < 5) { this._enimyTanks[i].Shot(this._battleField) };/* 5%的概率发射炮弹 */
}
}

  ok,现在我们的坦克可以正常的移动和发射炮弹了。但是我们发现坦克移动的方向不会发生改变,所以还需要一个小小的处理,在我们的Mover对象的Move方法中添加以下代码,敌人坦克就能随机变换方向了。

     // 敌人坦克有30%几率变换方向
if ((this instanceof EnimyTank) && Math.random() * 100 > 30) {
this.Direction = parseInt(Math.random() * 4);
}

5.3   炮弹碰撞检测

  之前我们炮弹的碰撞检测只写了打到障碍物的检测,所以我们还需要添加炮弹碰撞到坦克的情况。 实现思路很简单,当我们的子弹穿过空地或草地(坦克能停留的两种地形)时,我们检测地图的占有对象是不是坦克就可以了。上代码:

Bomb.js:

             //  如果下一个是草或者空地
else if (nextObj.obj instanceof EmptyB || nextObj.obj instanceof TodB) {
// 玩家炮弹打中敌人坦克
if (nextObj.occupier instanceof EnimyTank && this.Owner instanceof SelfTank) {
UtilityClass.RemoveE(nextObj.occupier.UI, document.getElementById("divMap"));
nextObj.occupier.UI = null;
GameLoader.prototype._enimyTanks.pop();
nextObj.occupier = null;
} // 敌人炮弹打中玩家坦克
else if (nextObj.occupier instanceof SelfTank && this.Owner instanceof EnimyTank) {
//UtilityClass.RemoveE(nextObj.occupier.UI, document.getElementById("divMap"));
//nextObj.occupier = null;
}
}

  此时,我们会发现当玩家的炮弹击中敌人后,敌人坦克会随机的占有他的4个方向中的一个单元格。这是什么原因造成的呢?   我们可以想想,当我们的炮弹命中敌人的时候,他有可能正在移动。这时候我们把他移除了,但是他的Move的步进方法还会继续执行,别忘了,我们是用的setInterval,所以他就鬼使神差步进到下一个单元格。 这时候坦克对象移除了,但是占用还在,就会出问题了。

  解决的方案很简单,我们在移除坦克时将坦克的UI 已经设置为null了,所以在步进前我们判断他UI的值为null时,我们就停止步进就ok了。代码很简单:

   if (This instanceof EnimyTank) {
// 如果敌人坦克被销毁,则停止步进
if (This.UI == null) {
clearInterval(subMove);
}
}

5.4   多个敌人坦克的解决方案

  这时候我们还发现一个严重的问题: 我们的敌人坦克是保存在游戏装载对象里的一个数组,当我们消灭敌人坦克时,我们不知道到底该从中移除哪个坦克。

  其实这个问题的解决思路相当简单:在初始化敌人坦克时给他一个属性保存他在数组中的索引,当需要消除坦克对象时,我们直接根据索引移除就可以了。

1、初始化存储索引

  

 enimyT1.index = this._enimyTanks.length;

2、给Array扩展原型方法,移除指定位置的数组。

  

 Array.prototype.removeAt = function (index) {
var arr = [], j = 0;
// 遍历数组,过滤指定位置的元素
for (var i = 0; i < this.length; i++) {
if (i != index) {
arr[j++] = this[i];
}
}
return arr;
}

3、修改炮弹打中敌人的代码。

  // 玩家炮弹打中敌人坦克
if (nextObj.occupier instanceof EnimyTank && this.Owner instanceof SelfTank) {
UtilityClass.RemoveE(nextObj.occupier.UI, document.getElementById("divMap"));
nextObj.occupier.UI = null;
var arr = GameLoader.prototype._enimyTanks.removeAt(nextObj.occupier.index);
// 重置坦克索引
for (var i = 0; i < arr.length; i++) {
arr[i].index = i;
}
GameLoader.prototype._enimyTanks = arr;
nextObj.occupier = null;
}

  这里有一个重置索引的代码,大家可能不明白为什么这么做。 当我们移除掉一个坦克后,数组的元素个数变了,所以原来的数组索引有可能失效。所以我们只要重置一下,就ok了。

  大致的功能已经出来了,肯定有一些bug和待完善的地方。列如坦克的移动和炮弹的发射不兼容,玩家子弹和敌人子弹碰撞时应该消除... 还有一些功能未实现:玩家坦克被击中消失、游戏道具、敌人坦克生成、计分、关卡、玩家自己绘制地图。  没有错,我打算把这些难题交给大家了。 写这个博客主要的目的已经达到了:学习js面向对象。希望大家有时间继续完善这个游戏,在完成的过程中可以学到很多东西。  感谢各位听我啰嗦。

最后这个版本的下载地址:

http://pan.baidu.com/s/1pJ3DWKV

  

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

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

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

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

    之前,我们完成了坦克的移动和地图的绘制,这次我们来完成碰撞检测和炮弹的发射. 上代码前来张最新的类图: 3. 碰撞检测     前面我们已经完成了坦克的移动和地图的绘制,下面我们开始写碰撞检测. 3. ...

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

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

  4. html5制作坦克大战

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

  5. Java坦克大战 (四) 之子弹的产生

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

  6. javascript面向对象精要第四章构造函数和原型对象整理精要

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

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

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

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

  9. javascript面向对象系列第四篇——选项卡的实现

    前面的话 面向对象的应用并非只是读几本书那么容易,需要有大量的工程实践做基础才能真正理解并学会使用它.本文将用面向对象的技术来制作一个简单的选项卡 图示说明 由图示结果看到,这是一个非常简单的选项卡. ...

随机推荐

  1. js 后台异步执行

    public void AlertMsg(string msg, bool async) { string script = string.Format("alert('{0}'); &qu ...

  2. Error: The VPN client agent was unable to create the interprocess communication depot.

    当安装Cisco AnyConnect VPN Client出现The VPN client agent was unable to create the interprocess communica ...

  3. Java学习笔记(一) java介绍

    编程语言分为:编译型语言和解释型语言. 编译型语言需要经过特定编译器通过一次性编译,成为该特定平台硬件可执行的机器码,可脱离开发环境独立运行,运行效率较高,但是无法跨平台移植. 解释型语言需要经过特定 ...

  4. Python图片转换成矩阵,矩阵数据转换成图片

    # coding=gbk from PIL import Image import numpy as np # import scipy def loadImage(): # 读取图片 im = Im ...

  5. 关于fisher判别的一点理解

    最近一个朋友问这方面的一些问题,其实之前也就很粗略的看了下fisher,真正帮别人解答问题的时候才知道原来自己也有很多东西不懂.下面小结下自己对fisher判别的理解: 其实fisher和PCA差不多 ...

  6. eclipse配置jdk问题

    1.JDK安装成功,eclipse也安装成功,这时候实际上是可以不配置JDK,因为系统已经默认给你配置好了,

  7. HTML5入门十一---Canvas画布实现画图(二)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  8. sql server 自定义函数的使用

    sql server 自定义函数的使用 自定义函数 用户定义自定义函数像内置函数一样返回标量值,也可以将结果集用表格变量返回 用户自定义函数的类型: 标量函数:返回一个标量值 表格值函数{内联表格值函 ...

  9. java 菱形

    //画菱形 一半 for(int hs=1;hs<11;hs++) //行数 { //画空格 for(int kg = 9; kg >= hs; kg--) //空格数 { System. ...

  10. c# webbrowser 清除当前网站 cookie

    //这个方法可以创建一个清除当前页面下指定域的所有cookie //必须是可以访问的域,比如你访问的是qq.com,那么可以清除www.qq.com,qzone.qq.com等页面的cookie // ...