【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 坦克的初始化位置

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

  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"); background-repeat: no-repeat; overflow: hidden; position: absolute; width: 32px; height: 32px; z-index: 3; }
  7     </style>
  8 </head>
  9 <body>
 10     <div class="map" id="map">
 11         <div id="me" class="tank">
 12         </div>
 13     </div>
 14 
 15     <script src="../06tank/js/core.js" type="text/javascript"></script>
 16     <script type="text/javascript">
 17         var Tank = function (id, dir, x, y) {
 18             this.el = getById(id);
 19             this.direction = dir ? dir : 'up';
 20             this.tid = null;
 21             this.speed = 10;
 22             //坦克活动状态 0 未活动 1 正在活动
 23             this.activeState = 0;
 24             this.x = x ? x : 100;
 25             this.y = y ? y : 200;
 26             this.dirState = {
 27                 up: 1,
 28                 right: 1,
 29                 down: 1,
 30                 left: 1
 31             };
 32         };
 33         Tank.prototype.init = function () {
 34             var dir = this.direction;
 35             var tank = this.el;
 36             setCss(tank, 'left', this.x + 'px');
 37             setCss(tank, 'top', this.y + 'px');
 38             this.setDirection(dir);
 39         };
 40         Tank.prototype.setDirection = function (dir) {
 41             var tank = this.el;
 42             if (dir == 'up') {
 43                 setCss(tank, 'backgroundPosition', '0 0');
 44             }
 45             if (dir == 'right') {
 46                 setCss(tank, 'backgroundPosition', '-5px -36px');
 47             }
 48             if (dir == 'down') {
 49                 setCss(tank, 'backgroundPosition', '0 -73px');
 50             }
 51             if (dir == 'left') {
 52                 setCss(tank, 'backgroundPosition', '0 -105px');
 53             }
 54             this.dirState[dir] = 1;
 55         };
 56 
 57         var tank = new Tank('me', 'right', 100, 100);
 58         tank.init();
 59 
 60         function getDir(code) {
 61             if (code == '87' || code == '119') {
 62                 return 'up';
 63             }
 64             if (code == '100' || code == '68') {
 65                 return 'right';
 66             }
 67             if (code == '115' || code == '83') {
 68                 return 'down';
 69             }
 70             if (code == '97' || code == '65') {
 71                 return 'left';
 72             }
 73             return null;
 74         }
 75 
 76         document.onkeydown = function (evt) {
 77             evt = (evt) ? evt : window.event;
 78             var keyCode = evt.keyCode;
 79             var charCode = evt.charCode;
 80             var dir = getDir();
 81             if (keyCode) {
 82                 dir = getDir(keyCode.toString());
 83             }
 84             if (charCode) {
 85                 dir = getDir(charCode.toString());
 86             }
 87             tank.setDirection(dir);
 88 
 89             evt.preventDefault();
 90             return false;
 91         };
 92         document.onkeyup = function (evt) {
 93         };
 94         document.onkeypress = function (evt) {
 95             evt = (evt) ? evt : window.event;
 96             var keyCode = evt.keyCode;
 97             var charCode = evt.charCode;
 98             var dir = getDir();
 99             if (keyCode) {
100                 dir = getDir(keyCode.toString());
101             }
102             if (charCode) {
103                 dir = getDir(charCode.toString());
104             }
105             evt.preventDefault();
106             return false;
107         };
108     </script>
109 </body>
110 </html>
View Code

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

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

  1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2 <html xmlns="http://www.w3.org/1999/xhtml">
  3 <head>
  4     <title></title>
  5     <style type="text/css">
  6         .map { background: gray; border: 1px solid black; position: relative; margin: 50px auto; width: 416px; height: 416px; }
  7         .tank { background-image: url("//images0.cnblogs.com/blog/294743/201306/12123133-eaa9ada8690e4216a2bee3e56442e032.gif"); background-repeat: no-repeat; overflow: hidden; position: absolute; width: 32px; height: 32px; z-index: 3; }
  8     </style>
  9 </head>
 10 <body>
 11     <div class="map" id="map">
 12         <div id="me" class="tank">
 13         </div>
 14     </div>
 15     <script type="text/javascript">
 16         function getById(id) {
 17             return !id ? null : document.getElementById(id);
 18         }
 19 
 20         function getAttr(el, k) {
 21             if (el) {
 22                 var v = el.getAttribute[k] ? el.getAttribute[k] : null;
 23                 return v;
 24             }
 25         }
 26 
 27         function setAttr(el, k, v) {
 28             if (el) {
 29                 el.setAttribute(k, v);
 30             }
 31         }
 32 
 33         function getCss(el, k) {
 34             if (el) {
 35 
 36                 if (el.style[k]) {
 37                     return el.style[k];
 38                 }
 39                 return null;
 40             }
 41         }
 42 
 43         function setCss(el, k, v) {
 44             if (el) {
 45                 if (!el.style || el.style.length == 0) {
 46                     el.style = {};
 47                 }
 48                 el.style[k] = v;
 49             }
 50         }
 51 
 52         var MyGlobal = {
 53             mapWidth: 416,
 54             mapHeight: 416,
 55             width: 448,
 56             height: 512
 57         };
 58 
 59         var Tank = function (id, dir, x, y) {
 60             this.el = getById(id);
 61             this.direction = dir ? dir : 'up';
 62             this.tid = null;
 63             this.speed = 10;
 64             //坦克活动状态 0 未活动 1 正在活动
 65             this.activeState = 0;
 66             this.x = x ? x : 100;
 67             this.y = y ? y : 200;
 68             this.dirState = {
 69                 up: 1,
 70                 right: 1,
 71                 down: 1,
 72                 left: 1
 73             };
 74         };
 75         Tank.prototype.init = function () {
 76             var dir = this.direction;
 77             var tank = this.el;
 78             setCss(tank, 'left', this.x + 'px');
 79             setCss(tank, 'top', this.y + 'px');
 80             this.setDirection(dir);
 81         };
 82         Tank.prototype.setDirection = function (dir) {
 83             var tank = this.el;
 84             if (dir == 'up') {
 85                 setCss(tank, 'backgroundPosition', '0 0');
 86             }
 87             if (dir == 'right') {
 88                 setCss(tank, 'backgroundPosition', '-5px -36px');
 89             }
 90             if (dir == 'down') {
 91                 setCss(tank, 'backgroundPosition', '0 -73px');
 92             }
 93             if (dir == 'left') {
 94                 setCss(tank, 'backgroundPosition', '0 -105px');
 95             }
 96             this.dirState[dir] = 1;
 97         };
 98 
 99         Tank.prototype.move = function (dir) {
100             if (this.activeState != 0) return false; //正在运动我们便不管他
101             this.activeState = 1; //将当前状态设置为正在运动
102             if (this.direction != dir) {
103                 this.direction = dir;
104                 this.setDirection(dir);
105             }
106             //处理运动中的定时器
107             if (this.tid) {
108                 clearTimeout(this.tid);
109                 this.tid = null;
110             }
111             var state = this.dirState[dir];
112             var tank = this.el;
113             if (state == 1 || state == -1) {
114                 var strPos = getCss(tank, 'backgroundPosition');
115                 var arrPos = strPos.split(' ');
116                 var l = arrPos ? arrPos[0] : 0;
117                 var t = arrPos ? arrPos[1] : 0;
118                 var curPos = parseInt(l);
119                 var top = parseInt(t);
120                 var po = curPos - (43) * (state);
121                 var curPos = po + 'px ' + t + 'px';
122                 setCss(tank, 'backgroundPosition', curPos);
123             }
124             var xpos = getCss(tank, 'left') ? getCss(tank, 'left') : 0;
125             var ypos = getCss(tank, 'top') ? getCss(tank, 'top') : 0;
126             xpos = parseInt(xpos);
127             ypos = parseInt(ypos);
128             var mx = MyGlobal.mapWidth - 32;
129             var my = MyGlobal.mapHeight - 32;
130             switch (dir) {
131                 case 'up': ypos <= 0 ? 0 : ypos--; break;
132                 case 'right': xpos >= mx ? mx : xpos++; break;
133                 case 'down': ypos >= my ? my : ypos++; break;
134                 case 'left': xpos <= 0 ? 0 : xpos--; break;
135             }
136             setCss(tank, 'left', xpos + 'px');
137             setCss(tank, 'top', ypos + 'px');
138             var scope = this;
139             var speed = this.speed;
140             var repeat = function () {
141                 scope.move(dir);
142             };
143             if (!this.tid) {
144                 this.tid = setTimeout(repeat, speed);
145             }
146             //移动结束
147             this.activeState = 0;
148         }
149         Tank.prototype.stop = function () {
150             clearTimeout(this.tid);
151             this.tid = null;
152         };
153 
154         var tank = new Tank('me', 'up', 100, 100);
155         tank.init();
156 
157         function getDir(code) {
158             if (code == '87' || code == '119') {
159                 return 'up';
160             }
161             if (code == '100' || code == '68') {
162                 return 'right';
163             }
164             if (code == '115' || code == '83') {
165                 return 'down';
166             }
167             if (code == '97' || code == '65') {
168                 return 'left';
169             }
170             return null;
171         }
172 
173         document.onkeydown = function (evt) {
174             evt = (evt) ? evt : window.event;
175             var keyCode = evt.keyCode;
176             var charCode = evt.charCode;
177             var dir = getDir();
178             if (keyCode) {
179                 dir = getDir(keyCode.toString());
180             }
181             if (charCode) {
182                 dir = getDir(charCode.toString());
183             }
184             tank.move(dir);
185 
186             evt.preventDefault();
187             return false;
188         };
189         document.onkeyup = function (evt) {
190             tank.stop();
191         };
192         document.onkeypress = function (evt) {
193             evt = (evt) ? evt : window.event;
194             var keyCode = evt.keyCode;
195             var charCode = evt.charCode;
196             var dir = getDir();
197             if (keyCode) {
198                 dir = getDir(keyCode.toString());
199             }
200             if (charCode) {
201                 dir = getDir(charCode.toString());
202             }
203             tank.move(dir);
204 
205             evt.preventDefault();
206             return false;
207         };
208     </script>
209 </body>
210 </html>
完整代码
 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 };

