用canvas整個打飛機遊戲

  聲明:本文爲原創文章,如需轉載,請註明來源WAxes,謝謝!html

  以前在當耐特的DEMO裏看到個打飛機的遊戲,而後就把他的圖片和音頻扒了了下來。。。。本身憑着玩的心情從新寫了一個。僅供娛樂哈。。。。。。我沒有用框架,全部js都是本身寫的。。。。。。因此就能夠來當個簡單的教程,對那些剛玩canvas的,或許能有些幫助,樓主玩canvas也不是好久,技術不是很好,請見諒哈。git

  閒話很少說,先上DEMO撒:飛機遊戲   樓主寫這我的純碎娛樂,沒想着寫成多正式的遊戲哈。github

  步入主題啦:打飛機遊戲文件有index.html入口文件,allSprite.js精靈的邏輯處理文件,loading.js加載處理文件以及data.js(初始化的一些數據)。canvas

  首先,正常的遊戲基本上都須要一個loading,loading頁面就是用來預加載數據的,包括精靈表圖片,音頻等,由於這是個小遊戲,要加載的就只有一些音頻和圖片。裏面的加載代碼主要就下面這些,其餘是製做loading動畫的,那個比較簡單,就不貼了,若是有興趣的直接在DEMO裏看控制檯就好了:數組

loadImg:function(datas){
            var _this = this;
            var dataIndex = 0;
            li();
            function li(){
                if(datas[dataIndex].indexOf("mp3")>=0){
                    var audio = document.createElement("audio");
                    document.body.appendChild(audio);
                    audio.preload = "auto";
                    audio.src = datas[dataIndex];
                    audio.oncanplaythrough = function(){
                        this.oncanplaythrough = null;
                        dataIndex++;
                        if(dataIndex===datas.length){
                            _this.percent = 100;
                        }else {
                            _this.percent = parseInt(dataIndex/datas.length*100);
                            li.call(_this);
                        }
                    }
                }else {
                    preLoadImg(datas[dataIndex] , function(){
                        dataIndex++;
                        if(dataIndex===datas.length){
                            _this.percent = 100;
                        } else {
                            _this.percent = parseInt(dataIndex/datas.length*100);
                            li.call(_this);
                        }
                    })
                }
            }
        },

//再貼出preLoadImg的方法
function preLoadImg(src , callback){
    var img = new Image();
    img.src = src;
    if(img.complete){
        callback.call(img);
    }else {
        img.onload = function(){
            callback.call(img);
        }
    }
}

我先在data.js裏面用一個數組保存文件的連接,而後判斷這些連接是圖片仍是音頻,若是是圖片就用preLoadImg加載,預加載圖片的代碼很簡單,就是new一個圖片對象,而後把連接賦給它,加載完後再回調。音頻的加載則是經過生成一個HTML5的audio dom對象,把連接賦給它,audio有一個事件「canplaythrough」,瀏覽器預計可以在不停下來進行緩衝的狀況下持續播放指定的音頻/視頻時,會發生 canplaythrough 事件,也就是說當canplaythrough被調用時,音頻就已經被加載的差很少了,能夠進行下一個音頻的加載了。就這樣當把全部東西都加載完後,再進行回調,開始遊戲。瀏覽器

 

  遊戲開始了,一個遊戲,會須要不少的對象,因此我就統一寫成了一個精靈對象,不一樣對象之間的每一幀的運動狀況直接用behavior來分別編寫就好了。app

    W.Sprite = function(name , painter , behaviors , args){
        if(name !== undefined) this.name = name;
        if(painter !== undefined) this.painter = painter;
        this.top = 0;
        this.left = 0;
        this.width = 0;
        this.height = 0;
        this.velocityX = 3;
        this.velocityY = 2;
        this.visible = true;
        this.animating = false;
        this.behaviors = behaviors;
        this.rotateAngle = 0;
        this.blood = 50;
        this.fullBlood = 50;
        if(name==="plan"){
            this.rotateSpeed = 0.05;
            this.rotateLeft = false;
            this.rotateRight = false;
            this.fire = false;
            this.firePerFrame = 10;
            this.fireLevel = 1;
        }else if(name==="star"){
            this.width = Math.random()*2;
            this.speed = 1*this.width/2;
            this.lightLength = 5;
            this.cacheCanvas = document.createElement("canvas");
            this.cacheCtx = this.cacheCanvas.getContext('2d');
            this.cacheCanvas.width = this.width+this.lightLength*2;
            this.cacheCanvas.height = this.width+this.lightLength*2;
            this.painter.cache(this);
        }else if(name==="badPlan"){
            this.badKind = 1;
            this.speed = 2;
            this.rotateAngle = Math.PI;
        }else if(name==="missle"){
            this.width = missleWidth;
        }else if(name==="boom"){
            this.width = boomWidth;
        }else if(name==="food"){
            this.width = 40;
            this.speed = 3;
            this.kind = "LevelUP"
        }
        this.toLeft = false;
        this.toTop = false;
        this.toRight = false;
        this.toBottom = false;

        this.outArcRadius = Math.sqrt((this.width/2*this.width/2)*2);

        if(args){
            for(var arg in args){
                this[arg] = args[arg];
            }
        }
    }
    Sprite.prototype = {
        constructor:Sprite,
        paint:function(){
            if(this.name==="badPlan"){this.update();}

            if(this.painter !== undefined && this.visible){
                if(this.name!=="badPlan") {
                    this.update();
                }
                if(this.name==="plan"||this.name==="missle"||this.name==="badPlan"){
                    ctx.save();
                    ctx.translate(this.left , this.top);
                    ctx.rotate(this.rotateAngle);
                    this.painter.paint(this);
                    ctx.restore();
                }else {
                    this.painter.paint(this);
                }
            }
        },
        update:function(time){
            if(this.behaviors){
                for(var i=0;i<this.behaviors.length;i++){
                    this.behaviors[i].execute(this,time);
                }
            }
        }
    }

寫出精靈類後,就能夠經過編寫每一個的painter以及behavior來生成不一樣的對象了。接下來就是寫painter了,painter分紅兩種,一種是普通的painter,一種就是精靈表painter,由於像爆炸動畫,飛機開槍動畫,都不是一張圖片就能搞定的,因此就須要用到精靈表了:
框架

而繪製這些就要爲他們定製一個精靈表繪製器,下面這個是最簡單的精靈表繪製器,針對遊戲的複雜性能夠相對的修改精靈表寫法,直到合適,不過原理都大同小異,就是小修小改而已:dom

var SpriteSheetPainter = function(cells){
            this.cells = cells || [];
            this.cellIndex = 0;
        }
        SpriteSheetPainter.prototype = {
            advance:function(){
                if(this.cellIndex === this.cells.length-1){
                    this.cellIndex = 0;
                }
                else this.cellIndex++;
            },
            paint:function(sprite){
                var cell = this.cells[this.cellIndex];
                context.drawImage(spritesheet , cell.x , cell.y , cell.w , cell.h , sprite.left , sprite.top , cell.w , cell.h);
            }
        }

而普通的繪製器就更簡單了,直接寫一個painter,把要畫的什麼東西都寫進去就好了。ide

有了精靈類和精靈表繪製器後,咱們就能夠把星星,飛機,子彈,爆炸對象都寫出來了:下面是整個allSprite.js的代碼:

(function(W){
    "use strict"
    var planWidth = 24,
        planHeight = 24,
        missleWidth = 70,
        missleHeight = 70,
        boomWidth = 60;
    //精靈類
    W.Sprite = function(name , painter , behaviors , args){
        if(name !== undefined) this.name = name;
        if(painter !== undefined) this.painter = painter;
        this.top = 0;
        this.left = 0;
        this.width = 0;
        this.height = 0;
        this.velocityX = 3;
        this.velocityY = 2;
        this.visible = true;
        this.animating = false;
        this.behaviors = behaviors;
        this.rotateAngle = 0;
        this.blood = 50;
        this.fullBlood = 50;
        if(name==="plan"){
            this.rotateSpeed = 0.05;
            this.rotateLeft = false;
            this.rotateRight = false;
            this.fire = false;
            this.firePerFrame = 10;
            this.fireLevel = 1;
        }else if(name==="star"){
            this.width = Math.random()*2;
            this.speed = 1*this.width/2;
            this.lightLength = 5;
            this.cacheCanvas = document.createElement("canvas");
            this.cacheCtx = this.cacheCanvas.getContext('2d');
            this.cacheCanvas.width = this.width+this.lightLength*2;
            this.cacheCanvas.height = this.width+this.lightLength*2;
            this.painter.cache(this);
        }else if(name==="badPlan"){
            this.badKind = 1;
            this.speed = 2;
            this.rotateAngle = Math.PI;
        }else if(name==="missle"){
            this.width = missleWidth;
        }else if(name==="boom"){
            this.width = boomWidth;
        }else if(name==="food"){
            this.width = 40;
            this.speed = 3;
            this.kind = "LevelUP"
        }
        this.toLeft = false;
        this.toTop = false;
        this.toRight = false;
        this.toBottom = false;

        this.outArcRadius = Math.sqrt((this.width/2*this.width/2)*2);

        if(args){
            for(var arg in args){
                this[arg] = args[arg];
            }
        }
    }
    Sprite.prototype = {
        constructor:Sprite,
        paint:function(){
            if(this.name==="badPlan"){this.update();}

            if(this.painter !== undefined && this.visible){
                if(this.name!=="badPlan") {
                    this.update();
                }
                if(this.name==="plan"||this.name==="missle"||this.name==="badPlan"){
                    ctx.save();
                    ctx.translate(this.left , this.top);
                    ctx.rotate(this.rotateAngle);
                    this.painter.paint(this);
                    ctx.restore();
                }else {
                    this.painter.paint(this);
                }
            }
        },
        update:function(time){
            if(this.behaviors){
                for(var i=0;i<this.behaviors.length;i++){
                    this.behaviors[i].execute(this,time);
                }
            }
        }
    }

    // 精靈表繪製器
    W.SpriteSheetPainter = function(cells , isloop , endCallback , spritesheet){
        this.cells = cells || [];
        this.cellIndex = 0;
        this.dateCount = null;
        this.isloop = isloop;
        this.endCallback = endCallback;
        this.spritesheet = spritesheet;
    }
    SpriteSheetPainter.prototype = {
        advance:function(){
            this.cellIndex = this.isloop?(this.cellIndex===this.cells.length-1?0:this.cellIndex+1):(this.cellIndex+1);
        },
        paint:function(sprite){
            if(this.dateCount===null){
                this.dateCount = new Date();
            }else {
                var newd = new Date();
                var tc = newd-this.dateCount;
                if(tc>40){
                    this.advance();
                    this.dateCount = newd;
                }
            }
            if(this.cellIndex<this.cells.length || this.isloop){
                var cell = this.cells[this.cellIndex];
                ctx.drawImage(this.spritesheet , cell.x , cell.y , cell.w , cell.h , sprite.left-sprite.width/2 , sprite.top-sprite.width/2 , cell.w , cell.h);
            } else if(this.endCallback){
                this.endCallback.call(sprite);
                this.cellIndex = 0;
            }
        }
    }

    //特製飛機精靈表繪製器
    W.controllSpriteSheetPainter = function(cells , spritesheet){
        this.cells = cells || [];
        this.cellIndex = 0;
        this.dateCount = null;
        this.isActive = false;
        this.derection = true;
        this.spritesheet = spritesheet;
    }
    controllSpriteSheetPainter.prototype = {
        advance:function(){
            if(this.isActive){
                this.cellIndex++;
                if(this.cellIndex === this.cells.length){
                    this.cellIndex = 0;
                    this.isActive = false;
                }
            }
        },
        paint:function(sprite){
            if(this.dateCount===null){
                this.dateCount = new Date();
            }else {
                var newd = new Date();
                var tc = newd-this.dateCount;
                if(tc>sprite.firePerFrame){
                    this.advance();
                    this.dateCount = newd;
                }
            }
            var cell = this.cells[this.cellIndex];
            ctx.drawImage(this.spritesheet , cell.x , cell.y , cell.w , cell.h , -planWidth/2 , -planHeight/2 , cell.w , cell.h);
        }
    }

    W.planBehavior = [
        {execute:function(sprite,time){
            if(sprite.toTop){
                sprite.top = sprite.top<planHeight/2? sprite.top : sprite.top-sprite.velocityY;
            }
            if(sprite.toLeft){
                sprite.left = sprite.left<planWidth/2? sprite.left : sprite.left-sprite.velocityX;
            }
            if(sprite.toRight){
                sprite.left = sprite.left>canvas.width-planWidth/2? sprite.left : sprite.left+sprite.velocityX;
            }
            if(sprite.toBottom){
                sprite.top = sprite.top>canvas.height-planHeight/2? sprite.top : sprite.top+sprite.velocityY;
            }
            if(sprite.rotateLeft){
                sprite.rotateAngle -= sprite.rotateSpeed;
            }
            if(sprite.rotateRight){
                sprite.rotateAngle += sprite.rotateSpeed;
            }
            if(sprite.fire&&!sprite.painter.isActive){
                sprite.painter.isActive = true;
                this.shot(sprite);

            }
        },
        shot:function(sprite){
            this.addMissle(sprite , sprite.rotateAngle);
            var missleAngle = 0.1
            for(var i=1;i<sprite.fireLevel;i++){
                this.addMissle(sprite , sprite.rotateAngle-i*missleAngle);
                this.addMissle(sprite , sprite.rotateAngle+i*missleAngle);
            }

            var audio = document.getElementsByTagName("audio");
            for(var i=0;i<audio.length;i++){
                console.log(audio[i].paused)
                if(audio[i].src.indexOf("shot")>=0&&audio[i].paused){
                    audio[i].play();
                    break;
                }
            }
        },
        addMissle:function(sprite , angle){
                for(var j=0;j<missles.length;j++){
                    if(!missles[j].visible){
                        missles[j].left = sprite.left;
                        missles[j].top = sprite.top;
                        missles[j].rotateAngle = angle;
                        var missleSpeed = 20;
                        missles[j].velocityX = missleSpeed*Math.sin(-missles[j].rotateAngle);
                        missles[j].velocityY = missleSpeed*Math.cos(-missles[j].rotateAngle);
                        missles[j].visible = true;
                        break;
                    }
                }
            }
        }
    ]

    W.starBehavior = [
        {execute:function(sprite,time){
            if(sprite.top > canvas.height){
                sprite.left = Math.random()*canvas.width;
                sprite.top = Math.random()*canvas.height - canvas.height;
            }
            sprite.top += sprite.speed;
        }}
    ]

    W.starPainter = {
        paint:function(sprite){
            ctx.drawImage(sprite.cacheCanvas , sprite.left-sprite.width/2-sprite.lightLength , sprite.top-sprite.width/2-sprite.lightLength)
        },

        cache:function(sprite){
            sprite.cacheCtx.save();
            var opacity = 0.5,addopa = 1/sprite.lightLength;
            sprite.cacheCtx.fillStyle = "rgba(255,255,255,0.8)";
            sprite.cacheCtx.beginPath();
            sprite.cacheCtx.arc(sprite.width/2+sprite.lightLength , sprite.width/2+sprite.lightLength , sprite.width/2 , 0 , 2*Math.PI);
            sprite.cacheCtx.fill();
            for(var i=1;i<=sprite.lightLength;i+=2){
                opacity-=addopa;
                sprite.cacheCtx.fillStyle = "rgba(255,255,255,"+opacity+")";
                sprite.cacheCtx.beginPath();
                sprite.cacheCtx.arc(sprite.width/2+sprite.lightLength , sprite.width/2+sprite.lightLength , sprite.width/2+i , 0 , 2*Math.PI);
                sprite.cacheCtx.fill();
            }
        }
    }

    W.foodBehavior = [
        {execute:function(sprite,time){
            sprite.top += sprite.speed;
            if(sprite.top > canvas.height+sprite.width){
                sprite.visible = false;
            }
        }}
    ]

    W.foodPainter = {
        paint:function(sprite){
            ctx.fillStyle = "rgba("+parseInt(Math.random()*255)+","+parseInt(Math.random()*255)+","+parseInt(Math.random()*255)+",1)"
            ctx.font="15px 微軟雅黑"
            ctx.textAlign = "center";
            ctx.textBaseline = "middle";
            ctx.fillText(sprite.kind , sprite.left , sprite.top);
        }
    }



    W.missleBehavior = [{
        execute:function(sprite,time){
            sprite.left -= sprite.velocityX;
            sprite.top -= sprite.velocityY;
            if(sprite.left<-missleWidth/2||sprite.top<-missleHeight/2||sprite.left>canvas.width+missleWidth/2||sprite.top<-missleHeight/2){
                sprite.visible = false;
            }
        }
    }];

    W.misslePainter = {
        paint:function(sprite){
            var img = new Image();
            img.src="../planGame/image/plasma.png"
            ctx.drawImage(img , -missleWidth/2+1 , -missleHeight/2+1 , missleWidth , missleHeight);
        }
    }

    W.badPlanBehavior = [{
        execute:function(sprite,time){
            if(sprite.top > canvas.height || !sprite.visible){
                var random = Math.random();

                if(point>=200&&point<400){
                    sprite.fullBlood = 150;
                    if(random<0.1){
                        sprite.badKind = 2;
                        sprite.fullBlood = 250;
                    }
                }else if(point>=400&&point<600){
                    sprite.fullBlood = 250;
                    if(random<0.2){
                        sprite.badKind = 2;
                        sprite.fullBlood = 400;
                    }
                    if(random<0.1){
                        sprite.badKind = 3;
                        sprite.fullBlood = 600;
                    }
                }else if(point>=600){
                    sprite.fullBlood = 500;
                    if(random<0.4){
                        sprite.badKind = 2;
                        sprite.fullBlood = 700;
                    }
                    if(random<0.2){
                        sprite.badKind = 3;
                        sprite.fullBlood = 1000;
                    }
                }

                sprite.visible = true;
                sprite.blood = sprite.fullBlood;
                sprite.left = Math.random()*(canvas.width-2*planWidth)+planWidth;
                sprite.top = Math.random()*canvas.height - canvas.height;
            }
            sprite.top += sprite.speed;
        },
        shot:function(sprite){
            this.addMissle(sprite , sprite.rotateAngle);
            var missleAngle = 0.1
            for(var i=1;i<sprite.fireLevel;i++){
                this.addMissle(sprite , sprite.rotateAngle-i*missleAngle);
                this.addMissle(sprite , sprite.rotateAngle+i*missleAngle);
            }
        },
        addMissle:function(sprite , angle){
            for(var j=0;j<missles.length;j++){
                if(!missles[j].visible){
                    missles[j].left = sprite.left;
                    missles[j].top = sprite.top;
                    missles[j].rotateAngle = angle;
                    var missleSpeed = 20;
                    missles[j].velocityX = missleSpeed*Math.sin(-missles[j].rotateAngle);
                    missles[j].velocityY = missleSpeed*Math.cos(-missles[j].rotateAngle);
                    missles[j].visible = true;
                    break;
                }
            }
        }
    }];

    W.badPlanPainter = {
        paint:function(sprite){
            var img = new Image();
            img.src="../planGame/image/ship.png"
            switch(sprite.badKind){
                case 1:ctx.drawImage(img , 96 , 0 , planWidth , planWidth , -planWidth/2 , -planHeight/2 , planWidth , planWidth);
                break;

                case 2:ctx.drawImage(img , 120 , 0 , planWidth , planWidth , -planWidth/2 , -planHeight/2 , planWidth , planWidth);
                break;

                case 3:ctx.drawImage(img , 144 , 0 , planWidth , planWidth , -planWidth/2 , -planHeight/2 , planWidth , planWidth);
                break;
            }

            ctx.strokeStyle = "#FFF";
            ctx.fillStyle = "#F00";
            var bloodHeight = 1;
            ctx.strokeRect(-planWidth/2-1 , planHeight+bloodHeight+3 , planWidth+2 , bloodHeight+2);
            ctx.fillRect(planWidth/2-planWidth*sprite.blood/sprite.fullBlood , planHeight+bloodHeight+3 , planWidth*sprite.blood/sprite.fullBlood , bloodHeight);
        }
    }

    W.planSize = function(){
        return {
            w:planWidth,
            h:planHeight
        }    
    }
})(window);
View Code

這些繪製方法之類的都相對比較簡單。

  主要說一下飛機的運動以及對象數量的控制,飛機怎麼運動?毫無疑問,經過鍵盤控制它運動,可能不少人就會想到經過keydown這個方法按下的時候經過判斷keyCode來讓飛機持續運動。可是有個問題,keydown事件不支持多鍵按下,也就是說,當你按下X鍵時,keyCode是88,與此同時你按下方向鍵後,keyCode會瞬間變成37,也就是說,若是你單純的想靠keydown來控制飛機運動,飛機就只能作一件事,要麼只能夠往某個方向移動,要麼只會開槍。

  因此,咱們要經過keydown和keyup來實現飛機的運動,原理很容易理解:當咱們按下往左的方向鍵時,咱們給飛機一個往左的狀態,也就是讓飛機的toLeft屬性爲true,而在動畫循環中,判斷飛機的狀態,若是toLeft爲true則飛機的x值不停地減小,飛機也就會不停地往左移動,而後當咱們擡起手指時觸發keyup事件,咱們就再keyup事件中解除飛機往左的狀態。飛機也就中止往左移動了。其餘狀態也同樣的原理,這樣寫的話,就可以讓飛機多種狀態於一輩子了。能夠同時開槍同時處處跑了。

實現的代碼以下:

