1 /**	
  2  * CodeTank
  3  * Copyright (c) 2012 Tencent AlloyTeam All rights reserved.
  4  *
  5  * @fileOverview CodeTank!
  6  * @version	1.0
  7  * @author	Cson(<a href="mailto:csonlai1989@gmail.com">csonlai1989@gmail.com</a>)
  8  * @description 
  9  * 雷达、子弹、坦克、炮管的类
 10  */
 11 
 12 
 13 
 14 Jx().$package("tank", function(J) {
 15    /**
 16 	* @namespace	
 17 	* @name tank
 18 	* @type Object
 19 	*/
 20 	var cg=J.cnGame,
 21 		core=J.cnGame.core,
 22 		Sprite=J.cnGame.Sprite,
 23 		spriteList=J.cnGame.spriteList,
 24 		Line=J.cnGame.shape.Line,
 25 		Circle=J.cnGame.shape.Circle,
 26 		Text=J.cnGame.shape.Text,
 27 		SS=J.cnGame.SpriteSheet,
 28 		srcObj=config.srcObj,
 29 		uiObj=config.uiObj,
 30 		battleTopMargin = 98,
 31 		Polygon=J.cnGame.shape.Polygon;
 32 
 33 	var ui=this.ui={
 34 		"classic":[
 35 			uiObj.classicBody,
 36 			uiObj.classicGun,
 37 			uiObj.classicRadar,
 38 			uiObj.classicBullet
 39 		],
 40 		// 红
 41 		"red":[
 42 			uiObj.redBody,
 43 			uiObj.redGun,
 44 			uiObj.redRadar,
 45 			uiObj.redBullet
 46 		],
 47 		// 橙
 48 		"orange":[
 49 			uiObj.orangeBody,
 50 			uiObj.orangeGun,
 51 			uiObj.orangeRadar,
 52 			uiObj.orangeBullet
 53 		],
 54 		// 黄
 55 		"yellow":[
 56 			uiObj.yellowBody,
 57 			uiObj.yellowGun,
 58 			uiObj.yellowRadar,
 59 			uiObj.yellowBullet
 60 		],
 61 		// 绿
 62 		"green":[
 63 			uiObj.greenBody,
 64 			uiObj.greenGun,
 65 			uiObj.greenRadar,
 66 			uiObj.greenBullet
 67 		],
 68 		// 靛
 69 		"indigo":[
 70 			uiObj.indigoBody,
 71 			uiObj.indigoGun,
 72 			uiObj.indigoRadar,
 73 			uiObj.indigoBullet
 74 		],
 75 		// 蓝
 76 		"blue":[
 77 			uiObj.blueBody,
 78 			uiObj.blueGun,
 79 			uiObj.blueRadar,
 80 			uiObj.blueBullet
 81 		],
 82 		// 紫
 83 		"purple":[
 84 			uiObj.purpleBody,
 85 			uiObj.purpleGun,
 86 			uiObj.purpleRadar,
 87 			uiObj.purpleBullet
 88 		],
 89 		// 金
 90 		"gold":[
 91 			uiObj.goldBody,
 92 			uiObj.goldGun,
 93 			uiObj.goldRadar,
 94 			uiObj.goldBullet
 95 		],	
 96 		// 白
 97 		"white":[
 98 			uiObj.whiteBody,
 99 			uiObj.whiteGun,
100 			uiObj.whiteRadar,
101 			uiObj.whiteBullet
102 		]				
103 	}
104     var angleToRadian=function(angle){
105     	return angle/180*Math.PI;
106     }
107     var radianToAngle=function(radian){
108     	return radian*180/Math.PI;
109     }	
110 	/**
111 	 *限制角度在0-360内
112 	**/
113 	var restrictAngle=function(angle){
114 		if(angle>Math.PI*2||angle<-Math.PI*2){
115 			angle%=Math.PI*2;
116 		}
117 		if(angle<0) angle+=Math.PI*2;
118 		return angle;
119 	};    
120 	/*	子弹类 */
121 	var Bullet=this.Bullet=new J.Class({extend : J.cnGame.Sprite},(function(){						  
122 		return {
123 			/**
124 			 * 初始化 
125 			 */
126 			init:function(options){
127 				
128 				this.robot=null;
129 				Bullet.superClass.init.call(this,options);
130 				this.powerScope=this.powerScope||[1,3];//子弹能量范围
131 				this.power=Math.max(this.powerScope[0],Math.min(this.powerScope[1],this.power));//修正power值
132 				
133 			},
134 			/**
135 			 * 返回子弹的速度 
136 			 * @function
137 			 * @name getSpeed
138 			 * @memberOf Bullet.prototype
139 			 * 
140 			 * @return {Number} 返回子弹速度值
141 			 */
142 			getSpeed:function(){
143 				return this.speed[0];
144 			},
145 			/**
146 			 * 返回子弹的角度 
147 			 * @function
148 			 * @name getHeading
149 			 * @memberOf Bullet.prototype
150 			 * 
151 			 * @return {Number} 返回子弹的角度 
152 			 */
153 			getHeading:function(){
154 				return radianToAngle(restrictAngle(this.angle));
155 			},
156 			/**
157 			 * 返回某个对象相对于子弹的角度 
158 			 * 
159 			 * @name getBearing
160 			 * @function
161 			 * @memberOf Bullet.prototype
162 			 * @param {Object} obj 相对的对象
163 			 * @return {Number} 返回某个对象相对于子弹的角度 
164 			 */
165 			getBearing:function(obj){
166 				return this.getRelatedAngle(obj);
167 			},
168 			/**
169 			 * 子弹击中爆炸    
170 			 * @name explode
171 			 * @function	
172 			 * @memberOf Bullet.prototype
173 			 */
174 			explode:function(){//爆炸位置
175 				var self=this;
176 				this.pos=[this.pos[0]-this.size[0]/2,this.pos[1]-this.size[1]/2];
177 				this.stop();
178 				this.isExplode=true;
179 				var explodeAnimation=new SS({id:"explode",size:[184,46],frameSize:[46,46],src:self.explodeSrc,onFinish:function(){self.disappear();}});//添加爆炸动画
180 				this.addAnimation(explodeAnimation);
181 				if(config.isPlaySound){
182 					var audio=cg.loader.loadedAudios[srcObj.bulletExplode];
183 					if(audio){
184 						audio.currentTime=0;
185 						audio.play();
186 					}
187 				}
188 				this.setCurrentAnimation("explode");
189 			},
190 			/**
191 			 * 子弹消失 
192 			 * 
193 			 * @name disappear
194 			 * @function	
195 			 * @memberOf Bullet.prototype
196 			 */
197 			disappear:function(){
198 				gameObj.spriteList.remove(this);
199 
200 			}
201 
202 		}
203 	})());
204 
205 	/**
206 	 * 火炮
207 	 * @class Gun
208 	 * @constructor Gun
209 	 * @param {Object} options 参数对象
210 	 * @return 火炮实例
211 	 */						  
212 					
213 	var Gun=this.Gun=new J.Class({extend : J.cnGame.Sprite},(function(){
214 										 
215 		return {
216 			/**
217 			*初始化
218 			**/
219 			init:function(options){
220 				this.robot=null;
221 				Gun.superClass.init.call(this,options);
222 				this.heat=0;//热度
223 				this.coldRate=this.coldRate||0.1;//冷却速度
224 				//this.fireHurt=this.fireHurt||1;//发射子弹的能量损耗
225 				this.heatAddFunc=this.heatAddFunc||function(power){return power/2;};//炮管加热的计算
226 				this.turnSpeed=this.turnSpeed||Math.PI/40;
227 				
228 			},
229 			isStop:function(){
230 				return this.speed[0]==0&&this.speed[1]==0;
231 			},
232 			/**
233 			 * 设置子弹的参数值
234 			 * 
235 			 * @name setBullet
236 			 * @function
237 			 * @memberOf Gun.prototype
238 			 * @param {Object} options 参数对象
239 			 */
240 			setBullet:function(options){
241 				this.bulletOpt=options;//保存子弹基本参数
242 				
243 			},
244 			/**
245 			 * 开火
246 			 * 
247 			 * @name fire
248 			 * @function
249 			 * @memberOf Gun.prototype
250 			 * @param {Number} power 子弹能量
251 			 * @return {Number} 返回子弹对象
252 			 */
253 			fire:function(power){
254 				var newBullet;
255 				var self=this;
256 				if(this.heat==0){
257 					this.addHeat(power);
258 					this.robot.hurt(power);
259 					var bulletPos=[self.pos[0]+30*Math.cos(self.angle),self.pos[1]-30*Math.sin(self.angle)];//炮弹发出位置
260 					var bulletOpt=cg.core.extend(this.bulletOpt,{src:self.robot.ui[3],angle:self.angle,pos:bulletPos,power:power});
261 					newBullet=new Bullet(bulletOpt);
262 					gameObj.spriteList.add(newBullet);
263 					
264 					if(config.isPlaySound){
265 						var audio=cg.loader.loadedAudios[srcObj.gun];
266 						if(audio){
267 							audio.currentTime = 0;
268 							audio.play();
269 						}
270 					}
271 				}
272 				return newBullet;	
273 			},
274 			/**
275 			 * 获取火炮朝向角度
276 			 * 
277 			 * @name getHeading
278 			 * @function
279 			 * @memberOf Gun.prototype
280 			 * @return {Number} 返回robot角度
281 			 */
282 			getHeading:function(){
283 				return radianToAngle(restrictAngle(this.angle));
284 			},
285 			/**
286 			 * 返回某对象相对于火炮的角度
287 			 * 
288 			 * @name getBearing
289 			 * @function
290 			 * @memberOf Gun.prototype
291 			 * @return {Number} 返回某对象相对于火炮的角度
292 			 */
293 			getBearing:function(obj){
294 				return this.getRelatedAngle(obj);
295 			},
296 			/**
297 			*炮管加热
298 			**/		
299 			addHeat:function(power){
300 				this.heat+=this.heatAddFunc(power);
301 			},
302 			/**
303 			*炮管冷却
304 			**/
305 			cold:function(){
306 				this.heat=Math.max(0,this.heat-this.coldRate);
307 			},
308 			/**
309 			*更新
310 			**/
311 			update:function(duration){
312 				Gun.superClass.update.call(this,duration);
313 				this.setCurrentImage(this.robot.ui[1],[0,0],this.size);
314 				if(this.heat>0){
315 					this.cold();
316 				}
317 			}
318 		}
319 	})());
320 
321 	/**
322 	 * 雷达
323 	 * @class Radar
324 	 * @constructor Radar
325 	 * @param {Object} options 参数对象
326 	 * @return 雷达实例
327 	 */			
328 	var Radar=this.Radar=new J.Class({extend : J.cnGame.Sprite},(function(){	
329 
330 		var isInnerArea=function(radar,point,polygonLines){
331 			var robot=radar.robot;
332 			var count=0;
333 			var crossPointArr=[];//相交的点的数组
334 			var crossPoint;
335 			var leftLine=new Line({start:point,end:[point[0]-9999,point[1]]});//左射线
336 			var lines=polygonLines;
337 			for(var i=0,len=lines.length;i<len;i++){
338 				var l=lines[i];
339 				crossPoint=l.isCross(leftLine);
340 		
341 				if(crossPoint){
342 					for(var j=0,len2=crossPointArr.length;j<len2;j++){
343 		                //如果交点和之前的交点相同,即表明交点为多边形的顶点
344 		                if(crossPointArr[j][0]==crossPoint[0]&&crossPointArr[j][1]==crossPoint[1]){
345 		                    break;    
346 		                }
347 			        }		         
348 			        if(j==len2){//没有和之前的交点相同,则添加
349 		                crossPointArr.push(crossPoint);    
350 		                count++;
351 			        }
352 				}
353 			}
354 		    if(count%2==0){
355 		        return false;
356 		    }
357 		    else if(crossPoint&&count==1&&crossPoint[0]==robot.pos[0]&&crossPoint[1]==robot.pos[1]){
358 		    	var rightLine=new Line({start:point,end:[point[0]+9999,point[1]]});//右射线
359 		    	for(var i=0,len=lines.length;i<len;i++){
360 		    		var l=lines[i];
361 		    		if(l.isCross(rightLine)){
362 		    			return true;
363 		    		}
364 		    	}
365 	    		return false;
366 		    }
367 		    return true;//包含
368 		};
369 		return {
370 			/**
371 			*初始化
372 			**/
373 			init:function(options){
374 				Radar.superClass.init.call(this,options);
375 				this.scanStyle=this.scanStyle||"blue";//雷达素描区域颜色
376 				this.scanRadian=this.scanRadian||Math.PI/18;//素描区域角度
377 				this.rayArr=[];//雷达射线数组
378 				this.density=this.density||15;//射线密度
379 				this.maxLength=2000;//射线长度
380 				this.dRad=this.scanRadian/this.density;//角度之间的夹角角度
381 				this.rads=[this.angle+this.scanRadian/2,this.angle-this.scanRadian/2];//区域左右边界的角度
382 				this.turnSpeed=this.turnSpeed||Math.PI/40;
383 				this.scan();
384 			},
385 			/**
386 			*雷达开始检测
387 			**/
388 			scan:function(){
389 				//this.robot.runScan=true;
390 				var rads=this.rads=[this.angle+this.scanRadian/2,this.angle-this.scanRadian/2];//更新区域左右边界的角度
391 				var maxLength=this.maxLength;
392 				var startPos=this.pos;
393 				var leftPoint=[this.pos[0]+Math.cos(rads[0])*maxLength,this.pos[1]-Math.sin(rads[0])*maxLength];
394 				var rightPoint=[this.pos[0]+Math.cos(rads[1])*maxLength,this.pos[1]-Math.sin(rads[1])*maxLength];
395 				this.scanArea=new Polygon({pointsArr:[startPos,leftPoint,rightPoint],style:this.scanStyle});
396 			},
397 			isScan:function(robot){
398 				//if(this.robot.isStop()) return false;
399 
400 				var lines=this.scanArea.getLineSegs();
401 				if(this.runScan&&isInnerArea(this,robot.pos,lines)){
402 					return true;
403 				}	
404 				return false;
405 			},
406 			isStop:function(){
407 				return this.speed[0]==0&&this.speed[1]==0;
408 			},			
409 			/**
410 			 * 设置雷达射线颜色
411 			 * 
412 			 * @name setScanStyle
413 			 * @function
414 			 * @memberOf Radar.prototype
415 			 * @param {String} style 射线颜色
416 			 */
417 			setScanStyle:function(style){
418 				this.scanStyle=style;
419 			},
420 			/**
421 			 * 获取雷达朝向角度
422 			 * 
423 			 * @name getHeading
424 			 * @function
425 			 * @memberOf Radar.prototype
426 			 * @return {Number} 返回雷达朝向角度
427 			 */
428 			getHeading:function(){
429 				return radianToAngle(restrictAngle(this.angle));
430 			},
431 			/**
432 			 * 获取某对象相对于雷达的朝向角度
433 			 * 
434 			 * @name getBearing
435 			 * @function
436 			 * @memberOf Radar.prototype
437 			 * @param {Object} obj 相对对象     
438 			 * @return {Number} 某对象相对于雷达的朝向角度
439 			 */
440 			getBearing:function(obj){
441 				return this.getRelatedAngle(obj);
442 			},
443 			/**
444 			*消失
445 			**/
446 			disappear:function(){
447 				gameObj.spriteList.remove(this);
448 			},
449 			/**
450 			*重写update
451 			**/
452 			update:function(duration){
453 				Radar.superClass.update.call(this,duration);
454 				this.setCurrentImage(this.robot.ui[2],[0,0],this.size);
455 				if(this.runScan)
456 				this.scan();
457 			},
458 			/**
459 			*重写draw
460 			**/
461 			draw:function(){
462 
463 				//if(config.isShowRadar&&this.runScan)
464 				if(config.isShowRadar)
465 				this.scanArea.draw();
466 
467 				Radar.superClass.draw.call(this);
468 			}
469 			
470 		}
471 	})());
472 
473 	/**
474 	 *		
475 	 * @memberOf tank
476 	 * @class
477 	 * @name Robot
478 	 * @param {Object} options 初始化参数
479 	 * @return Robot实例
480 	 */
481 	var Robot=this.Robot=new J.Class({extend : J.cnGame.Sprite},(function(){	
482 
483 		/**
484 		 * tank 对话框
485 		 */
486 		var TankMsgBox = function (tank, msg, color) {
487 			this.tank = tank;
488 			this.msg = msg;
489 			this.color = color;
490 			
491 			this._init();
492 		};
493 		TankMsgBox.prototype = {
494 			_init: function () {
495 				this._createDom();
496 				this.update();
497 			},
498 			_createDom: function () {
499 				if (!this.dom) {
500 					this.dom = document.createElement('div');
501 					this.textDom = document.createElement('div');
502 					this.arrowDom = document.createElement('div');
503 					
504 					this.dom.className = 'tankMsgBox';
505 					this.textDom.className = 'tankMsgBoxText';
506 					this.arrowDom.className = 'tankMsgBoxArrow';
507 					this.dom.style.display = 'none';
508 					document.body.appendChild(this.dom);
509 					this.dom.appendChild(this.textDom);
510 					this.dom.appendChild(this.arrowDom);
511 					
512 				}
513 				return this.dom;
514 			},
515 			update: function () { 
516 				var canvasTop=J.cnGame.pos[1];
517 				var canvasLeft=J.cnGame.pos[0];
518 				if (this.isVisible() && this.dom) {
519 					var pos = this.tank.getPos(),
520 						dim = {
521 							width: this.dom.offsetWidth,
522 							height: this.dom.offsetHeight
523 						};
524 					
525 					this.arrowDom.style.left = dim.width/2-3 + 'px';
526 					this.dom.style.left = pos[0]-(dim.width/2) + canvasLeft+ 'px';//20为canvas 左边距
527 					this.dom.style.top = pos[1]-dim.height + canvasTop - 58 + 'px';
528 				}
529 			},
530 			getMsg: function () {
531 				return this.msg;
532 			},
533 			setMsg: function (msg, color) {
534 				if (msg) this.msg = msg;
535 				color = color || "#aaa";
536 				//this.dom.innerHTML = msg;
537 				if (this.dom) {
538 					this.textDom.innerHTML = msg;
539 					this.dom.style.color = color;
540 				}
541 				
542 				//this.dom.style.borderColor = color;
543 			},
544 			show: function (msg, color) {
545 				var me = this;
546 				msg && this.setMsg(msg, color);
547 				//if (time == undefined) time = 500;
548 				var time = 3000;
549 				if (this.dom) this.dom.style.display = 'block';
550 				this.update();
551 				
552 				clearTimeout(this.__timer)
553 				this.__timer = setTimeout(function () {
554 					me.hide();
555 					
556 					/*if (me.tank.energy <= 0) {
557 						//me.destory();
558 
559 					}*/
560 				}, time);
561 			},
562 			hide: function () {
563 				if (this.dom) this.dom.style.display = 'none';
564 			},
565 			isVisible: function () {
566 				return !(this.dom.style.display == 'none');
567 			},
568 			destory: function () {
569 				document.body.removeChild(this.dom);
570 				this.dom = null;
571 				this.textDom = null;
572 				this.arrowDom = null;
573 			}
574 		};
575         
576         // dom 的血条框
577         var DomRect = function (opt) {
578             this.opt = opt;
579             this._init();
580         };
581         DomRect.prototype = {
582             _init: function () {
583                 this._createDom();
584             },
585             _createDom: function () {
586                 var dom = document.createElement('div');
587                 dom.className = 'tankEnergyRect';
588                 document.body.appendChild(dom);
589                 this.dom = dom;
590             },
591             setOptions: function (o) {
592                 if (o.pos) this.pos = o.pos;
593                 if (o.size) this.size = o.size;
594             },
595             draw: function () {
596 				var canvasTop=J.cnGame.pos[1];
597 				var canvasLeft=J.cnGame.pos[0];
598                 if (this.dom && this.pos && this.size) {
599                 	this.dom.style['width'] = this.size[0] + 'px';
600                     this.dom.style['left'] = this.pos[0] - (this.dom.offsetWidth/2) +canvasLeft + 'px';
601                     this.dom.style['top'] = this.pos[1] + canvasTop +7+ 'px';
602                     
603                 }
604             },
605             hide: function () {
606                 this.dom.style['display'] = 'none';
607             },
608             destory: function () {
609                 document.body.removeChild(this.dom);
610                 this.dom = null;
611             }
612         };
613         
614         // dom 名字
615         var DomText = function (opt) {
616             this.opt = opt;
617             this._init();
618         };
619         DomText.prototype = {
620             _init: function () {
621                 this._createDom();
622             },
623             _createDom: function () {
624                 var dom = document.createElement('span');
625                 dom.className = 'tankNameText';
626                 document.body.appendChild(dom);
627                 this.dom = dom;
628             },
629             getWidth:function(){
630             	return this.dom.clientWidth;
631             },
632             getHeight:function(){
633             	return this.dom.clientHeight;
634             },            
635             setOptions: function (o) {
636 
637                 if (o.pos) this.pos = o.pos;
638                 if (o.style) this.style=o.style;
639                 if (o.text && !this.text) {
640                     this.text = o.text;
641                     this.dom.innerHTML = this.text;
642                 } 
643             },
644             draw: function () {
645 				var canvasTop=J.cnGame.pos[1];
646 				var canvasLeft=J.cnGame.pos[0];
647                 if (this.dom && this.pos && this.text) {
648                 
649              		this.dom.style['color']=this.style;
650                     this.dom.style['left'] = this.pos[0] - (this.dom.offsetWidth/2) + canvasLeft + 'px';
651                     this.dom.style['top'] = this.pos[1] + canvasTop -3 + 'px';
652                 }
653             },
654             hide: function () {
655                 this.dom.style['display'] = 'none';
656             },
657             destory: function () {
658                 document.body.removeChild(this.dom);
659                 this.dom = null;
660             }
661         };
662 
663         var DomArea=function(opt){
664         	this.opt=opt;
665         	this._init();
666         };
667         DomArea.prototype={
668         	_init:function(){
669         		this._createDom();
670         	},
671             _createDom: function () {
672             	var mask=document.createElement('span');
673             	mask.className="tankMask";
674                 var btn = document.createElement('span');
675                 btn.className = 'deletBtn panelCloseButton';
676                 btn.innerHTML="x";
677                 mask.appendChild(btn);
678                 this.btn = btn;
679                 this.mask=mask;
680             },
681             getWidth:function(){
682             	return this.mask.clientWidth;
683             },
684             getHeight:function(){
685             	return this.mask.clientHeight;
686             },
687             setOptions: function (o) {
688                 if (o.pos) this.pos = o.pos;
689                 if (o.size) this.size = o.size;
690                 var r=this.opt.robot;
691                 r.nameText.dom.appendChild(this.mask);
692             },
693             draw: function () {
694                 if (this.mask && this.size) {
695                 	this.mask.style['width'] = this.size[0] + 'px';
696                 	this.mask.style['height'] = this.size[1] + 'px';       
697                 }
698                 
699             },
700             show:function(){
701             	this.btn.style['display'] = 'block';
702             },
703             hide: function () {
704                 this.btn.style['display'] = 'none';
705             },
706             destory: function () {
707             	var r=this.opt.robot;
708                 this.mask.removeChild(this.btn);
709                 r.nameText.dom.removeChild(this.mask);
710                 this.btn = null;
711                 this.mask = null;
712             }
713         };
714 
715         var teamColorObj={
716         	"1":"red",
717         	"2":"yellow"
718         };
719         var createCanvas=function(width,height,left,top){
720 			var robotCanvas=document.createElement("canvas");
721 			//robotCanvas.style.background="rgba(152,133,107,0.5)";
722 			robotCanvas.style.position="absolute";
723 			robotCanvas.style.top=top+"px";
724 			robotCanvas.style.left=left+"px";
725 			robotCanvas.width=width;
726 			robotCanvas.height=height;  
727 			return robotCanvas;      	
728         }
729 
730 
731 		return {
732 			/**
733 			*初始化
734 			**/
735 			init:function(options){
736 				var self=this;
737 				Robot.superClass.init.call(this,options);
738 		
739                 // 名字和血条是否使用dom实现
740                 this.useDom = true;
741 				this.energy=this.energy||100;
742 				this.teamColor=teamColorObj[this.teamColor];
743 				this.name=this.name||"test";
744 				this.nameText= this.useDom ? new DomText({style: this.teamColor}) : new Text({style:this.teamColor});
745 				this.energyRect= this.useDom ? new DomRect({style: 'rgb(40, 249, 59)'}) : new cg.shape.Rect({style:"rgb(40,249,59)"});//血条
746 				this.deleteArea= new DomArea({robot:this});
747 				this.moveSpeed=this.moveSpeed||5;//robot移动速度
748 				this.turnSpeed=this.turnSpeed||Math.PI/80;//robot旋转速度
749 
750 
751 				
752 				this.setAdjustGunForRobotTurn(false);
753 				this.setAdjustRadarForGunTurn(false);
754 				this.setAdjustRadarForRobotTurn(false);
755 				
756 				this.stateManager=new robotState.StateManager({owner:this});
757 				this.updateText();	
758 				
759 			},
760 			isStop:function(){
761 				return this.speed[0]==0&&this.speed[1]==0&&this.radar.isStop()&&this.gun.isStop();
762 			},			
763 			/**
764 			 * 说话
765 			 * @function
766 			 * @name say
767 			 * @memberOf tank.Robot.prototype
768 			 * @param {String} words
769 			 * @param {String} color
770 			 */
771 			say: function (words, color) {
772 				if(!config.isShowMsg) return;
773 				if (!this.msgBox) {
774 					this.msgBox = new TankMsgBox(this, words, color);
775 				}
776 				this.msgBox.show(words, color);
777 			},
778 			/*setName:function(name){
779 				this.name=name;
780 				return this;
781 			},*/
782 			/**
783 			 * 更换UI
784 			 * 
785 			 * @name setUI
786 			 * @function
787 			 * @memberOf tank.Robot.prototype
788 			 * @param {Object} ui ui对象(如tank.ui["green"])   
789 			 * @return {Object} 坦克实例
790 			 */
791 			setUI:function(newUI){
792 	
793 				this.ui=newUI||ui.orange;
794 				var self=this;
795 				var loadedImgsObj=cg.loader.loadedImgs;
796 		
797 				cg.loader.load(this.ui[0],function(img){
798 					var src=img.srcPath;
799 					self.tbody=new cg.SpriteSheet({id:"tbody",size:[38,76],src:src,frameSize:[38,38],direction:"down",loop:true});
800 					self.setCurrentAnimation(self.tbody);
801 
802 				});				
803 				cg.loader.load(this.ui[1],function(img){
804 					var src=img.srcPath;
805 					self.gunSrc=src;
806 					self.gun.setCurrentImage(src);//更新ui
807 				});
808 				cg.loader.load(this.ui[2],function(img){
809 					var src=img.srcPath;
810 					self.radarSrc=src;
811 					self.radar.setCurrentImage(src);//更新ui
812 				}); 
813 
814 				cg.loader.load(this.ui[3],function(img){
815 					var src=img.srcPath;
816 					self.bulletSrc=src;
817 				});                			
818 				
819 				return this;
820 			},
821 			/**
822 			 * 返回绘制坦克的2Dcontext
823 			 * @name getGraphics
824 			 * @function
825 			 * @memberOf tank.Robot.prototype
826 			 * @return {Object} 返回绘制坦克的2Dcontext
827 			 */	
828 			getGraphics:function(){
829 				var area=this.deleteArea;
830 				var w=area.getWidth();
831 				var h=area.getHeight();
832 				var canvasW=80;
833 				var canvasH=h;
834 
835 				if(!this.robotDrawContext){
836 					
837 					var name=this.nameText;
838 					
839 					var robotCanvas=createCanvas(canvasW,canvasH,(name.getWidth()-80)/2,14);
840 					area.mask.appendChild(robotCanvas);
841 
842 					var robotDrawContext=robotCanvas.getContext('2d');
843 					this.robotDrawContext=robotDrawContext;
844 				}
845 				this.robotDrawContext.clearRect(0,0,canvasW,canvasH);
846 				this.robotDrawContext.save();
847 				this.robotDrawContext.translate(canvasW/2,42);//坦克中点
848 				this.robotDrawContext.rotate(this.angle * -1);
849 				return this.robotDrawContext;
850 			},			
851 			/**
852 			*绘制robot
853 			**/
854 			draw:function(){
855 				Robot.superClass.draw.call(this);
856 				this.gun.draw();		
857 				this.radar.draw();
858 				this.drawText();
859 			
860 				if(this.constructor.prototype.hasOwnProperty("onPaint")){//用户实现了onPaint处理程序
861 					var context=this.getGraphics();
862 					tank.event.notifyPaintEvent(this,context);//robot绘制前的回调
863 					context.restore();
864 				}
865 			},
866 			/**
867 			*更新文本
868 			**/		
869 			updateText:function(){
870 				var self=this;
871 				if(this.nameText&&this.energyRect&&this.deleteArea){
872 					this.nameText.setOptions({pos:[this.pos[0],this.pos[1]-50],text: self.name,style:this.teamColor});
873 					this.energyRect.setOptions({pos:[this.pos[0],this.pos[1]-40],size:[self.energy/2,3]});
874 					this.deleteArea.setOptions({pos:[this.pos[0],this.pos[1]],size:[this.nameText.dom.clientWidth+20,80]});
875 				}
876 
877 			},
878 			/**
879 			*绘制文本
880 			**/	
881 			drawText:function(){
882 				var self=this;
883 				if(this.nameText&&this.energyRect&&this.deleteArea){
884 					this.nameText.setOptions({text: self.name});
885 					this.nameText.draw();
886 					this.energyRect.draw();
887 					this.deleteArea.draw();
888 				}
889 
890 				
891 			},
892 			/**
893 			*设置雷达
894 			**/
895 			setRadar:function(options){
896 				options.angle*=-1;
897 				var self=this;
898 				this.setOptions.call(options,{pos:self.pos,robot:self,angle:self.angle,src:self.radarSrc});//添加对robot的引用,中点位置,角度与robot一致
899 				this.radar=new Radar(options);
900 		
901 			},
902 			/**
903 			*设置火炮
904 			**/
905 			setGun:function(options){
906 				options.angle*=-1;
907 				var self=this;
908 				this.setOptions.call(options,{pos:self.pos,robot:self,angle:self.angle,src:self.gunSrc});//添加对robot的引用,中点位置,角度与robot一致
909 				this.gun=new Gun(options);
910 			},
911 			/**
912 			*设置子弹
913 			**/
914 			setBullet:function(options){
915 				var self=this;
916 				cg.core.extend(options,{robot:self,src:self.bulletSrc});//增加对robot的引用
917 				this.gun.setBullet(options);
918 			},
919 			/**
920 			 * 返回剩余的移动距离
921 			 * 
922 			 * @name getDistanceRemaining
923 			 * @function
924 			 * @memberOf tank.Robot.prototype
925 			 * @return {Number} 剩余移动距离
926 			 */			
927 			getDistanceRemaining:function(){
928 				return this.distanceRemaining;
929 			},
930 			/**
931 			 * 返回剩余的旋转角度
932 			 * 
933 			 * @name getTurnRemaining
934 			 * @function
935 			 * @memberOf tank.Robot.prototype
936 			 * @return {Number} 剩余旋转角度
937 			 */			
938 			getTurnRemaining:function(){
939 				return radianToAngle(this.radianRemaining);
940 			},	
941 			/**
942 			 * 返回大炮剩余的旋转角度
943 			 * 
944 			 * @name getGunTurnRemaining
945 			 * @function
946 			 * @memberOf tank.Robot.prototype
947 			 * @return {Number} 剩余大炮旋转角度
948 			 */							
949 			getGunTurnRemaining:function(){
950 				return radianToAngle(this.gun.radianRemaining);
951 			},	
952 			/**
953 			 * 返回剩余的雷达旋转角度
954 			 * 
955 			 * @name getRadarTurnRemaining
956 			 * @function
957 			 * @memberOf tank.Robot.prototype
958 			 * @return {Number} 剩余雷达旋转角度
959 			 */						
960 			getRadarTurnRemaining:function(){
961 				return radianToAngle(this.radar.radianRemaining);
962 			},	
963 			/**
964 			 * 向前走一定距离
965 			 * 
966 			 * @name ahead
967 			 * @function
968 			 * @memberOf tank.Robot.prototype
969 			 * @param {Number} distance 距离 
970 			 * @param {Function} onFinished 完成移动的回调函数 
971 			 * @return {Object} 坦克实例
972 			 */
973 			ahead:function(distance,onFinished){
974 				var self=this;
975 				var aheadState=new robotState.State(this.customState);
976 				aheadState.setOptions({
977 					name:"ahead",
978 					distance:distance,
979 					onMoveFinished:onFinished,
980 					owner:self
981 				});
982 				this.stateManager.addState(aheadState);
983 				this.customState=null;
984 				return this;
985 			},
986 			/**
987 			 * 向后走
988 			 * 
989 			 * @name back
990 			 * @function
991 			 * @param {Number} distance 后退距离
992 			 * @param {Function} onFinished 后退完成的回调函数
993 			 * @memberOf tank.Robot.prototype
994 			 * @return {Object} 坦克实例
995 			 */	
996 			back:function(distance,onFinished){
997 				distance*=-1;
998 				this.ahead(distance,onFinished);
999 				return this;
1000 			},				
1001 			/**
1002 			 * 坦克车身旋转一定角度
1003 			 * 
1004 			 * @name turn
1005 			 * @function
1006 			 * @memberOf tank.Robot.prototype
1007 			 * @param {Number} angle 旋转角度
1008 			 * @param {Function} onFinished 完成转动的回调函数 
1009 			 * @return {Object} 坦克实例
1010 			 */
1011 			turn:function(angle,onFinished){
1012 				angle*=-1;
1013 				var self=this;
1014 				var radian=angleToRadian(angle);
1015 				var turnState=new robotState.State(this.customState);
1016 				turnState.setOptions({
1017 					name:"turn",
1018 					angle:radian,
1019 					onTurnFinished:onFinished,
1020 					owner:self
1021 				});
1022 				this.stateManager.addState(turnState);
1023 				this.customState=null;
1024 				return this;				
1025 			},
1026 
1027 			/**
1028 			 * 坦克车身向右旋转一定角度
1029 			 * 
1030 			 * @name turnRight
1031 			 * @function
1032 			 * @memberOf tank.Robot.prototype
1033 			 * @param {Number} angle 旋转角度
1034 			 * @param {Function} onFinished 完成转动的回调函数 
1035 			 * @return {Object} 坦克实例
1036 			 */
1037 			turnRight:function(angle,onFinished){
1038 				this.turn(angle, onFinished);
1039 				return this;
1040 			},
1041 
1042 			/**
1043 			 * 坦克车身向左旋转一定角度
1044 			 * 
1045 			 * @name turnLeft
1046 			 * @function
1047 			 * @memberOf tank.Robot.prototype
1048 			 * @param {Number} angle 旋转角度
1049 			 * @param {Function} onFinished 完成转动的回调函数 
1050 			 * @return {Object} 坦克实例
1051 			 */
1052 			turnLeft:function(angle,onFinished){
1053 				angle*=-1;
1054 				this.turn(angle, onFinished);
1055 				return this;
1056 			},
1057 			/**
1058 			 * 火炮旋转一定角度
1059 			 * 
1060 			 * @name turnGun
1061 			 * @function
1062 			 * @memberOf tank.Robot.prototype
1063 			 * @param {Number} angle 旋转角度
1064 			 * @param {Function} onFinished 完成转动的回调函数 
1065 			 * @return {Object} 坦克实例
1066 			 */
1067 			turnGun:function(angle,onFinished){
1068 				angle*=-1;
1069 				var self=this;
1070 				var radian=angleToRadian(angle);
1071 				var turnState=new robotState.State(this.customState);
1072 				turnState.setOptions({
1073 					name:"turnGun",
1074 					gunAngle:radian,
1075 					onGunTurnFinished:onFinished,
1076 					owner:self
1077 				});
1078 				this.stateManager.addState(turnState);
1079 				this.customState=null;
1080 				return this;						
1081 			},
1082 
1083 
1084 			/**
1085 			 * 火炮向右旋转一定角度
1086 			 * 
1087 			 * @name turnGunRight
1088 			 * @function
1089 			 * @memberOf tank.Robot.prototype
1090 			 * @param {Number} angle 旋转角度
1091 			 * @param {Function} onFinished 完成转动的回调函数 
1092 			 * @return {Object} 坦克实例
1093 			 */
1094 			turnGunRight:function(angle,onFinished){
1095 				this.turnGun(angle, onFinished);
1096 				return this;
1097 			},
1098 
1099 
1100 			/**
1101 			 * 火炮向左旋转一定角度
1102 			 * 
1103 			 * @name turnGunLeft
1104 			 * @function
1105 			 * @memberOf tank.Robot.prototype
1106 			 * @param {Number} angle 旋转角度
1107 			 * @param {Function} onFinished 完成转动的回调函数 
1108 			 * @return {Object} 坦克实例
1109 			 */
1110 			turnGunLeft:function(angle,onFinished){
1111 				angle*=-1;	
1112 				this.turnGun(angle, onFinished);
1113 				return this;
1114 			},
1115 			/**
1116 			 * 雷达旋转一定角度
1117 			 * 
1118 			 * @name turnRadar
1119 			 * @function
1120 			 * @memberOf tank.Robot.prototype
1121 			 * @param {Number} angle 旋转角度
1122 			 * @param {Function} onFinished 完成转动的回调函数 
1123 			 * @return {Object} 坦克实例
1124 			 */
1125 			turnRadar:function(angle,onFinished){
1126 				angle*=-1;
1127 				var self=this;
1128 				var radian=angleToRadian(angle);
1129 				var turnState=new robotState.State(this.customState);
1130 				turnState.setOptions({
1131 					name:"turnRadar",
1132 					radarAngle:radian,
1133 					onRadarTurnFinished:onFinished,
1134 					owner:self
1135 				});
1136 				this.stateManager.addState(turnState);
1137 				this.customState=null;
1138 				return this;	
1139 			},
1140 
1141 			/**
1142 			 * 雷达向右旋转一定角度
1143 			 * 
1144 			 * @name turnRadarRight
1145 			 * @function
1146 			 * @memberOf tank.Robot.prototype
1147 			 * @param {Number} angle 旋转角度
1148 			 * @param {Function} onFinished 完成转动的回调函数 
1149 			 * @return {Object} 坦克实例
1150 			 */
1151 			turnRadarRight:function(angle,onFinished){
1152 				this.turnRadar(angle, onFinished);
1153 				return this;
1154 			},
1155 
1156 			/**
1157 			 * 雷达向左旋转一定角度
1158 			 * 
1159 			 * @name turnRadarLeft
1160 			 * @function
1161 			 * @memberOf tank.Robot.prototype
1162 			 * @param {Number} angle 旋转角度
1163 			 * @param {Function} onFinished 完成转动的回调函数 
1164 			 * @return {Object} 坦克实例
1165 			 */
1166 			turnRadarLeft:function(angle,onFinished){
1167 				angle*=-1;
1168 				this.turnRadar(angle, onFinished);
1169 				return this;
1170 			},
1171 
1172 			/**
1173 			 * 设置火炮是否独立于robot的旋转
1174 			 * 
1175 			 * @name setAdjustGunForRobotTurn
1176 			 * @function
1177 			 * @memberOf tank.Robot.prototype
1178 			 * @param {Boolean} independent 是否独立 
1179 			 * @return {Object} 坦克实例
1180 			 */
1181 			setAdjustGunForRobotTurn:function(independent){//independent:true or false
1182 				this.isAdjustGunForRobotTurn=independent;
1183 				return this;
1184 			},	
1185 			/**
1186 			 * 设置雷达是否独立于火炮的旋转
1187 			 * 
1188 			 * @name setAdjustRadarForGunTurn
1189 			 * @function
1190 			 * @memberOf tank.Robot.prototype
1191 			 * @param {Boolean} independent 是否独立 
1192 			 * @return {Object} 坦克实例
1193 			 */
1194 			setAdjustRadarForGunTurn:function(independent){
1195 				this.isAdjustRadarForGunTurn=independent;
1196 				return this;
1197 				
1198 			},
1199 			/**
1200 			 * 设置雷达是否独立于robot的旋转
1201 			 * 
1202 			 * @name setAdjustRadarForRobotTurn
1203 			 * @function
1204 			 * @memberOf tank.Robot.prototype
1205 			 * @param {Boolean} independent 是否独立 
1206 			 * @return {Object} 坦克实例
1207 			 */		
1208 			setAdjustRadarForRobotTurn:function(independent){
1209 				this.isAdjustRadarForRobotTurn=independent;
1210 				return this;
1211 			},
1212 			/**
1213 			 * 运动主函数,用户重写该函数,实现robot自定义的运动轨迹
1214 			 * 
1215 			 * @name run
1216 			 * @function
1217 			 * @memberOf tank.Robot.prototype
1218 			 */	
1219 			run:function(){},
1220 			/**
1221 			 * 停止移动
1222 			 * 
1223 			 * @name stopMove
1224 			 * @function
1225 			 * @memberOf tank.Robot.prototype
1226 			 * @return {Object} 坦克实例
1227 			 */	
1228 			stopMove:function(){
1229 				
1230 				var self=this;
1231 				
1232 				var stopState=new robotState.State(this.customState);
1233 				stopState.setOptions({
1234 					name:"stop",
1235 					angle:0,
1236 					gunAngle:0,
1237 					radarAngle:0,
1238 					distance:0,
1239 					stop:true,
1240 					owner:this
1241 				});
1242 				
1243 				this.stateManager.addState(stopState);	
1244 				this.customState=null;		
1245 				return this;	
1246 			},
1247 			cancelScan:function(){
1248 				this.radar.runScan=false;
1249 			},
1250 			/**
1251 			 * 恢复雷达扫描
1252 			 * 
1253 			 * @name scan
1254 			 * @function
1255 			 * @memberOf tank.Robot.prototype
1256 			 * @return {Object} 坦克实例
1257 			 */				
1258 			scan:function(){
1259 				var scanState=new robotState.State(this.customState);
1260 
1261 				scanState.setOptions({
1262 					scan:true,
1263 					owner:this
1264 				});	
1265 				this.stateManager.addState(scanState);
1266 				return this;			
1267 			},			
1268 			/**
1269 			*帧更新
1270 			**/
1271 			update:function(duration){
1272 						
1273 				this.stateManager.update();
1274 				
1275 				if(!this.radar.canScan&&this.isStop()) this.cancelScan();
1276 				else {
1277 					this.radar.runScan=true;
1278 					this.radar.canScan=false;
1279 				}
1280 
1281 				this.goLoop();	
1282 				Robot.superClass.update.call(this,duration);
1283 	
1284 				this.gun.update(duration);
1285 				this.radar.update(duration);
1286 				this.updateText();
1287 				this.msgBox && this.msgBox.update(duration);
1288 				this.handleCustomEvent();//处理自定义事件
1289 				if(!this.isExplode)
1290 				this.setCurrentImage(this.ui[0],[0,0],this.size);
1291 				this.speed=[0,0];
1292 				this.gun.speed=[0,0];
1293 				this.radar.speed=[0,0];
1294 			
1295 			},
1296 			goLoop:function(){
1297 				if(!this.isExplode&&!this.stateManager.getEventListLength()&&!this.stateManager.getMainListLength()&&this.loopFunc){
1298 					this.loopFunc.call(this);///事件状态队列为空时才添加
1299 				}
1300 			},
1301 			/**
1302 			 * 设置下一次执行的前进的距离
1303 			 * 
1304 			 * @name setAhead
1305 			 * @function
1306 			 * @param {Number} distance 前进的距离
1307 			 * @memberOf tank.Robot.prototype
1308 			 * @return {Object} 坦克实例
1309 			 */	
1310 			setAhead:function(distance,onFinished){
1311 				this.customState=this.customState||{};
1312 				this.customState.owner=this;
1313 				this.customState.distance=distance;
1314 				this.customState.onMoveFinished=onFinished;				
1315 				return this;
1316 			},
1317 			/**
1318 			 * 设置下一次执行旋转的角度
1319 			 * 
1320 			 * @name setTurn
1321 			 * @function
1322 			 * @param {Number} angle 旋转的角度
1323 			 * @memberOf tank.Robot.prototype
1324 			 * @return {Object} 坦克实例
1325 			 */	
1326 			setTurn:function(angle,onFinished){
1327 				angle*=-1;
1328 				this.customState=this.customState||{};
1329 				var radian=angleToRadian(angle);
1330 				this.customState.owner=this;
1331 				this.customState.angle=radian;
1332 				this.customState.onTurnFinished=onFinished;
1333 				return this;
1334 			},
1335 			/**
1336 			 * 设置下一次执行向左旋转的角度
1337 			 * 
1338 			 * @name setTurnLeft
1339 			 * @function
1340 			 * @param {Number} angle 旋转的角度
1341 			 * @memberOf tank.Robot.prototype
1342 			 * @return {Object} 坦克实例
1343 			 */	
1344 			setTurnLeft:function(angle,onFinished){
1345 				angle*=-1;
1346 				this.setTurn(angle,onFinished);
1347 				return this;
1348 			},
1349 			/**
1350 			 * 设置下一次执行向右旋转的角度
1351 			 * 
1352 			 * @name setTurnRight
1353 			 * @function
1354 			 * @param {Number} angle 旋转的角度
1355 			 * @memberOf tank.Robot.prototype
1356 			 * @return {Object} 坦克实例
1357 			 */	
1358 			setTurnRight:function(angle,onFinished){
1359 				this.setTurn(angle,onFinished);
1360 				return this;
1361 			},			
1362 			/**
1363 			 * 设置下一次火炮执行旋转的角度
1364 			 * 
1365 			 * @name setGunTurn
1366 			 * @function
1367 			 * @param {Number} angle 旋转的角度
1368 			 * @memberOf tank.Robot.prototype
1369 			 * @return {Object} 坦克实例
1370 			 */	
1371 			setGunTurn:function(angle,onFinished){
1372 				angle*=-1;
1373 				this.customState=this.customState||{};
1374 				var radian=angleToRadian(angle);
1375 				this.customState.owner=this;
1376 				this.customState.gunAngle=radian;
1377 				this.customState.onGunTurnFinished=onFinished;	
1378 				return this;
1379 			},
1380 			/**
1381 			 * 设置下一次火炮执行向左旋转的角度
1382 			 * 
1383 			 * @name setGunTurnLeft
1384 			 * @function
1385 			 * @param {Number} angle 旋转的角度
1386 			 * @memberOf tank.Robot.prototype
1387 			 * @return {Object} 坦克实例
1388 			 */				
1389 			setGunTurnLeft:function(angle,onFinished){
1390 				angle*=-1;
1391 				this.setGunTurn(angle,onFinished);
1392 				return this;
1393 			},
1394 			/**
1395 			 * 设置下一次火炮执行向右旋转的角度
1396 			 * 
1397 			 * @name setGunTurnRight
1398 			 * @function
1399 			 * @param {Number} angle 旋转的角度
1400 			 * @memberOf tank.Robot.prototype
1401 			 * @return {Object} 坦克实例
1402 			 */				
1403 			setGunTurnRight:function(angle,onFinished){
1404 				this.setGunTurn(angle,onFinished);
1405 				return this;
1406 			},
1407 			/**
1408 			 * 设置下一次雷达执行向左旋转的角度
1409 			 * 
1410 			 * @name setRadarTurnLeft
1411 			 * @function
1412 			 * @param {Number} angle 旋转的角度
1413 			 * @memberOf tank.Robot.prototype
1414 			 * @return {Object} 坦克实例
1415 			 */				
1416 			setRadarTurnLeft:function(angle,onFinished){
1417 				angle*=-1;
1418 				this.setRadarTurn(angle,onFinished);
1419 				return this;
1420 			},
1421 			/**
1422 			 * 设置下一次雷达执行向右旋转的角度
1423 			 * 
1424 			 * @name setRadarTurnRight
1425 			 * @function
1426 			 * @param {Number} angle 旋转的角度
1427 			 * @memberOf tank.Robot.prototype
1428 			 * @return {Object} 坦克实例
1429 			 */				
1430 			setRadarTurnRight:function(angle,onFinished){
1431 				this.setRadarTurn(angle,onFinished);
1432 				return this;
1433 			},			
1434 			/**
1435 			 * 设置下一次开火的能量
1436 			 * 
1437 			 * @name setFire
1438 			 * @function
1439 			 * @param {Number} power 能量值
1440 			 * @memberOf tank.Robot.prototype
1441 			 * @return {Object} 坦克实例
1442 			 */				
1443 			setFire:function(power){
1444 				power=power||1;
1445 				power=Math.min(power,3);//不能超过3的火力
1446 				this.customState=this.customState||{};
1447 				this.customState.owner=this;
1448 				this.customState.power=power;
1449 				return this;
1450 			},
1451 			/**
1452 			 * 设置下一次雷达执行旋转的角度
1453 			 * 
1454 			 * @name setRadarTurn
1455 			 * @function
1456 			 * @param {Number} angle 旋转的角度
1457 			 * @memberOf tank.Robot.prototype
1458 			 * @return {Object} 坦克实例
1459 			 */	
1460 			setRadarTurn:function(angle,onFinished){
1461 				angle*=-1;
1462 				this.customState=this.customState||{};
1463 				var radian=angleToRadian(angle);
1464 				this.customState.owner=this;
1465 				this.customState.radarAngle=radian;
1466 				this.customState.onRadarTurnFinished=onFinished;	
1467 				return this;
1468 			},
1469 			/**
1470 			 * 添加自定义组合状态
1471 			 * 
1472 			 * @name execute
1473 			 * @function
1474 			 * @param {Function} onFinished 完成的回调函数
1475 			 * @memberOf tank.Robot.prototype
1476 			 * @return {Object} 坦克实例
1477 			 */	
1478 			execute:function(onFinished){
1479 				var customState=this.stateManager.getCurrentState(this);
1480 				if(customState){
1481 					//customState.updateFuncList=[];
1482 					customState.addFunc(this.customState);
1483 				}
1484 				else{
1485 					customState=new robotState.State(this.customState);
1486 					customState.setOptions({owner:this,onFinished:onFinished});
1487 					this.stateManager.addState(customState);
1488 					this.customState=customState;
1489 				}
1490 				this.customState=null;
1491 				return this;		
1492 			},
1493 			/**
1494 			 * 一直循环执行的行为
1495 			 * 
1496 			 * @name loop
1497 			 * @function
1498 			 * @param {Function} func 需要循环执行的方法
1499 			 * @memberOf tank.Robot.prototype
1500 			 * @return {Object} 坦克实例
1501 			 */			
1502 			loop:function(func){
1503 				this.loopFunc=func;
1504 				return this;
1505 			},			
1506 			/**
1507 			 * 神马也不做
1508 			 * 
1509 			 * @name doNothing
1510 			 * @function
1511 			 * @memberOf tank.Robot.prototype
1512 			 * @return {Object} 坦克实例
1513 			 */
1514 			doNothing:function(){
1515 				var self=this;
1516 				var nothingState=new robotState.State();
1517 				nothingState.setOptions({
1518 					name:"doNothing",
1519 					owner:this
1520 				});
1521 				this.stateManager.addState(nothingState);
1522 				return this;
1523 			},
1524 			/**
1525 			 * 输出日志
1526 			 * 
1527 			 * @name log
1528 			 * @function
1529  			 * @param {Object} msg 日志输出的消息
1530 			 * @param {String} tag 日志消息的tag
1531 			 * @memberOf tank.Robot.prototype
1532 			 * @return {Object} 坦克实例
1533 			 */			
1534 			log:function(msg,tag){
1535 				var currentUser=site.account.getCurrentUser();
1536 				if(!currentUser) return;
1537 				var uid=currentUser.uid;
1538 				var tankUser=this.name.split(".")[0];
1539 				if(tankUser==uid){//只输出自己创建的坦克的日志
1540 					J.log(this.name+":"+msg,tag);
1541 				}
1542 				return this;	
1543 			},
1544 			/**
1545 			 * 开火
1546 			 * 
1547 			 * @name fire
1548 			 * @function
1549 			 * @memberOf tank.Robot.prototype
1550 			 * @param {Number} power 火力大小(1-3)
1551 			 * @return {Object} 坦克实例
1552 			 */
1553 			fire:function(power){//power:火力大小
1554 				power=power||1;//默认火力值为1
1555 				power=Math.min(power,3);//不能超过3的火力
1556 				var fireState=new robotState.State(this.customState);
1557 				fireState.setOptions({
1558 					name:"fire",
1559 					power:power,
1560 					owner:this
1561 				});
1562 				this.stateManager.addState(fireState);
1563 			},
1564 			/**
1565 			 * 设置雷达射线颜色
1566 			 * 
1567 			 * @name setScanStyle
1568 			 * @function
1569 			 * @memberOf tank.Robot.prototype
1570 			 * @param {String} style 雷达扫描区域样式
1571 			 * @return {Object} 坦克实例
1572 			 */	
1573 			setScanStyle:function(style){
1574 				this.radar.setScanStyle(style);
1575 				return this;
1576 			},
1577 			/**
1578 			 * 返回战场尺寸
1579 			 * 
1580 			 * @name getBattleFieldSize
1581 			 * @function
1582 			 * @memberOf tank.Robot.prototype
1583 			 * @return {Array} 战场尺寸
1584 			 */	
1585 			getBattleFieldSize:function(){
1586 				return [cg.canvas.width,cg.canvas.height];
1587 			},
1588 			/**
1589 			 * 返回战场高度
1590 			 * 
1591 			 * @name getBattleFieldHeight
1592 			 * @function
1593 			 * @memberOf tank.Robot.prototype
1594 			 * @return {Number} 战场高度
1595 			 */				
1596 			getBattleFieldHeight:function(){
1597 				return cg.canvas.height;
1598 			},
1599 			/**
1600 			 * 返回战场宽度
1601 			 * 
1602 			 * @name getBattleFieldWidth
1603 			 * @function
1604 			 * @memberOf tank.Robot.prototype
1605 			 * @return {Number} 战场宽度
1606 			 */				
1607 			getBattleFieldWidth:function(){
1608 				return cg.canvas.width;
1609 			},
1610 			/**
1611 			 * 返回坦克能量
1612 			 * 
1613 			 * @name getEnergy
1614 			 * @function
1615 			 * @memberOf tank.Robot.prototype
1616 			 * @return {Number} 坦克能量
1617 			 */	
1618 			getEnergy:function(){
1619 				return this.energy;
1620 			},
1621 			/**
1622 			 * 返回坦克距离某对象的距离
1623 			 * 
1624 			 * @name getDistance
1625 			 * @function
1626 			 * @param {Object} obj 要比较的坦克对象
1627 			 * @memberOf tank.Robot.prototype
1628 			 * @return {Number} 坦克距离某对象的距离
1629 			 */	
1630 			/*getDistance:function(obj){
1631 				return this.parent.prototype.getDistance.call(this,obj);
1632 			},*/
1633 			/**
1634 			 * 返回坦克朝向角度
1635 			 * 
1636 			 * @name getHeading
1637 			 * @function
1638 			 * @memberOf tank.Robot.prototype
1639 			 * @return {Number} 坦克朝向角度
1640 			 */	
1641 			getHeading:function(){
1642 				return radianToAngle(restrictAngle(this.angle));
1643 			},
1644 			/**
1645 			 * 返回火炮朝向角度
1646 			 * 
1647 			 * @name getGunHeading
1648 			 * @function
1649 			 * @memberOf tank.Robot.prototype
1650 			 * @return {Number} 火炮朝向角度
1651 			 */	
1652 			getGunHeading:function(){
1653 				return this.gun.getHeading();
1654 			},
1655 			/**
1656 			 * 返回雷达朝向角度
1657 			 * 
1658 			 * @name getRadarHeading
1659 			 * @function
1660 			 * @memberOf tank.Robot.prototype
1661 			 * @return {Number} 雷达朝向角度
1662 			 */	
1663 			getRadarHeading:function(){
1664 				return this.radar.getHeading();
1665 			},
1666 			/**
1667 			 * 返回某对象相对于坦克的角度
1668 			 * 
1669 			 * @name getBearing
1670 			 * @function
1671 			 * @param {Object} obj 要比较的坦克对象
1672 			 * @memberOf tank.Robot.prototype
1673 			 * @return {Number} 返回某对象相对于坦克的角度
1674 			 */	
1675 			getBearing:function(obj){
1676 				return this.getRelatedAngle(obj);
1677 			},
1678 			/**
1679 			 * 返回坦克的尺寸
1680 			 * @name getSize
1681 			 * @function
1682 			 * @memberOf tank.Robot.prototype
1683 			 * @return {Number} 返回坦克的尺寸
1684 			 */	
1685 			getSize:function(){
1686 				return this.size;
1687 			},
1688 			/**
1689 			 * 返回坦克的高度
1690 			 * @name getHeight
1691 			 * @function
1692 			 * @memberOf tank.Robot.prototype
1693 			 * @return {Number} 返回坦克的高度
1694 			 */				
1695 			getHeight:function(){
1696 				return this.size[1];
1697 			},
1698 			/**
1699 			 * 返回坦克的宽度
1700 			 * @name getWidth
1701 			 * @function
1702 			 * @memberOf tank.Robot.prototype
1703 			 * @return {Number} 返回坦克的宽度
1704 			 */				
1705 			getWidth:function(){
1706 				return this.size[0];
1707 			},			
1708 			/**
1709 			 * 返回坦克的位置
1710 			 * @name getPos
1711 			 * @function
1712 			 * @memberOf tank.Robot.prototype
1713 			 * @return {Number} 返回坦克的位置
1714 			 */	
1715 			getPos:function(){
1716 				return this.pos;
1717 			},
1718 			/**
1719 			 * 返回坦克的X位置
1720 			 * @name getX
1721 			 * @function
1722 			 * @memberOf tank.Robot.prototype
1723 			 * @return {Number} 返回坦克的X位置
1724 			 */				
1725 			getX:function(){
1726 				return this.pos[0];
1727 			},
1728 			/**
1729 			 * 返回坦克的Y位置
1730 			 * @name getY
1731 			 * @function
1732 			 * @memberOf tank.Robot.prototype
1733 			 * @return {Number} 返回坦克的Y位置
1734 			 */				
1735 			getY:function(){
1736 				return this.pos[1];
1737 			},
1738 			/**
1739 			 * 返回坦克的速度
1740 			 * @name getSpeed
1741 			 * @function
1742 			 * @memberOf tank.Robot.prototype
1743 			 * @return {Number} 返回坦克的速度
1744 			 */	
1745 			getSpeed:function(){
1746 				if(!J.isUndefined(this.preSpeed)){
1747 					return this.preSpeed[0];
1748 				}
1749 				return 0;
1750 			},
1751 			/**
1752 			 * 返回坦克的名字
1753 			 * @name getName
1754 			 * @function
1755 			 * @memberOf tank.Robot.prototype
1756 			 * @return {Number} 返回坦克的名字
1757 			 */	
1758 			getName:function(){
1759 				return this.name;
1760 			},
1761 
1762 			/**
1763 			*重置robot位置到上一次的位置
1764 			**/
1765 			resetPos:function(){
1766 				//this.preSpeed=this.preSpeed||this.speed;
1767 				//this.preSpeed=this.speed;
1768 				if(!this.preSpeed) this.preSpeed=[0,0];
1769 				if(!this.gun.preSpeed) this.gun.preSpeed=[0,0];
1770 				if(!this.radar.preSpeed) this.radar.preSpeed=[0,0];
1771 
1772 				this.pos[0]-=this.preSpeed[0]*Math.cos(this.angle)*2;
1773 				this.pos[1]+=this.preSpeed[0]*Math.sin(this.angle)*2;
1774 				this.angle-=this.preSpeed[1];
1775 				this.gun.angle-=this.gun.preSpeed[1];
1776 				this.radar.angle-=this.radar.preSpeed[1];
1777 
1778 
1779 				return this;
1780 			},
1781 			/**
1782 			*受伤能量损耗
1783 			**/
1784 			hurt:function(energy){
1785 				this.energy-=energy;
1786 				return this;
1787 			
1788 			},
1789 			/**
1790 			*robot消失
1791 			**/
1792 			disappear:function(){
1793 				gameObj.spriteList.remove(this);	
1794 				gameObj.spriteList.remove(this.gun);
1795 				gameObj.spriteList.remove(this.radar);
1796 
1797                 this.deleteArea.destory();
1798                 this.nameText.destory();
1799                 this.energyRect.destory();
1800 
1801                 this.deleteArea=this.nameText=this.energyRect=null;
1802          
1803 				return this;
1804 			},
1805 			/**
1806 			 * 获取敌人的数量
1807 			 * @name getOthers
1808 			 * @function
1809 			 * @memberOf tank.Robot.prototype
1810 			 * @return {Number} 返回敌人的数量
1811 			 */	
1812 			getOthers:function(){
1813 				var robotList=gameObj.spriteList.get(function(elem){
1814 					return elem instanceof Robot;								
1815 				})
1816 				return robotList.length-1;
1817 			},
1818 			/**
1819 			*添加用户事件处理
1820 			**/	
1821 			addCustomEvent:function(evtName,condition,handler){
1822 				this.conditionObj=this.conditionObj||{};
1823 				this.conditionHandlerObj=this.conditionHandlerObj||{};
1824 				var conditionObj=this.conditionObj;
1825 				var conditionHandlerObj=this.conditionHandlerObj;
1826 				conditionHandlerObj[evtName]||(conditionHandlerObj[evtName]=[]);
1827 				conditionObj[evtName]=condition;
1828 				conditionHandlerObj[evtName].push(handler);
1829 				
1830 				
1831 			},
1832 			/**
1833 			*触发用户事件处理
1834 			**/		
1835 			handleCustomEvent:function(){
1836 				var conditionObj=this.conditionObj;
1837 				var conditionHandlerObj=this.conditionHandlerObj;
1838 				for(name in conditionObj){
1839 					if(conditionObj&&conditionObj.hasOwnProperty(name)&&conditionObj[name].call(this)){
1840 						if(conditionHandlerObj&&conditionHandlerObj[name]){
1841 							for(var i=0,len=conditionHandlerObj[name].length;i<len;i++){
1842 								conditionHandlerObj[name][i].call(this);	
1843 							}
1844 						}
1845 					}
1846 				}
1847 			},
1848 			/**
1849 			 * 坦克爆炸    
1850 			 * @name explode
1851 			 * @function	
1852 			 * @memberOf Tank.prototype
1853 			 */
1854 			explode:function(){//爆炸位置
1855 				var self=this;
1856 				this.stateManager.cleanMainStateList();
1857 				this.stateManager.cleanEventStateList();
1858 				this.stop();
1859 				this.isExplode=true;
1860 				var explodeAnimation=new SS({id:"e1",size:[322,46],frameSize:[46,46],src:config.srcObj.explode,onFinish:function(){self.disappear();}});//添加爆炸动画
1861 				this.addAnimation(explodeAnimation);
1862 				if(config.isPlaySound){
1863 					var audio=cg.loader.loadedAudios[srcObj.bulletExplode];
1864 					if(audio){
1865 						audio.currentTime=0;
1866 						audio.play();
1867 					}
1868 				}
1869 				this.setCurrentAnimation("e1");
1870 			},
1871 			/**
1872 			 * 获取炮管冷却速率
1873 			 * @name getGunColdRate
1874 			 * @function
1875 			 * @memberOf tank.Robot.prototype
1876 			 * @return {Number} 获取炮管冷却速率
1877 			 */	
1878 			getGunColdRate:function(){
1879 				return this.gun.coldRate;
1880 			},	
1881 			/**
1882 			 * 获取炮管热度
1883 			 * @name getGunHeat
1884 			 * @function
1885 			 * @memberOf tank.Robot.prototype
1886 			 * @return {Number} 获取炮管热度
1887 			 */	
1888 			getGunHeat:function(){
1889 				return this.gun.heat;
1890 			},	
1891 			/**
1892 			 * 获取是否队友
1893 			 * @name isTeammate
1894 			 * @function
1895 			 * @param {String} name 坦克的名字
1896 			 * @memberOf tank.Robot.prototype
1897 			 * @return {boolean} 获取是否队友
1898 			 */				
1899 			isTeammate:function(name){
1900 				var teammatesList=this.getTeammates();
1901 
1902 				for(var i=0,len=teammatesList.length;i<len;i++){
1903 					var robot=teammatesList[i];
1904 					if(robot.name==name){
1905 						return true;
1906 					}
1907 				}
1908 				return false;
1909 
1910 			},
1911 			/**
1912 			 * 获取队友列表
1913 			 * @name getTeammates
1914 			 * @function
1915 			 * @memberOf tank.Robot.prototype
1916 			 * @return {Array} 队友列表
1917 			 */				
1918 			getTeammates:function(){
1919 				var teammatesList=[];
1920 				var robotList=gameObj.getCurrentRobotList();
1921 				for(var i=0,len=robotList.length;i<len;i++){	
1922 					var robot=robotList[i];
1923 					if(!J.isUndefined(this.team)&&!robot.isExplode&&this.team==robot.team&&robot!=this){
1924 						teammatesList.push(robot);
1925 					}
1926 				}			
1927 				return teammatesList;
1928 			},
1929 			/**
1930 			 * 向队友发送信息
1931 			 * @name sendMessage
1932 			 * @function
1933 			 * @param {Array} robot 坦克对象数组或单个坦克对象
1934 			 * @param {Object} message 发送的消息对象
1935 			 * @memberOf tank.Robot.prototype
1936 			 * @return {Object} 坦克对象
1937 			 */				
1938 			sendMessage:function(robot,message){//robot可以为单个robot或一个robot数组
1939 				if(J.isArray(robot)){
1940 					for(var i=0,len=robot.length;i<len;i++){
1941 						arguments.callee.call(this,robot[i],message);
1942 					}
1943 					return;
1944 				}
1945 				if(this.isTeammate(robot.name)&&!robot.isExplode){
1946 					tank.event.notifyMessageReceivedEvent(this,robot,message);
1947 				}
1948 				return this;
1949 			},
1950 			/**
1951 			 * 向所有队友发送信息
1952 			 * @name broadcastMessage
1953 			 * @function
1954 			 * @param {Object} message 发送的消息对象
1955 			 * @memberOf tank.Robot.prototype
1956 			 * @return {Object} 坦克对象
1957 			 */				
1958 			broadcastMessage:function(message){
1959 				var teammates=this.getTeammates();
1960 				this.sendMessage(teammates,message);
1961 				return this;
1962 			},
1963 			onMouseOver:function(){
1964 				this.deletPannel.show();
1965 			},
1966 			/**
1967 			 * 收到消息处理程序,由子类重写
1968 			 * @name onMessageReceived
1969 			 * @function
1970 			 * @param {Object} e 事件对象
1971 			 * @memberOf tank.Robot.prototype
1972 			 */				
1973 			onMessageReceived:function(e){
1974 			},
1975 			/**
1976 			 * 子弹射失处理程序,由子类重写
1977 			 * @name onBulletMissed
1978 			 * @function
1979 			 * @param {Object} e 事件对象
1980 			 * @memberOf tank.Robot.prototype
1981 			 */	
1982 			onBulletMissed:function(e){//eve.bullet:missed的子弹对象
1983 			},
1984 			/**
1985 			 * 子弹射中其他robot处理程序,由子类实现
1986 			 * @name onBulletHit
1987 			 * @function
1988 			 * @param {Object} e 事件对象
1989 			 * @memberOf tank.Robot.prototype
1990 			 */	
1991 			onBulletHit:function(e){//eve.bullet:射中的子弹对象  eve.robot:射中的robot对象
1992 			},
1993 			/**
1994 			 * 子弹射中其他子弹的处理程序,由子类重写
1995 			 * @name onBulletHitBullet
1996 			 * @function
1997 			 * @param {Object} e 事件对象
1998 			 * @memberOf tank.Robot.prototype
1999 			 */				
2000 			onBulletHitBullet:function(e){//eve.ownBullet:射出的子弹对象  eve.bullet:击中的敌人的子弹
2001 				
2002 			},
2003 			/**
2004 			 * 被子弹射中处理程序,由子类重写
2005 			 * @name onHitByBullet
2006 			 * @function
2007 			 * @param {Object} e 事件对象
2008 			 * @memberOf tank.Robot.prototype
2009 			 */	
2010 			onHitByBullet:function(e){//eve.bullet:被哪个子弹射中
2011 			},
2012 			/**
2013 			 * 撞击其他Robot处理程序,由子类重写
2014 			 * @name onHitRobot
2015 			 * @function
2016 			 * @param {Object} e 事件对象
2017 			 * @memberOf tank.Robot.prototype
2018 			 */	
2019 			onHitRobot:function(e){//eve.robot:与哪个robot相碰撞	
2020 			
2021 			},
2022 			/**
2023 			 * 撞击墙壁处理程序,由子类重写
2024 			 * @name onHitWall
2025 			 * @function
2026 			 * @param {Object} e 事件对象
2027 			 * @memberOf tank.Robot.prototype
2028 			 */	
2029 			onHitWall:function(e){//eve.wall:与哪个方向的墙碰撞({up:true,left:true,down:false,right:false} 未完善!
2030 			
2031 			},
2032 			/**
2033 			 * 雷达扫描到其他robot的处理程序,由子类重写
2034 			 * @name onScannedRobot
2035 			 * @function
2036 			 * @param {Object} e 事件对象
2037 			 * @memberOf tank.Robot.prototype
2038 			 */	
2039 			onScannedRobot:function(e){//eve.scanList:看到的其他robot的列表	
2040 			},
2041 			/**
2042 			 * 其他robot死亡的处理程序,由子类重写
2043 			 * @name onRobotDeath
2044 			 * @function
2045 			 * @param {Object} e 事件对象
2046 			 * @memberOf tank.Robot.prototype
2047 			 */	
2048 			onRobotDeath:function(e){},
2049 			/**
2050 			 * robot死亡的处理程序,由子类重写
2051 			 * @name onDeath
2052 			 * @function
2053 			 * @param {Object} e 事件对象
2054 			 * @memberOf tank.Robot.prototype
2055 			 */			
2056 			onDeath:function(e){},
2057 			/**
2058 			 * robot胜利的处理程序,由子类重写
2059 			 * @name onWin
2060 			 * @function
2061 			 * @param {Object} e 事件对象back
2062 			 * @memberOf tank.Robot.prototype
2063 			 */	
2064 			onWin:function(e){},
2065 			/**
2066 			 * 绘制机器人前的回调函数
2067 			 * @name onPaint
2068 			 * @function
2069 			 * @memberOf tank.Robot.prototype
2070 			 * @param {Object} context 2Dcontext对象
2071 			 * @return {Number} 绘制机器人前的回调函数
2072 			 */				
2073 			onPaint:function(context){
2074 			},
2075 			/**
2076 			 * 键盘按下事件处理程序
2077 			 * @name onKeyDown
2078 			 * @function
2079 			 * @memberOf tank.Robot.prototype
2080 			 * @param {Object} e 事件对象
2081 			 */				
2082 			onKeyDown:function(e){		
2083 			},
2084 			/**
2085 			 * 键盘松开事件处理程序
2086 			 * @name onKeyUp
2087 			 * @function
2088 			 * @memberOf tank.Robot.prototype
2089 			 * @param {Object} e 事件对象
2090 			 */				
2091 			onKeyUp:function(e){
2092 			},
2093 			/**
2094 			 * 鼠标点击事件处理程序
2095 			 * @name onClick
2096 			 * @function
2097 			 * @memberOf tank.Robot.prototype
2098 			 * @param {Object} e 事件对象
2099 			 */		
2100 			onClick:function(e){
2101 			},
2102 			/**
2103 			 * 鼠标移动事件处理程序
2104 			 * @name onMouseMove
2105 			 * @function
2106 			 * @memberOf tank.Robot.prototype
2107 			 * @param {Object} e 事件对象
2108 			 */				
2109 			onMouseMove:function(e){
2110 			},
2111 			/**
2112 			 * 鼠标按下事件处理程序
2113 			 * @name onMouseDown
2114 			 * @function
2115 			 * @memberOf tank.Robot.prototype
2116 			 * @param {Object} e 事件对象
2117 			 */				
2118 			onMouseDown:function(e){
2119 			},
2120 			/**
2121 			 * 鼠标松开事件处理程序
2122 			 * @name onMouseUp
2123 			 * @function
2124 			 * @memberOf tank.Robot.prototype
2125 			 * @param {Object} e 事件对象
2126 			 */				
2127 			onMouseUp:function(e){
2128 			}
2129 		}
2130 	})());
2131 });						  
2132 						  
2133 						  
2134