完整代码:

  1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2 <html xmlns="http://www.w3.org/1999/xhtml">
  3 <head>
  4     <title></title>
  5     <style type="text/css">
  6         .map { background: gray; border: 1px solid black; position: relative; margin: 50px auto; width: 416px; height: 416px; }
  7         .tank { background-image: url("//images0.cnblogs.com/blog/294743/201306/12123133-eaa9ada8690e4216a2bee3e56442e032.gif"); background-repeat: no-repeat; overflow: hidden; position: absolute; width: 32px; height: 32px; z-index: 3; }
  8         .bullet { background-image: url('//images0.cnblogs.com/blog/294743/201306/12123510-662de29d9e0c447389b42fcb47bff652.gif'); width: 8px; height: 8px; position: absolute; z-index: 4; background-repeat: no-repeat; }
  9         .Boom { background-image: url('//images0.cnblogs.com/blog/294743/201306/12121341-0e6fba003915418a909cde86d0b8aac6.png'); width: 64px; height: 64px; position: absolute; z-index: 4; }
 10     </style>
 11 </head>
 12 <body>
 13     <div class="map" id="map">
 14         <div id="me" class="tank">
 15         </div>
 16     </div>
 17     <script type="text/javascript">
 18         function getById(id) {
 19             return !id ? null : document.getElementById(id);
 20         }
 21 
 22         function getAttr(el, k) {
 23             if (el) {
 24                 var v = el.getAttribute[k] ? el.getAttribute[k] : null;
 25                 return v;
 26             }
 27         }
 28 
 29         function setAttr(el, k, v) {
 30             if (el) {
 31                 el.setAttribute(k, v);
 32             }
 33         }
 34 
 35         function getCss(el, k) {
 36             if (el) {
 37 
 38                 if (el.style[k]) {
 39                     return el.style[k];
 40                 }
 41                 return null;
 42             }
 43         }
 44 
 45         function setCss(el, k, v) {
 46             if (el) {
 47                 if (!el.style || el.style.length == 0) {
 48                     el.style = {};
 49                 }
 50                 el.style[k] = v;
 51             }
 52         }
 53 
 54         var MyGlobal = {
 55             mapWidth: 416,
 56             mapHeight: 416,
 57             width: 448,
 58             height: 512
 59         };
 60 
 61         //子弹对象
 62         var Bullet = function (dir) {
 63             this.direction = dir ? dir : 'up';
 64             this.speed = 5;
 65             var factor = 0;
 66             this.tid = null;
 67             this.activeState = 0;
 68             this.blastState = 0; //爆炸状态 0-4
 69             this.blastReason = 0; //爆炸原因 0一般爆炸,4 集中坦克 3......
 70             this.x = 0;
 71             this.y = 0;
 72             if (dir) {
 73                 switch (dir) {
 74                     case 'up': factor = 0; break;
 75                     case 'right': factor = 1; break;
 76                     case 'down': factor = 2; break;
 77                     case 'left': factor = 3; break;
 78                 }
 79             }
 80             var el = document.createElement('div');
 81             var bp = 'background-position :' + (0 - 8 * factor) + 'px  0 ;';
 82             el.setAttribute('style', bp);
 83             el.setAttribute('class', 'bullet');
 84             this.el = el;
 85         };
 86 
 87         Bullet.prototype.move = function () {
 88 
 89             var bullet = this.el;
 90             var dir = this.direction;
 91             var xpos = getCss(bullet, 'left') ? getCss(bullet, 'left') : 0;
 92             var ypos = getCss(bullet, 'top') ? getCss(bullet, 'top') : 0;
 93             xpos = parseInt(xpos);
 94             ypos = parseInt(ypos);
 95             var mx = MyGlobal.mapWidth - 8;
 96             var my = MyGlobal.mapHeight - 8;
 97             var stop = false;
 98             switch (dir) {
 99                 case 'up':
100                     if (ypos <= 0) {
101                         stop = true;
102                     } else {
103                         ypos--;
104                     }
105                     break;
106                 case 'right':
107                     if (xpos >= mx) {
108                         stop = true;
109                     } else {
110                         xpos++;
111                     }
112                     break;
113                 case 'down':
114                     if (ypos >= my) {
115                         stop = true;
116                     } else {
117                         ypos++;
118                     }
119                     break;
120                 case 'left':
121                     if (xpos <= 0) {
122                         stop = true;
123                     } else {
124                         xpos--;
125                     }
126                     break;
127             }
128 
129             setCss(bullet, 'left', xpos + 'px');
130             setCss(bullet, 'top', ypos + 'px');
131             this.x = xpos;
132             this.y = ypos;
133 
134             var scope = this;
135             var speed = this.speed;
136             var repeat = function () {
137                 scope.move();
138             };
139             if (this.tid) {
140                 clearTimeout(this.tid);
141                 this.tid = null;
142             }
143             if (!this.tid) {
144                 this.tid = setTimeout(repeat, speed);
145             }
146             if (stop) {
147                 this.blast();
148             }
149         };
150 
151         Bullet.prototype.blast = function (reason) {
152             var el = this.el;
153             var x = this.x - 28;
154             var y = this.y - 28;
155             setCss(el, 'left', x + 'px');
156             setCss(el, 'top', y + 'px');
157             this.x = x;
158             this.y = y;
159             var scope = this;
160             setAttr(el, 'class', 'Boom');
161             setCss(scope.el, 'backgroundPosition', '0 0');
162             var action = function () {
163                 if (scope.blastState < (scope.blastReason + 1)) {
164                     var b = scope.blastState * 64 * (-1);
165                     b = b + 'px 0';
166                     setCss(scope.el, 'backgroundPosition', b);
167                     scope.blastState++;
168                     setTimeout(action, 20);
169                 } else {
170                     getById('map').removeChild(scope.el);
171                     delete scope;
172                 }
173             };
174             if (reason) {
175                 this.blastReason = reason;
176             }
177             setTimeout(action, 20);
178 
179             clearTimeout(this.tid);
180             this.tid = null;
181 
182             //    this.blastState
183 
184         };
185 
186         //坦克对象
187         var Tank = function (id, dir, x, y) {
188             this.el = getById(id);
189             this.direction = dir ? dir : 'up';
190             this.tid = null;
191             this.speed = 10;
192             //坦克活动状态 0 未活动 1 正在活动
193             this.activeState = 0;
194             this.x = x ? x : 100;
195             this.y = y ? y : 200;
196             this.dirState = {
197                 up: 1,
198                 right: 1,
199                 down: 1,
200                 left: 1
201             };
202         };
203         Tank.prototype.init = function () {
204             var dir = this.direction;
205             var tank = this.el;
206             setCss(tank, 'left', this.x + 'px');
207             setCss(tank, 'top', this.y + 'px');
208             this.setDirection(dir);
209         };
210         Tank.prototype.setDirection = function (dir) {
211             var tank = this.el;
212             if (dir == 'up') {
213                 setCss(tank, 'backgroundPosition', '0 0');
214             }
215             if (dir == 'right') {
216                 setCss(tank, 'backgroundPosition', '-5px -36px');
217             }
218             if (dir == 'down') {
219                 setCss(tank, 'backgroundPosition', '0 -73px');
220             }
221             if (dir == 'left') {
222                 setCss(tank, 'backgroundPosition', '0 -105px');
223             }
224             this.dirState[dir] = 1;
225         };
226 
227         Tank.prototype.move = function (dir) {
228             if (this.activeState != 0) return false; //正在运动我们便不管他
229             this.activeState = 1; //将当前状态设置为正在运动
230             if (this.direction != dir) {
231                 this.direction = dir;
232                 this.setDirection(dir);
233             }
234             //处理运动中的定时器
235             if (this.tid) {
236                 clearTimeout(this.tid);
237                 this.tid = null;
238             }
239             var state = this.dirState[dir];
240             var tank = this.el;
241             if (state == 1 || state == -1) {
242                 var strPos = getCss(tank, 'backgroundPosition');
243                 var arrPos = strPos.split(' ');
244                 var l = arrPos ? arrPos[0] : 0;
245                 var t = arrPos ? arrPos[1] : 0;
246                 var curPos = parseInt(l);
247                 var top = parseInt(t);
248                 var po = curPos - (40) * (state);
249                 var curPos = po + 'px ' + top + 'px';
250                 setCss(tank, 'backgroundPosition', curPos);
251                 this.dirState[dir] = state == 1 ? -1 : 1;
252 
253             }
254             var xpos = getCss(tank, 'left') ? getCss(tank, 'left') : 0;
255             var ypos = getCss(tank, 'top') ? getCss(tank, 'top') : 0;
256             xpos = parseInt(xpos);
257             ypos = parseInt(ypos);
258             var mx = MyGlobal.mapWidth - 32;
259             var my = MyGlobal.mapHeight - 32;
260             switch (dir) {
261                 case 'up': ypos <= 0 ? 0 : ypos--; break;
262                 case 'right': xpos >= mx ? mx : xpos++; break;
263                 case 'down': ypos >= my ? my : ypos++; break;
264                 case 'left': xpos <= 0 ? 0 : xpos--; break;
265             }
266             setCss(tank, 'left', xpos + 'px');
267             setCss(tank, 'top', ypos + 'px');
268             this.x = xpos;
269             this.y = ypos;
270             var scope = this;
271             var speed = this.speed;
272             var repeat = function () {
273                 scope.move(dir);
274             };
275             if (!this.tid) {
276                 this.tid = setTimeout(repeat, speed);
277             }
278             //移动结束
279             this.activeState = 0;
280         };
281 
282         Tank.prototype.stop = function () {
283             clearTimeout(this.tid);
284             this.tid = null;
285         };
286 
287         Tank.prototype.fire = function () {
288             var bullet = new Bullet(this.direction);
289             var l = (this.x + 12) + 'px';
290             var t = (this.y + 12) + 'px'
291             //    top:12px;left:12px;
292             var el = bullet.el;
293             setCss(el, 'top', t);
294             setCss(el, 'left', l);
295             bullet.y = this.y + 12;
296             bullet.x = this.x + 12;
297             getById('map').appendChild(el);
298             //    bullet.el = this.el.getElementsByTagName('div')[0];
299             bullet.move();
300         };
301 
302 
303         //实际应用
304         var tank = new Tank('me', 'right', 100, 100);
305         tank.init();
306 
307         function getDir(code) {
308             if (code == '87' || code == '119') {
309                 return 'up';
310             }
311             if (code == '100' || code == '68') {
312                 return 'right';
313             }
314             if (code == '115' || code == '83') {
315                 return 'down';
316             }
317             if (code == '97' || code == '65') {
318                 return 'left';
319             }
320             return null;
321         }
322 
323         document.onkeydown = function (evt) {
324             evt = (evt) ? evt : window.event;
325             var keyCode = evt.keyCode;
326             var charCode = evt.charCode;
327             var dir = getDir();
328             if (keyCode) {
329                 dir = getDir(keyCode.toString());
330             }
331             if (charCode) {
332                 dir = getDir(charCode.toString());
333             }
334             if (dir)
335                 tank.move(dir);
336             if (charCode == '106' || keyCode == '74') {
337                 tank.fire();
338             }
339             evt.preventDefault();
340             return false;
341         };
342         document.onkeyup = function (evt) {
343             tank.stop();
344         };
345         document.onkeypress = function (evt) {
346             evt = (evt) ? evt : window.event;
347             var keyCode = evt.keyCode;
348             var charCode = evt.charCode;
349             var dir = getDir();
350             if (keyCode) {
351                 dir = getDir(keyCode.toString());
352             }
353             if (charCode) {
354                 dir = getDir(charCode.toString());
355             }
356             if (dir)
357                 tank.move(dir);
358             if (charCode == '106' || keyCode == '74') {
359                 tank.fire();
360             }
361             evt.preventDefault();
362             return false;
363         };
364     </script>
365 </body>
366 </html>
完整代码

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

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

结语

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

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

我们后面点优化吧。

 

posted on 2013-06-12 14:33  叶小钗  阅读(5579)  评论(20编辑  收藏  举报