【javascript面向对象之路】让我们一起来坦克大战吧01

简介:
提问

不知道大家发现没有,运行时候浏览器或者电脑会变得很卡哦。根据我们之前的学习,你知道是什么原因导致的吗?

若是各位有兴趣,请你回答卡的原因,并提出优化方案。 

前言

PS 各位要看效果还是使用ff或者google吧,ie7以下好像有问题。

最近大家都在坦克大战,我突然想了下我是不是也应该坦克大战一番呢?于是,我们就有了今天的东西。

其实做坦克大战并不是为了坦克大战,而是为了javascript面向对象!所以我这里并不会完成这个游戏,做到哪步是哪步吧。

怎么说呢?javascript面向对象大家都听得很多了,但能真正理解的人并不多,我事实上也是水的,知道一点皮毛是没用的,所以想以此提升面向对象的思想。

PS:最近其实事情挺多的,HTML5+CSS3、CSS、javascript、bootstrap、响应式布局......我现在是想到哪打哪啊!

算了,扯远了,我们开始今天的学习吧。

PS:运行的时候请使用高版本浏览器,这里暂时没有做浏览器兼容

工欲善其事必先利其器

刚开始干我就在想,我是不是该写个类库神马的,于是在这里磨磨蹭蹭的搞了一个多小时,硬是挤出了以下代码:

复制代码
 1 function getById(id) {
 2     return !id ? null : document.getElementById(id);
 3 }
 4 
 5 function getAttr(el, k) {
 6     if (el) {
 7         var v = el.getAttribute[k] ? el.getAttribute[k] : null;
 8         return v;
 9     }
10 }
11 
12 function setAttr(el, k, v) {
13     if (el) {
14        el.setAttribute(k, v);
15     }
16 }
17 
18 function getCss(el, k) {
19     if (el) {
20        
21         if (el.style[k]) {
22             return el.style[k];
23         }  
24         return null;
25     }
26 }
27 
28 function setCss(el, k, v) {
29     if (el) {
30         if (!el.style || el.style.length == 0) {
31             el.style = {};
32         }
33         el.style[k] = v;
34     }
35 }
复制代码
不用看,也不用说,光是想求得元素的样式这块我就知道有问题,但是我们不能舍本逐末,这里暂时不管他(因为我搞了个把小时了),我们还是按着逻辑往下走吧。

资料准备

我们这里需要一点点坦克的图片,于是打开我们的PS,PS之:

这个坦克的资源,我不知道原来从哪里来的,这里先私自用了,原作者若是觉得有问题请留言。

PS:我们这里先不考虑小图标的问题,一点点来吧

首先是我们的子弹爆炸要用到的图片:



看到这个图片各位就应该要想到炮弹爆炸式怎么实现的了哦!

然后我们的主角,坦克的图片:



下面是我们的子弹:



于是我们几个坦克也有了,子弹也有了,好了我们先不关注其它,看看我们能不能把坦克给搞出来(话说我PS不是太好,这个也必须纳入必学范围)。

移动的坦克

我们搞移动的坦克之前,在页面上先弄一张地图,作为坦克使用:

复制代码
 1 <html xmlns="http://www.w3.org/1999/xhtml">
 2 <head>
 3     <title></title>
 4     <style type="text/css">
 5         .map { background: gray; border: 1px solid black; position: relative; margin: 50px auto; width: 416px; height: 416px; }
 6     </style>
 7 </head>
 8 <body>
 9     <div class="map" id="map">
10         <div id="me" class="tank">
11         </div>
12     </div>
13 </body>
14 </html>
复制代码


好了,让我们主角坦克登场吧,注意其中的me:

复制代码
 1 <html xmlns="http://www.w3.org/1999/xhtml">
 2 <head>
 3     <title></title>
 4     <style type="text/css">
 5         .map { background: gray; border: 1px solid black; position: relative; margin: 50px auto; width: 416px; height: 416px; }
 6          .tank { background-image: url("images/tank.gif"); overflow: hidden; position: absolute; width: 32px; height: 32px; z-index: 3; }
 7          
 8     </style>
 9 </head>
10 <body>
11     <div class="map" id="map">
12         <div id="me" class="tank">
13         </div>
14     </div>
15 </body>
16 </html>
复制代码


我们可爱的坦克,还是2二级的坦克出现啦,现在我们为他加上移动效果,这里就要开始写代码啦,首先我们定义一个坦克类:

复制代码
 1 var Tank = function (id, dir, x, y) {
 2     this.el = getById(id);
 3     this.direction = dir ? dir : 'up';
 4     this.tid = null;
 5     this.speed = 10;
 6     //坦克活动状态 0 未活动 1 正在活动
 7     this.activeState = 0;
 8     this.x = x ? x : 100;
 9     this.y = y ? y : 200;
10     this.dirState = {
11         up: 1,
12         right: 1,
13         down: 1,
14         left: 1
15     };
16 }
复制代码
我现在能想到坦克具有的属性便是:

1 坦克对应的html标签

2 坦克的初始化方向

3 坦克的初始化位置

在修改一点点,我们就能控制坦克转向了:

 View Code
运行效果(此处可运行):

然后我们来加上移动的动画,各位注意啦,我们这里要使用js实现动画啦!我们来看看这段代码:

 完整代码
复制代码
 1 Tank.prototype.move = function (dir) {
 2     if (this.activeState != 0) return false; //正在运动我们便不管他
 3     this.activeState = 1; //将当前状态设置为正在运动
 4     if (this.direction != dir) {
 5         this.direction = dir;
 6         this.setDirection(dir);
 7     }
 8     //处理运动中的定时器
 9     if (this.tid) {
10         clearTimeout(this.tid);
11         this.tid = null;
12     }
13     var state = this.dirState[dir];
14     var tank = this.el;
15     if (state == 1 || state == -1) {
16         var strPos = getCss(tank, 'backgroundPosition');
17         var arrPos = strPos.split(' ');
18         var l = arrPos ? arrPos[0] : 0;
19         var t = arrPos ? arrPos[1] : 0;
20         var curPos = parseInt(l);
21         var top = parseInt(t);
22         var po = curPos - (43) * (state);
23         var curPos = po + 'px ' + t + 'px';
24         setCss(tank, 'backgroundPosition', curPos);
25     }
26     var xpos = getCss(tank, 'left') ? getCss(tank, 'left') : 0;
27     var ypos = getCss(tank, 'top') ? getCss(tank, 'top') : 0;
28     xpos = parseInt(xpos);
29     ypos = parseInt(ypos);
30     var mx = MyGlobal.mapWidth - 32;
31     var my = MyGlobal.mapHeight - 32;
32     switch (dir) {
33         case 'up': ypos <= 0 ? 0 : ypos--; break;
34         case 'right': xpos >= mx ? mx : xpos++; break;
35         case 'down': ypos >= my ? my : ypos++; break;
36         case 'left': xpos <= 0 ? 0 : xpos--; break;
37     }
38     setCss(tank, 'left', xpos + 'px');
39     setCss(tank, 'top', ypos + 'px');
40     var scope = this;
41     var speed = this.speed;
42     var repeat = function () {
43         scope.move(dir);
44     };
45     if (!this.tid) {
46         this.tid = setTimeout(repeat, speed);
47     }
48     //移动结束
49     this.activeState = 0;
50 };
复制代码
这个代码其实没什么好说的,只不过我们每次运动后会改变其方向的状态值,为的就是不停的改变背景,以达到坦克前进的效果。

运行效果(此处可运行):

于是我们简单的完成了坦克移动的功能了,现在我们来考虑炮弹的问题了。

炮弹对象

上面的是坦克对象,我们现在来看看炮弹对象,我们将坦克,炮弹,砖块各自看做一个对象,这样不知道面向对象没。。。

