紧接着上次做的将游戏最终完成。
1、现在要绘出敌方飞机:
因为敌方飞机有三种不同的形式,每种飞机的参数各不相同,这里就要新建三个数组及对象来储存他们。
// 绘制敌方飞机,(3种) var enemy1 = []; enemy1[0] = new Image(); enemy1[0].src = "img/enemy1.png"; enemy1[1] = new Image(); enemy1[1].src = "img/enemy1_down1.png"; enemy1[2] = new Image(); enemy1[2].src = "img/enemy1_down2.png"; enemy1[3] = new Image(); enemy1[3].src = "img/enemy1_down3.png"; enemy1[4] = new Image(); enemy1[4].src = "img/enemy1_down4.png"; var enemy1s = { img : enemy1, width : 57, height : 51, length : enemy1.length, type : 1, frame : 1, life : 1, score : 1 } var enemy2 = []; enemy2[0] = new Image(); enemy2[0].src = "img/enemy2.png"; enemy2[1] = new Image(); enemy2[1].src = "img/enemy2_down1.png"; enemy2[2] = new Image(); enemy2[2].src = "img/enemy2_down2.png"; enemy2[3] = new Image(); enemy2[3].src = "img/enemy2_down3.png"; enemy2[4] = new Image(); enemy2[4].src = "img/enemy2_down4.png"; var enemy2s = { img : enemy2, width : 69, height : 95, length : enemy2.length, type : 2, frame : 1, life : 3, score : 5 } var enemy3 = []; enemy3[0] = new Image(); enemy3[0].src = "img/enemy3_n1.png"; enemy3[1] = new Image(); enemy3[1].src = "img/enemy3_n2.png"; enemy3[2] = new Image(); enemy3[2].src = "img/enemy3_down1.png"; enemy3[3] = new Image(); enemy3[3].src = "img/enemy3_down2.png"; enemy3[4] = new Image(); enemy3[4].src = "img/enemy3_down3.png"; enemy3[5] = new Image(); enemy3[5].src = "img/enemy3_down4.png"; enemy3[6] = new Image(); enemy3[6].src = "img/enemy3_down5.png"; enemy3[7] = new Image(); enemy3[7].src = "img/enemy3_down6.png"; var enemy3s = { img : enemy3, width : 169, height : 260, length : enemy3.length, type : 3, frame : 2, life : 10, score : 20 }
然后创建敌方飞机的构造函数,值得思考的是飞机碰撞的相关逻辑,想象一下当敌方飞机与子弹或者我方飞机碰撞时他们坐标有什么样的联系然后换算出来。
function enemys(images){ this.img = images.img; this.width = images.width; this.height = images.height; this.length = images.length; this.type = images.type; this.frame = images.frame; this.life = images.life; this.score = images.score; this.x = Math.random() * (wid-this.width); this.y = -this.height; this.num = 0; this.boom = false; this.leave = false; this.paint = function () { gj.drawImage(this.img[this.num],this.x,this.y); } this.step = function () { if (!this.boom) { this.num ++ ; this.num = this.num % this.frame ; this.y ++ ; } else { this.num ++ ; if (this.num == this.length) { this.leave = true; score += this.score; this.num = this.length - 1; } } } this.booms = function () { this.life -- ; if (this.life == 0) { this.boom = true; } } // 敌方飞机的碰撞逻辑 this.checkHit = function (my){ return my.x > this.x - my.width && my.x < this.x + this.width && my.y < this.y + this.height ; } }
然后还是跟子弹一样,每一个敌方飞机都是一个独立的对象。
不过这里敌方飞机生成的时候得注意飞机的位置是canvas界面内随机生成的,而且不同种类的敌方飞机的生成概率是不同的。这里用随机数加判断的方法来实现。
然后完善之前埋下的伏笔,将这些对象的碰撞事件融合在一起,使这些零散的事件有一个清晰的逻辑。(我方飞机碰撞减生命值,子弹碰撞消失,敌方不同的飞机类型碰撞后有不同的表现形式,这些都要考虑在内。)
var Enemys = []; function createnemys(){ var rank = Math.random()*100; if (rank <= 7) { Enemys.push(new enemys(enemy1s)); } else if (rank <= 10) { Enemys.push(new enemys(enemy2s)); } else if (rank <= 11) { Enemys.push(new enemys(enemy3s)); } } function paintenemys(){ for (var i=0 ; i<Enemys.length ; i++) { Enemys[i].paint(); } } function stepenemys(){ for (var i=0 ; i<Enemys.length ; i++) { Enemys[i].step(); } } function Hitenemys(){ for (var i=0 ; i<Enemys.length ; i++) { if (Enemys[i].checkHit(heroes)) { Enemys[i].booms(); heroes.booms(); } for (var j = 0 ; j < bullets.length ; j ++) { if (Enemys[i].checkHit(bullets[j])) { Enemys[i].booms(); bullets[j].booms(); } } } } function Delenemys(){ for (var i=0 ; i<Enemys.length ; i++) { if (Enemys[i].leave || Enemys[i].y > hei+Enemys[i].height) { Enemys.splice(i,1);
state = GAMEOVER; } } }
然后绘制canvas左上角的得分与右上角的生命值。
// 绘制分数和生命值 function drawscore(){ gj.font = "bold 30px 微软雅黑"; gj.fillText("SCORE:"+score,20,50); gj.fillText("LIFE:"+life,wid-150,50); }
2、写暂停状态的事件:
这里我们要实现的逻辑是:当鼠标移出canvas界面时如果这时处于运行状态则使其暂停。
当鼠标移入canvas界面时如果这时处于暂停状态则使其运行。
// 暂停状态事件 canvas.onmouseover = function (){ if (state == PAUSE) { state = RUNNING } } canvas.onmouseleave = function (){ if (state == RUNNING) { state = PAUSE } } var pause = new Image(); pause.src = "img/game_pause_nor.png"
3、写游戏结束状态的事件:
首先,了解什么情况下游戏进入结束状态,进入结束状态后有哪些表现形式。
当我方飞机生命值归零或者敌方飞机飞出canvas下边界的时候游戏结束,界面显示GAME OVER
// 游戏结束事件 function Gameover(){ gj.font = "bold 50px 微软雅黑"; gj.fillText("GAME OVER",90,300); } setInterval( function (){ load.paint(); load.step(); if (state == START) { gj.drawImage(logo,40,0) } else if (state == LOADING) { wait.paint(); wait.step(); } else if (state == RUNNING) { heroes.paint(); heroes.step(); heroes.shoot(); bulletsPaint(); bulletsStep(); bulletsDel(); // console.log(bullets); createnemys(); paintenemys(); stepenemys(); Hitenemys(); Delenemys(); drawscore() // console.log(Enemys); } else if (state == PAUSE) { heroes.paint(); bulletsPaint(); paintenemys(); drawscore(); gj.drawImage(pause,200,300); } else if (state == GAMEOVER) { Gameover() } },50 )
这里我们加上了一些属性,当游戏结束之后,再次点击刷新页面重新开始:
// 给canvas一个点击事件,当处于开始状态的时候点击进入loading状态 canvas.onclick = function () { if (state == START) { state = LOADING; } if (state == GAMEOVER) { location.reload(); //当游戏结束时再次点击刷新页面重新开始。 } }