canvas雷霆战机

这个游戏大家肯定都玩过,今天分享一个用canvas写的一个小demo。
效果图:


QQ20180103-204422-HD.gif

一、首先要做的肯定是图片预加载

var imgArr = {
            "bg":"img/background.png",
            "herofly":"img/herofly.png",
            "bullet1":"img/bullet1.png",
            "bullet2":"img/bullet2.png",
            "enemy1":"img/enemy1.png",
            "enemy2":"img/enemy2.png",
            "enemy3":"img/enemy3.png",
            "prop":"img/prop.png"
        }
        var imgLength = 0;
        for(var i in imgArr){
            imgLength++;
        }
        var num = 0;
        var loadArr = {};
        for(let i in imgArr){
            var img = new Image();
            img.src = imgArr[i];
            img.onload = function(){
                loadArr[i] = this;
                num++;
                if(num>=imgLength){
                    main(loadArr);
                }
            }
        }

二、分析游戏中都几个对象

对象一:主机;
对象二:敌机;
对象三:奖励;
每个对象都有move移动,draw绘画,isClear是否清除的方法
以子弹为例:其余对象的构造函数类似

// 子弹构造函数
            function Bullet(x,y,power,obj,speed){
                this.x = x;
                this.y = y;
                this.power = power;
                this.obj = obj;
                this.w = obj.width;
                this.h = obj.height;
                this.speed = speed;
            }
            Bullet.prototype.draw = function(){
                context.drawImage(this.obj,0,0,this.w,this.h,this.x,this.y,this.w,this.h);
                // 子弹与敌机的碰撞检测
                for(var j = 0 ; j < enemy.length;j++){
                    if((this.xenemy[j].x) && (this.yenemy[j].y)){   
                        enemy[j].blood -= 25;
                        if(enemy[j].i == 5){
                            music2.src = "audio/enemy1_down.mp3";
                        }else if(enemy[j].i == 6){
                            music2.src = "audio/enemy2_down.mp3";
                        }else{
                            music2.src = "audio/enemy3_down.mp3";
                        }   
                        this.y = -10;   
                    }   
                }   
            }
            Bullet.prototype.move = function(){
                this.y -= this.speed;   
            }
            Bullet.prototype.isClear = function(){
                if(this.y<0){
                    return true;
                }else{
                    return false;
                }
            }

三、定义几个数组存放实例化的子弹,敌机,奖励

方便后面做碰撞判断

// 存放子弹的容器
            var bullet = [];
            var num = 0;
            var bgY = 0;
            // 存放敌机的容器
            var enemy = [];
            var enemyBlood = 100;
            // 存放奖励的容器
            var award = [];
            // 子弹的颗数
            var bulletNum = loadArr.bullet1;
            var bulletX = 30;
            // 敌机与主机碰撞的开关
            var isCarld = true;

四、动画函数

创建一个act函数做动画,函数里实例化子弹,敌机,以及做各种碰撞检测,这里注意:碰撞检测不要全部在act方法里判断,可以在构造函数的draw方法里判断,优化性能,使游戏画面流畅。

  1. 背景图滚动
                bgY--;
                context.drawImage(loadArr.bg,0,0+bgY,canvas.width,canvas.height);
                context.drawImage(loadArr.bg,0,canvas.height+bgY,canvas.width,canvas.height);
                if(Math.abs(bgY) >= canvas.height){
                    bgY = 0;
                }
  1. 绘画主机和实例化敌机,奖励,Rand()是一个封装好取随机数的函数,使用随机数出现的概率来决定不同敌机和不同奖励出现的概率。
