Heim  >  Artikel  >  Web-Frontend  >  Verwenden Sie HTML5 Canvas, um ein einfaches Masturbationsspiel zu erstellen

Verwenden Sie HTML5 Canvas, um ein einfaches Masturbationsspiel zu erstellen

不言
不言Original
2018-06-05 11:44:131856Durchsuche

In diesem Artikel wird hauptsächlich die Verwendung von HTML5 Canvas zum Erstellen eines einfachen Masturbationsspiels vorgestellt. Der Autor stellt auch relevanten Javascript-Code zur Verfügung.

Zuvor habe ich in Dang Knights DEMO eine Masturbation gesehen Spiel und zog seine Bilder und Audio herunter. . . . Ich habe es nur zum Spaß umgeschrieben. Nur zur Unterhaltung. . . . . . Ich verwende kein Framework, ich schreibe alle JS selbst. . . . . . Dies ist also ein einfaches Tutorial, das für diejenigen hilfreich sein kann, die noch keine Erfahrung mit Canvas haben. Bitte verzeihen Sie mir.

Beginnen wir ohne weitere Umschweife mit der DEMO: Airplane Game. Der Originalposter hat dies nur zur Unterhaltung geschrieben und hatte nicht die Absicht, daraus ein Serious Game zu machen.

Kommen wir zum Thema: Die Masturbationsspieldatei enthält die Index.html-Eintragsdatei, die Sprite-Logik-Verarbeitungsdatei allSprite.js, die Loading.js-Ladeverarbeitungsdatei und data.js (einige initialisierte Daten).

Zunächst einmal erfordern normale Spiele grundsätzlich ein Laden. Die Ladeseite wird zum Vorladen von Daten verwendet, einschließlich Sprite-Sheet-Bildern, Audio usw. Da es sich um ein kleines Spiel handelt, müssen die einzigen Dinge geladen werden sind einige Audio- und Bilddateien. Die darin enthaltenen Ladecodes dienen hauptsächlich der Erstellung von Ladeanimationen, daher werde ich sie nicht veröffentlichen. Wenn Sie interessiert sind, schauen Sie sich einfach die Konsole in der DEMO an:

XML/HTML-CodeInhalt in die Zwischenablage kopieren

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);   
        }   
    }   
}

Ich verwende zunächst ein Array in data.js, um die Links zu den Dateien zu speichern, und bestimme dann Unabhängig davon, ob es sich bei den Links um Bilder oder Audios handelt und ob es sich um Bilder handelt, verwenden Sie einfach preLoadImg zum Laden. Der Code zum Vorladen des Bildes ist sehr einfach. Erstellen Sie einfach ein neues Bildobjekt, weisen Sie ihm den Link zu und rufen Sie ihn nach dem Laden erneut auf. Audio wird geladen, indem ein HTML5-Audio-Dom-Objekt generiert und ihm der Link zugewiesen wird. Wenn der Browser erwartet, dass er die angegebene Audio-/Videowiedergabe fortsetzen kann, ohne ihn zum Puffern anzuhalten, tritt das Ereignis „canplaythrough“ auf , was bedeutet, dass beim Aufruf von canplaythrough das Audio fast geladen wurde und das nächste Audio geladen werden kann. Einfach so: Nachdem alles geladen ist, erfolgt der Rückruf und das Spiel beginnt.

Das Spiel erfordert viele Objekte, daher habe ich sie in einem Sprite-Objekt zusammengefasst. Die Bewegung jedes Frames zwischen verschiedenen Objekten kann mithilfe des Verhaltens separat geschrieben werden.

XML/HTML-CodeKopieren Sie den Inhalt in die Zwischenablage

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");   
        thisthis.cacheCtx = this.cacheCanvas.getContext('2d');   
        thisthis.cacheCanvas.width = this.width+this.lightLength*2;   
        thisthis.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);   
            }   
        }   
    }   
}

