zoukankan      html  css  js  c++  java
  • 小强的HTML5移动开发之路(8)——坦克大战游戏2

    在上一篇文章中我们已经画出了自己的坦克,并且可以控制自己的坦克移动,我们继续接着上一篇来实现我们的坦克大战游戏吧。

    一、将JS文件分离出来

    使用OO的思想,我们已经对坦克进行了封装,对画坦克也进行了封装,下面我们将这两个对象提取到外部的js文件中,文件内容如下:

    	//定义一个Hero类(后面还要改进)
    	//x表示坦克的横坐标
    	//y表示纵坐标
    	//direct表示方向
    	function Hero(x,y,direct){
    		this.x=x;
    		this.y=y;
    		this.speed=1;
    		this.direct=direct;
    		//上移
    		this.moveUp=function(){
    			this.y-=this.speed;
    			this.direct=0;
    		}
    		//右移
    		this.moveRight=function(){
    			this.x+=this.speed;
    			this.direct=1;
    		}
    		//下移
    		this.moveDown=function(){
    			this.y+=this.speed;
    			this.direct=2;
    		}
    		//左移
    		this.moveLeft=function(){
    			this.x-=this.speed;
    			this.direct=3;
    		}
    	}
    	
    		//绘制坦克
    	function drawTank(tank){
    		//考虑方向
    		switch(tank.direct){
    			case 0:		//向上
    			case 2:		//向下
    				//设置颜色
    				cxt.fillStyle="#BA9658";
    				//左边的矩形
    				cxt.fillRect(tank.x,tank.y,5,30);
    				//右边的矩形
    				cxt.fillRect(tank.x+17,tank.y,5,30);
    				//画中间的矩形
    				cxt.fillRect(tank.x+6,tank.y+5,10,20);
    				//画出坦克的盖子
    				cxt.fillStyle="#FEF26E";
    				cxt.arc(tank.x+11,tank.y+15,5,0,Math.PI*2,true);
    				cxt.fill();
    				//画出炮筒
    				cxt.strokeStyle="#FEF26E";
    				cxt.lineWidth=1.5;
    				cxt.beginPath();
    				cxt.moveTo(tank.x+11,tank.y+15);
    				if(tank.direct==0){         //只是炮筒的方向不同
    					cxt.lineTo(tank.x+11,tank.y);
    				}else{
    					cxt.lineTo(tank.x+11,tank.y+30);
    				}
    				cxt.closePath();
    				cxt.stroke();
    				break;
    			case 1:
    			case 3:
    				//设置颜色
    				cxt.fillStyle="#BA9658";
    				//上边的矩形
    				cxt.fillRect(tank.x-4,tank.y+4,30,5);
    				//下边的矩形
    				cxt.fillRect(tank.x-4,tank.y+17+4,30,5);
    				//画中间的矩形
    				cxt.fillRect(tank.x+5-4,tank.y+6+4,20,10);
    				//画出坦克的盖子
    				cxt.fillStyle="#FEF26E";
    				cxt.arc(tank.x+15-4,tank.y+11+4,5,0,Math.PI*2,true);
    				cxt.fill();
    				//画出炮筒
    				cxt.strokeStyle="#FEF26E";
    				cxt.lineWidth=1.5;
    				cxt.beginPath();
    				cxt.moveTo(tank.x+15-4,tank.y+11+4);
    				if(tank.direct==1){         //只是炮筒的方向不同
    					cxt.lineTo(tank.x+30-4,tank.y+11+4);
    				}else{
    					cxt.lineTo(tank.x-4,tank.y+11+4);
    				}
    				cxt.closePath();
    				cxt.stroke();
    				break;	
    		}
    		
    	}
    

    在上一篇中有一个小问题,感谢 Mark_Lee的提醒

    				//画出坦克的盖子
    				cxt.fillStyle="#FEF26E";
    				cxt.arc(tank.x+15-4,tank.y+11+4,5,0,360,true);
    				cxt.fill();
    

    这里画的坦克盖子不是园的,大家可以参考:http://www.w3school.com.cn/html5/canvas_arc.asp


    好了,现在我们的html中的内容就变的清晰多了,html中的内容如下:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8"/>
    </head>
    <body onkeydown="getCommand();">
    <h1>html5-坦克大战</h1>
    <!--坦克大战的战场-->
    <canvas id="tankMap" width="400px" height="300px" style="background-color:black"></canvas>
    <!--将tankGame04.js引入-->
    <script type="text/javascript" src="tankGame04.js"></script>
    <script type="text/javascript">
    
    
    	//得到画布
    	var canvas1 = document.getElementById("tankMap");
    	//得到绘图上下文
    	var cxt = canvas1.getContext("2d");
    	
    	//我的tank
    	//规定0向上、1向右、2向下、3向左
    	var hero = new Hero(40,40,0);
    	drawTank(hero);
    
    	
    	//接收用户按键的函数
    	function getCommand(){
    		var code = event.keyCode;  //键盘上字幕的ASCII码
    		switch(code){
    			case 87:
    				hero.moveUp();
    				break;
    			case 68:
    				hero.moveRight();
    				break;
    			case 83:
    				hero.moveDown();
    				break;
    			case 65:
    				hero.moveLeft();
    				break;
    		}
    		//把画布清理
    		cxt.clearRect(0,0,400,300);
    		//重新绘制
    		drawTank(hero);
    	}
    </script>
    </body>
    </html>

    二、绘制敌人的坦克

    好多朋友可能现在已经有了思路,这还不简单吗?画敌人坦克的时候再新建立一个function仿照自己的坦克类再写一遍不就好了吗。还有的朋友不同意这个方法,说:既然都是坦克我们就不用写了,直接创建坦克实例不就完了吗。第一个朋友和第二个朋友的做法看似是面向对象其实不是面向对象,在做这种游戏的时候如果我们不用面向对象的思想去实现,也可以实现,但是会很复杂。

    我们这样考虑一下,自己坦克肯定和敌人坦克有区别,不能归为一类,比如:发的子弹不同,颜色不同等。但是两者又有相同点(都是坦克),我们是不是应该把这部分给抽象出来呢?是的,我们先抽象出来一个Tank类,再分别继承这个Tank类。你开玩笑吧大笑这个不是Java语言,这个是javascript脚本语言,哪里来的继承?惊讶呵呵,我们可以用javascript中的对象冒充,对象冒充,是JavaScript 和 ECMAScript实现继承的方法,在学习对象冒充实现继承前我们的先了解关键字 this 的使用

    function  classA(color){
      this.color = color;
      this.show = function(){alert(this.color);}
    }
    /*
       Note:
         1> this 代表的是classA函数所构建的对象,而非函数classA对象本身这样说主要是为了避免(function is object)的影响;
         2> 在构建classA对象时,是通过this来初始化的属性和方法的,如果用classB的this去冒充classA的this,那么就实现了简单的继承了
    */
    对象冒充的原理:函数classA通过this来初始化属性和方法,如果用函数classB的this冒充classA的this去执行,则就会使classB具有classA的属性和方法

    好了,现在我们用自己的坦克和敌人的坦克对象去冒充一下坦克,呵呵。

    	//定义一个Tank类(基类)
    	function Tank(x,y,direct,color){
    		this.x=x;
    		this.y=y;
    		this.speed=1;
    		this.direct=direct;
    		this.color=color;
    		//上移
    		this.moveUp=function(){
    			this.y-=this.speed;
    			this.direct=0;
    		}
    		//右移
    		this.moveRight=function(){
    			this.x+=this.speed;
    			this.direct=1;
    		}
    		//下移
    		this.moveDown=function(){
    			this.y+=this.speed;
    			this.direct=2;
    		}
    		//左移
    		this.moveLeft=function(){
    			this.x-=this.speed;
    			this.direct=3;
    		}
    	}
    
    	//定义一个Hero类
    	function Hero(x,y,direct,color){
    		//下面两句话的作用是通过对象冒充达到继承的效果
    		this.tank=Tank;
    		this.tank(x,y,direct,color);
    	}
    	
    	//定义一个EnemyTank类
    	function EnemyTank(x,y,direct,color){
    		this.tank=Tank;
    		this.tank(x,y,direct,color);
    	}
    	
    这样我们就将自己的坦克和敌人的坦克定义好了,那么绘制坦克的drawTank(tank)要不要变呢?因为绘制的是Tank所以不需要改动,呵呵,这就是面向对象的多态喽。

    创建坦克对象吧!

    	//我的tank
    	//规定0向上、1向右、2向下、3向左
    	var hero=new Hero(40,40,0,heroColor);
    	//敌人的tank
    	var enemyTanks=new Array();
    	for(var i=0;i<3;i++){
    		var enemyTank = new EnemyTank((i+1)*50,0,2,enemyColor);
    		enemyTanks[i]=enemyTank;	
    	}

    完整代码如下:

    tankGame05.js

    	//为了编程方便,我们定义两个颜色数组
    	var heroColor=new Array("#BA9658","#FEF26E");
    	var enemyColor=new Array("#00A2B5","#00FEFE");
    	
    	//定义一个Tank类(基类)
    	function Tank(x,y,direct,color){
    		this.x=x;
    		this.y=y;
    		this.speed=1;
    		this.direct=direct;
    		this.color=color;
    		//上移
    		this.moveUp=function(){
    			this.y-=this.speed;
    			this.direct=0;
    		}
    		//右移
    		this.moveRight=function(){
    			this.x+=this.speed;
    			this.direct=1;
    		}
    		//下移
    		this.moveDown=function(){
    			this.y+=this.speed;
    			this.direct=2;
    		}
    		//左移
    		this.moveLeft=function(){
    			this.x-=this.speed;
    			this.direct=3;
    		}
    	}
    
    	//定义一个Hero类
    	function Hero(x,y,direct,color){
    		//下面两句话的作用是通过对象冒充达到继承的效果
    		this.tank=Tank;
    		this.tank(x,y,direct,color);
    	}
    	
    	//定义一个EnemyTank类
    	function EnemyTank(x,y,direct,color){
    		this.tank=Tank;
    		this.tank(x,y,direct,color);
    	}
    	
    		//绘制坦克
    	function drawTank(tank){
    		//考虑方向
    		switch(tank.direct){
    			case 0:		//向上
    			case 2:		//向下
    				//设置颜色
    				cxt.fillStyle=tank.color[0];
    				//左边的矩形
    				cxt.fillRect(tank.x,tank.y,5,30);
    				//右边的矩形
    				cxt.fillRect(tank.x+17,tank.y,5,30);
    				//画中间的矩形
    				cxt.fillRect(tank.x+6,tank.y+5,10,20);
    				//画出坦克的盖子
    				cxt.fillStyle=tank.color[1];
    				cxt.arc(tank.x+11,tank.y+15,5,0,Math*PI*2,true);
    				cxt.fill();
    				//画出炮筒
    				cxt.strokeStyle=tank.color[1];
    				cxt.lineWidth=1.5;
    				cxt.beginPath();
    				cxt.moveTo(tank.x+11,tank.y+15);
    				if(tank.direct==0){         //只是炮筒的方向不同
    					cxt.lineTo(tank.x+11,tank.y);
    				}else{
    					cxt.lineTo(tank.x+11,tank.y+30);
    				}
    				cxt.closePath();
    				cxt.stroke();
    				break;
    			case 1:
    			case 3:
    				//设置颜色
    				cxt.fillStyle="#BA9658";
    				//上边的矩形
    				cxt.fillRect(tank.x-4,tank.y+4,30,5);
    				//下边的矩形
    				cxt.fillRect(tank.x-4,tank.y+17+4,30,5);
    				//画中间的矩形
    				cxt.fillRect(tank.x+5-4,tank.y+6+4,20,10);
    				//画出坦克的盖子
    				cxt.fillStyle="#FEF26E";
    				cxt.arc(tank.x+15-4,tank.y+11+4,5,0,Math*PI*2,true);
    				cxt.fill();
    				//画出炮筒
    				cxt.strokeStyle="#FEF26E";
    				cxt.lineWidth=1.5;
    				cxt.beginPath();
    				cxt.moveTo(tank.x+15-4,tank.y+11+4);
    				if(tank.direct==1){         //只是炮筒的方向不同
    					cxt.lineTo(tank.x+30-4,tank.y+11+4);
    				}else{
    					cxt.lineTo(tank.x-4,tank.y+11+4);
    				}
    				cxt.closePath();
    				cxt.stroke();
    				break;	
    		}
    		
    	}
    

    坦克大战.html

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8"/>
    </head>
    <body onkeydown="getCommand();">
    <h1>html5-坦克大战</h1>
    <!--坦克大战的战场-->
    <canvas id="tankMap" width="400px" height="300px" style="background-color:black"></canvas>
    <!--将tankGame04.js引入-->
    <script type="text/javascript" src="tankGame05.js"></script>
    <script type="text/javascript">
    	//得到画布
    	var canvas1=document.getElementById("tankMap");
    	//得到绘图上下文
    	var cxt=canvas1.getContext("2d");
    	
    	//我的tank
    	//规定0向上、1向右、2向下、3向左
    	var hero=new Hero(40,40,0,heroColor);
    	//敌人的tank
    	var enemyTanks=new Array();
    	for(var i=0;i<3;i++){
    		var enemyTank = new EnemyTank((i+1)*50,0,2,enemyColor);
    		enemyTanks[i]=enemyTank;	
    	}
    	
    	//定时刷新我们的作战区(定时重绘)
    	//自己的坦克,敌人坦克,子弹,炸弹,障碍物
    	function flashTankMap(){
    		//把画布清理
    		cxt.clearRect(0,0,400,300);
    		//我的坦克
    		drawTank(hero);
    		//敌人的坦克
    		for(var i=0;i<3;i++){
    			drawTank(enemyTanks[i]);
    		}
    	}
    	flashTankMap();
    	//接收用户按键的函数
    	function getCommand(){
    		var code = event.keyCode;  //键盘上字幕的ASCII码
    		switch(code){
    			case 87:
    				hero.moveUp();
    				break;
    			case 68:
    				hero.moveRight();
    				break;
    			case 83:
    				hero.moveDown();
    				break;
    			case 65:
    				hero.moveLeft();
    				break;
    		}
    		flashTankMap();
    	}
    </script>
    </body>
    </html>
    运行效果:

     既然我们的坦克和敌人的坦克都有了,我们要让他们战斗起来,下一篇我们将让坦克发子弹。


  • 相关阅读:
    android工程下assets与raw文件夹
    eclipse增加jar包方式对比
    跳出内循环,继续下一次外循环的写法
    ImportError: cannot import name 'BaseDataset' from 'src.dataset'
    神经网络中的反向传播法
    Pytorch中ndarray tensor list互转
    Python运行语法错误:IndentationError: unindent does not match any outer indentation level
    module 'torch' has no attribute 'gesv'
    极大似然估计
    Gaussian Processes
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6469393.html
Copyright © 2011-2022 走看看