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

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

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

5.1   创建敌人坦克对象

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

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

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

1   var enimyT1 = new EnimyTank();
2         enimyT1.XPosition = 0;
3         enimyT1.YPosition = 0;
4         enimyT1.UpdateUI(this._battleField);
5         this._enimyTanks.push(enimyT1);

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

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

代码:

1     for (var i = 0; i < this._enimyTanks.length; i++) {
2
3             if (this._enimyTanks[i] instanceof Mover) {
4                  this._enimyTanks[i].Move(this._battleField);
5                  if (Math.random() * 100 < 5) { this._enimyTanks[i].Shot(this._battleField) };/* 5%的概率发射炮弹 */
6             }
7         }

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

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

5.3   炮弹碰撞检测

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

Bomb.js:

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

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

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

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

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

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

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

1、初始化存储索引

  

 enimyT1.index = this._enimyTanks.length;

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

  

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

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

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

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

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

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

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

  

时间: 2024-08-03 09:33:31

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

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

PS:这个坦克大战是在网上下的一段源码之后,自己进行的重写.   写这个的目的是为了巩固自己这段时间对js的学习.整理到博客上,算是对自己近端时间学习js的一个整理. 同时也希望可以帮助到学习js的园友.由于自己也是刚学js不久,所以难免出现错误.如果发现希望给予指正.   这个教程适合熟悉js基本语法和面向对象语法的园友学习. 本身没有太难的东西,这个案例将js面向对象用的比较好,可以作为js面向对象的入门教程. 1.   创建基本对象,实现坦克简单的移动. 1.1    如何在地图中绘制画布

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

之前,我们完成了坦克的移动和地图的绘制,这次我们来完成碰撞检测和炮弹的发射. 上代码前来张最新的类图: 3. 碰撞检测 前面我们已经完成了坦克的移动和地图的绘制,下面我们开始写碰撞检测. 3.1    创建碰撞检测对象 我们创建一个对象来做碰撞检测,由于碰撞检测都是在对象移动的时候进行的所以我们让Mover继承我们的碰撞对象. HitTestObject.js:   这里我们把之前写的地图二维数组对象充分利用上了.通过对象x,y坐标取对应的地图对象,再根据属性判断是否可被穿过,是否已被占用. 3

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

2.   完善地图 我们的地图中有空地,墙,钢,草丛,水,总部等障碍物. 我们可以把这些全部设计为对象. 2.1  创建障碍物对象群 对象群保存各种地图上的对象,我们通过对象的属性来判断对象是否可以被穿过或被攻击. Barrier.js:   2.2    写入地图的数据. 在Common.js 中添加以下代码:   2.3    绘制地图 准备工作做完了,下面开始上大菜,绘制地图.前面有提到我们的地图为 13 * 13 的表格.所以我们在游戏装载对象添加行和列两个属性,并且添加初始化地图方法.

html5制作坦克大战

全部html5都采用绘图技术完成.坦克是画出来的.(坦克,子弹,墙,水,草坪) 首先我们画出坦克. 坦克是两边两个矩形,中间一个大矩形,矩形了有一个圆,还有一根线. 画出坦克的思路是以坦克的左上角为参照点,画出坦克的其他部分. 这样的好处是,当左上角的点发生改变是,坦克才能发生改变. 不使用图片的原因就是图片是比较耗费资源的.因为图片的像素点很大. tankGame1.html的代码 <!DOCTYPE html><html><head><meta charset

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

前言 javascript与程序的语言比如C#或者java不一样,他并没有“类”的概念,虽然最新的ECMAScript提出了Class的概念,我们却没有怎么用 就单以C#与Java来说,要到真正理解面向对象的程度也是要花一点功夫的,特别是初学的同学往往意识不到面向对象的好处,因为我们编码的流程是这样的 ① 面向过程 这个时候,我们要思想一个东西,往往就用一个大代码段完成了 ② 方法重用 我们有时候再也受不了重复的代码在一个地方存在了,于是这个时候我们会将相同的逻辑抽象为一个方法 ③ 当代码达到一

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

记起自己去年參加的一次面试,在做过Java多年的面试官面前发挥的并不好,但他一听说我会html5,立刻眼睛发亮.无论不顾的想要和我签约.. .所以.如今为工作犯愁的朋友们,学好html5,绝对会为你找到好工作加入重要砝码. html5 大致是 (html+css3+javascript apis).一句话: html5 支持了css3 的强大的选择器和动画等功能+ 支持javascript 非常多新的函数.所以html5就非常强大了. 所以在此特意韩顺平老师的html5课程-6小时编写经典坦克大

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

前面的话 面向对象的应用并非只是读几本书那么容易,需要有大量的工程实践做基础才能真正理解并学会使用它.本文将用面向对象的技术来制作一个简单的选项卡 图示说明 由图示结果看到,这是一个非常简单的选项卡.三个控制按钮利用点击事件分别控制三张不同的选项卡.选项卡用文字和背景颜色区分,控制按钮用轮廓outline区分 HTML代码 [1]使用行间样式来引入CSS的扩展性不高,需要根据实际情况谨慎使用 [2]在a标签中使用javascript:;来阻止默认的页面跳转行为 [3]给最外层div元素设置id属

java制作简单的坦克大战

坦克大战是我们小时候玩红白机时代的经典游戏,看到有不少小伙伴都使用各种语言实现了一下,手痒痒,也使用java做的一个比较简单的坦克大战,主要面向于学过Java的人群,与学了一段时间的人,有利于面向对象思想的提高,推荐给大家. 详情请参照注释,这里就不多废话了,实现一下儿时的经典而已. Blood.java ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 3

JavaScript学习总结(四)——this、原型链、javascript面向对象

一.this 在JavaScript中this表示:谁调用它,this就是谁. JavaScript是由对象组成的,一切皆为对象,万物皆为对象.this是一个动态的对象,根据调用的对象不同而发生变化,当然也可以使用call.apply修改this指向的对象.它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用 1.0.猜猜答案 代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8&quo