来自:http://blog.csdn.net/cai_xingyun/article/details/48629015
在上一篇文章中我们已经画出了自己的坦克,并且可以控制自己的坦克移动,我们继续接着上一篇来实现我们的坦克大战游戏吧。
一、将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
- <!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,那么就实现了简单的继承了
- */
好了,现在我们用自己的坦克和敌人的坦克对象去冒充一下坦克,呵呵。
- //定义一个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);
- }
创建坦克对象吧!
- //我的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>
既然我们的坦克和敌人的坦克都有了,我们要让他们战斗起来,下一篇我们将让坦克发子弹。