// 画主机
                newHero.draw();
                newHero.move();
                // 实例化敌机和奖励
                if(num%50 == 0){
                    var randNum = Rand(0,34);
//                  console.log(randNum);
                    if(randNum>=0 && randNum<20){
                        // 随机位置
                        var randX = Rand(0,canvas.width-loadArr.enemy1.width/5);
                        // 敌机的血量
                        var blood = enemyBlood -20;
                        var newEnemy = new Enemy(randX,-loadArr.enemy1.height,blood,20,loadArr.enemy1,1.5,5);
                        enemy.push(newEnemy);
                    }else if(randNum >= 20 && randNum <28){
                        var randX = Rand(0,canvas.width-loadArr.enemy2.width/6);
                        var blood = enemyBlood -50;
                        var newEnemy = new Enemy(randX,-loadArr.enemy2.height,blood,35,loadArr.enemy2,1,6);
                        enemy.push(newEnemy);
                    }else if(randNum >= 28 && randNum <30){
                        var blood = enemyBlood;
                        var randX = Rand(0,canvas.width-loadArr.enemy3.width/10);
                        var newEnemy = new Enemy(randX,-loadArr.enemy3.height,blood,50,loadArr.enemy3,0.5,10);
                        enemy.push(newEnemy);
//                      console.log(newEnemy.x,newEnemy.y);
                    }else if(randNum >= 30 && randNum <31){
                        // 奖励1
                        var randX = Rand(0,canvas.width-loadArr.prop.width/3);
                        var newRaward = new Award(randX,-loadArr.prop.height,loadArr.prop,1,0);
                        console.log(newRaward);
                        award.push(newRaward);
                    }else if(randNum >= 31 && randNum <33){
                        // 奖励2
                        var randX = Rand(0,canvas.width-loadArr.prop.width/3);
                        var newRaward = new Award(randX,-loadArr.prop.height,loadArr.prop,1,1);
                        console.log(newRaward);
                        award.push(newRaward);
                    }else{
                        // 奖励3
                        var randX = Rand(0,canvas.width-loadArr.prop.width/3);
                        var newRaward = new Award(randX,-loadArr.prop.height,loadArr.prop,1,2);
                        console.log(newRaward);
                        award.push(newRaward);
                    }
                }
  1. 敌机与主机的碰撞检测
    这里使用的事普通碰撞,大家有兴趣可以换成像素碰撞。
    遍历敌机enemy数组,使用isCarld控制只碰撞一次,主机血量减少。血量为0时主机爆炸游戏结束。
for(var i = 0 ; i < enemy.length ; i++){
                    enemy[i].draw();
                    enemy[i].move();
                    // 敌机与主机的碰撞检测
                    if((newHero.x< enemy[i].x+enemy[i].w && newHero.x+newHero.w>enemy[i].x) && (newHero.y< enemy[i].y+enemy[i].h && newHero.y+newHero.h>enemy[i].y)){
                        if(isCarld){
                            isCarld = false;
                            newHero.blood -= enemy[i].power;    
                            if(newHero.blood < 0){
                                newHero.blood = 0;
                            }
                            bloodNum.innerHTML = "血量:"+ newHero.blood;
                            bloodPress.style.width = 200*newHero.blood/100 + "px";
                        }
                        enemy[i].isF = true;
                        console.log(newHero.blood);
//                      music2.src = "audio/enemy2_out.mp3";
                    }
                    if(enemy[i].isF && enemy[i].y >= canvas.height){
                        isCarld = true;
                    }
                    if(enemy[i].isClear()){
                        enemy.splice(i,1);
                    }
//                  console.log(enemy.length);
                }

像子弹和敌机的碰撞还有主机和奖励的碰撞代码大同小异,就是其中逻辑不同,这里就不一一展示了。

  1. 游戏结束
    使用requestAnimationFrame做动画,使用cancelAnimationFrame(Timer);来停止动画。
var Timer = window.requestAnimationFrame(act);
                if(newHero.index >= newHero.i-1){
                    console.log("dfsf");
                    music1.src = "audio/game_over.mp3";
                    music1.loop = "";
                    music2.remove();
                    cancelAnimationFrame(Timer);
                    // 游戏结束
                    btn.style.display = "block";
                    context.beginPath();
                    context.fillStyle = "grey";
                    context.fillRect(0,150,canvas.width,200);
                    context.beginPath();
                    context.textBaseline = "middle";
                    context.textAlign = "center";
                    context.font = "40px Arial";
                    context.fillStyle = "red";
                    context.fillText("gameover",canvas.width/2,275);
                }

游戏结束的页面图:


canvas雷霆战机_第1张图片
C09F4603-BE58-4C6C-A1DB-25050CF7B32F.png

你可能感兴趣的:(canvas雷霆战机)