//keydown/keyup事件的綁定  
  window.onkeydown = function(event){
            switch(event.keyCode){
                case 88:myplan.fire = true;
                break;
                case 90:myplan.rotateLeft=true;
                break;
                case 67:myplan.rotateRight=true;
                break;
                case 37:myplan.toLeft = true;
                break;
                case 38:myplan.toTop = true;
                break;
                case 39:myplan.toRight = true;
                break;
                case 40:myplan.toBottom = true;
                break;
            }
        }

        window.onkeyup = function(event){
            switch(event.keyCode){
                case 88:myplan.fire = false;
                break;
                case 90:myplan.rotateLeft=false;
                break;
                case 67:myplan.rotateRight=false;
                break;
                case 37:myplan.toLeft = false;
                break;
                case 38:myplan.toTop = false;
                break;
                case 39:myplan.toRight = false;
                break;
                case 40:myplan.toBottom = false;
                break;
            }
        }    


//飛機每一幀的狀態更新處理代碼
execute:function(sprite,time){
            if(sprite.toTop){
                sprite.top = sprite.top<planHeight/2? sprite.top : sprite.top-sprite.velocityY;
            }
            if(sprite.toLeft){
                sprite.left = sprite.left<planWidth/2? sprite.left : sprite.left-sprite.velocityX;
            }
            if(sprite.toRight){
                sprite.left = sprite.left>canvas.width-planWidth/2? sprite.left : sprite.left+sprite.velocityX;
            }
            if(sprite.toBottom){
                sprite.top = sprite.top>canvas.height-planHeight/2? sprite.top : sprite.top+sprite.velocityY;
            }
            if(sprite.rotateLeft){
                sprite.rotateAngle -= sprite.rotateSpeed;
            }
            if(sprite.rotateRight){
                sprite.rotateAngle += sprite.rotateSpeed;
            }
            if(sprite.fire&&!sprite.painter.isActive){
                sprite.painter.isActive = true;
                this.shot(sprite);

            }

就是如此簡單。

  而後說下對象控制,打飛機遊戲,會發射大量子彈,產生大量對象,包括爆炸啊,飛機啊,子彈等,若是不停地進行對象的生成和銷燬,會讓瀏覽器的負荷變得很大,運行了一段時間後就會卡出翔了。因此,咱們要用能夠循環利用的對象來解決這個問題,不進行對象的銷燬,對全部對象進行保存,循環利用。

  個人作法就是,在遊戲初始化的時候,直接生成必定數量的對象,存放在數組裏面。當咱們須要一個對象的時候,就從裏面取,當用完後,再放回數組裏面。數組裏的全部對象都有一個屬性,visible,表明對象當前是否可用。

  舉個例子,當個人飛機發射一發炮彈,我須要一發炮彈,因此我就到炮彈數組裏遍歷,若是遍歷到的炮彈visible爲true,也就說明該對象正在使用着,不能拿來用,因此繼續遍歷,直到遍歷到visible爲false的炮彈對象,說明這個對象暫時沒人用。而後就能夠拿過來從新設置屬性,投入使用了。當炮彈擊中敵人或者打出畫布外的時候,把炮彈的visible設成false,又成了一個沒人用的炮彈在數組裏存放起來等待下一次調用。

  因此,咱們要預算算好頁面大概要用到多少個對象,而後就預先準備好對象,這樣,在遊戲進行中,不會有對象進行生成和銷燬,對遊戲性能方面就有了提高了。

  

  最後再說下音頻,遊戲裏面要用到多個一樣的audio才能保證音效的不間斷性:

var audio = document.getElementsByTagName("audio");
                                            for(var i=0;i<audio.length;i++){
                                                console.log(audio[i].paused)
                                                if(audio[i].src.indexOf("boom")>=0&&audio[i].paused){
                                                    audio[i].play();
                                                    break;
                                                }
                                            }

 

好吧,基本上就這樣了。技術或許還不夠好,純碎作個記錄,若是代碼有不當正處,歡迎指出,共同窗習。

源碼地址:https://github.com/whxaxes/canvas-test/tree/gh-pages/src/Game-demo/planGame

相關文章
相關標籤/搜索