复制代码
  1 //子弹对象
  2 var Bullet = function (dir) {
  3     this.direction = dir ? dir : 'up';
  4     this.speed = 5;
  5     var factor = 0;
  6     this.tid = null;
  7     this.activeState = 0;
  8     this.blastState = 0; //爆炸状态 0-4
  9     this.blastReason = 0; //爆炸原因 0一般爆炸,4 集中坦克 3......
 10     this.x = 0;
 11     this.y = 0;
 12     if (dir) {
 13         switch (dir) {
 14             case 'up': factor = 0; break;
 15             case 'right': factor = 1; break;
 16             case 'down': factor = 2; break;
 17             case 'left': factor = 3; break;
 18         }
 19     }
 20     var el = document.createElement('div');
 21     var bp = 'background-position :' + (0 - 8 * factor) + 'px  0 ;';
 22     el.setAttribute('style', bp);
 23     el.setAttribute('class', 'bullet');
 24     this.el = el;
 25 };
 26 
 27 Bullet.prototype.move = function () {
 28 
 29     var bullet = this.el;
 30     var dir = this.direction;
 31     var xpos = getCss(bullet, 'left') ? getCss(bullet, 'left') : 0;
 32     var ypos = getCss(bullet, 'top') ? getCss(bullet, 'top') : 0;
 33     xpos = parseInt(xpos);
 34     ypos = parseInt(ypos);
 35     var mx = MyGlobal.mapWidth - 8;
 36     var my = MyGlobal.mapHeight - 8;
 37     var stop = false;
 38     switch (dir) {
 39         case 'up':
 40             if (ypos <= 0) {
 41                 stop = true;
 42             } else {
 43                 ypos--;
 44             }
 45             break;
 46         case 'right':
 47             if (xpos >= mx) {
 48                 stop = true;
 49             } else {
 50                 xpos++;
 51             }
 52             break;
 53         case 'down':
 54             if (ypos >= my) {
 55                 stop = true;
 56             } else {
 57                 ypos++;
 58             }
 59             break;
 60         case 'left':
 61             if (xpos <= 0) {
 62                 stop = true;
 63             } else {
 64                 xpos--;
 65             }
 66             break;
 67     }
 68 
 69     setCss(bullet, 'left', xpos + 'px');
 70     setCss(bullet, 'top', ypos + 'px');
 71     this.x = xpos;
 72     this.y = ypos;
 73 
 74     var scope = this;
 75     var speed = this.speed;
 76     var repeat = function () {
 77         scope.move();
 78     };
 79     if (this.tid) {
 80         clearTimeout(this.tid);
 81         this.tid = null;
 82     }
 83     if (!this.tid) {
 84         this.tid = setTimeout(repeat, speed);
 85     }
 86     if (stop) {
 87         this.blast();
 88     }
 89 };
 90 
 91 Bullet.prototype.blast = function (reason) {
 92     var el = this.el;
 93     var x = this.x - 28;
 94     var y = this.y - 28;
 95     setCss(el, 'left', x + 'px');
 96     setCss(el, 'top', y + 'px');
 97     this.x = x;
 98     this.y = y;
 99     var scope = this;
100     setAttr(el, 'class', 'Boom');
101     setCss(scope.el, 'backgroundPosition', '0 0');
102     var action = function () {
103         if (scope.blastState < (scope.blastReason + 1)) {
104             var b = scope.blastState * 64 * (-1);
105             b = b + 'px 0';
106             setCss(scope.el, 'backgroundPosition', b);
107             scope.blastState++;
108             setTimeout(action, 20);
109         } else {
110             getById('map').removeChild(scope.el);
111             delete scope;
112         }
113     };
114     if (reason) {
115         this.blastReason = reason;
116     }
117     setTimeout(action, 20);
118 
119     clearTimeout(this.tid);
120     this.tid = null;
121 
122     //    this.blastState
123 
124 };
复制代码
完整代码:

 完整代码
效果演示(可运行)J可以发子弹,没有子弹就到高版本浏览器去试试

http://sandbox.runjs.cn/show/evpyzcku

结语

好了,今天到此为止,后面点我们来一步步修改代码,让代码变得“面向对象”,有机会便加上砖块和其它东东。

今天的代码不用说,千疮百孔,无论是性能方面,或者代码优雅度,还是神马都一团糟糕,但是经过几个小时的奋战,我现在脑子已经不好使了,只好暂时停一下。

我们后面点优化吧。



本文转自叶小钗博客园博客,原文链接http://www.cnblogs.com/yexiaochai/archive/2013/06/12/3132553.html,如需转载请自行联系原作者

相关文章
|
JavaScript 前端开发 Java
深入JS面向对象(原型-继承)(一)
深入JS面向对象(原型-继承)
30 0
|
7月前
js- 面向对象进阶
Object.defineProperty等面向对象的信息
|
7月前
|
存储 JavaScript 前端开发
|
2月前
|
设计模式 前端开发 JavaScript
深入认识:JavaScript中的面向对象
深入认识:JavaScript中的面向对象
12 0
|
3月前
|
Web App开发 JavaScript 前端开发
深度刨析 JavaScript 模拟面向对象的内部机制
深度刨析 JavaScript 模拟面向对象的内部机制
79 0
|
3月前
|
存储 JavaScript 前端开发
【JavaScript】<面向对象Object>函数方法&对象创建&原型对象&作用域解析
【1月更文挑战第17天】【JavaScript】<面向对象Object>函数方法&对象创建&原型对象&作用域解析
|
3月前
|
存储 JSON 前端开发
JavaScript:构造函数&面向对象
JavaScript:构造函数&面向对象
36 2
|
8月前
|
设计模式 JavaScript 前端开发
js面向对象入门
js面向对象入门
56 0
|
3月前
|
存储 JavaScript 前端开发
JavaScript知识总结 终结篇--面向对象,垃圾回收与内存泄漏
JavaScript知识总结 终结篇--面向对象,垃圾回收与内存泄漏
|
7月前
|
存储 JavaScript
js-面向对象
把数据及对数据的操作方法放在一起,作为一个相互依存的整体——对象。对同类对象抽象出其共性,形成类。类中的大多数数据,只能用本类的方法进行处理。