Nachdem Sie die Elfenklasse geschrieben haben, können Sie jeden zu generierenden Maler und jedes Verhalten schreiben verschiedene Objekte. Der nächste Schritt besteht darin, Maler zu schreiben. Der eine ist der normale Maler und der andere der Sprite-Sheet-Maler. Da Explosionsanimationen und Flugzeugschießanimationen nicht mit nur einem Bild erstellt werden können, müssen Sie es verwenden für das Sprite-Sheet:
2015511181456172.png (168×24)

2015511181533636.png (896×64)

Um diese zu zeichnen, müssen Sie einen Sprite-Sheet-Maler für sie anpassen. Im Folgenden finden Sie den einfachsten Sprite-Sheet-Maler. Je nach Komplexität des Spiels können Sie die Sprite-Sheet-Schreibmethode ändern, bis sie geeignet ist. Die Prinzipien sind jedoch ähnlich, nur geringfügige Änderungen:

XML/HTML-CodeKopieren Sie den Inhalt in die Zwischenablage

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);   
            }   
        }

Der normale Maler ist noch einfacher. Schreiben Sie einfach einen Maler und schreiben Sie alles, was Sie zeichnen möchten.

Mit der Sprite-Klasse und dem Sprite-Sheet-Renderer können wir Sterne, Flugzeuge, Kugeln und Explosionsobjekte schreiben: Das Folgende ist der gesamte allSprite.js-Code:

JavaScript-CodeInhalt in die Zwischenablage kopieren

(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(&#39;2d&#39;);   
            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);

Diese Zeichenmethoden sind relativ einfach.

Sprechen Sie hauptsächlich über die Bewegung des Flugzeugs und die Kontrolle der Anzahl der Objekte. Wie bewegt sich das Flugzeug? Es besteht kein Zweifel, dass viele Leute durch die Steuerung der Bewegung über die Tastatur daran denken, das Flugzeug durch Beurteilen des Tastencodes beim Drücken der Keydown-Methode weiter bewegen zu lassen. Es gibt jedoch ein Problem. Das Keydown-Ereignis unterstützt nicht das Drücken mehrerer Tasten, wenn Sie die Bewegung des Flugzeugs einfach per Tastendruck steuern möchten Es kann sich nur in eine bestimmte Richtung bewegen oder nur schießen.

  所以,我们要通过keydown和keyup来实现飞机的运动,原理很容易理解:当我们按下往左的方向键时,我们给飞机一个往左的状态,也就是让飞机的toLeft属性为true,而在动画循环中,判断飞机的状态,如果toLeft为true则飞机的x值不停地减少,飞机也就会不停地往左移动,然后当我们抬起手指时触发keyup事件,我们就再keyup事件中解除飞机往左的状态。飞机也就停止往左移动了。其他状态也一样的原理,这样写的话,就能够让飞机多种状态于一生了。可以同时开枪同时到处跑了。

实现的代码如下:

XML/HTML Code复制内容到剪贴板

//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){   
                spritesprite.top = sprite.top<planHeight/2? sprite.top : sprite.top-sprite.velocityY;   
            }   
            if(sprite.toLeft){   
                spritesprite.left = sprite.left<planWidth/2? sprite.left : sprite.left-sprite.velocityX;   
            }   
            if(sprite.toRight){   
                spritesprite.left = sprite.left>canvas.width-planWidth/2? sprite.left : sprite.left+sprite.velocityX;   
            }   
            if(sprite.toBottom){   
                spritesprite.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才能保证音效的不间断性:
复制代码

XML/HTML Code复制内容到剪贴板

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;   
                                                }   
                                            }

好吧,基本上就这样了。技术或许还不够好,纯碎做个记录,如果代码有不当正处,欢迎指出,共同学习。

相关推荐:

HTML5 Video/Audio播放本地文件

Das obige ist der detaillierte Inhalt vonVerwenden Sie HTML5 Canvas, um ein einfaches Masturbationsspiel zu erstellen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn