首页 > 解决方案 > JS浏览器游戏——避免初始化所有对象

问题描述

我遵循了一个关于如何使用 JS/HTML 构建基本游戏的教程,现在我正在扩展它:游戏。(点击空格开火,右箭头向右移动,左箭头向左移动)

我有:

我在我的数组中添加了30多个.enemies对象,#enemies我感觉在游戏运行时对页面的速度有影响。什么是不逐渐在我的数组中添加.enemies对象的最有效方法?#enemies

var hero = {
    top : 700,
    left : 550
};


var missiles = [];

var enemies = [
{left: 700, top: -100},
{left: 500, top: -200},
{left: 200, top: -300},
{left: 700, top: -400},
{left: 400, top: -500},
{left: 800, top: -600},
{left: 200, top: -900},
{left: 250, top: -900},
{left: 120, top: -900},
{left: 160, top: -900},
{left: 280, top: -900},
{left: 330, top: -900},
{left: 330, top: -1100},
{left: 280, top: -1500},
{left: 800, top: -1500},
{left: 500, top: -1500},
{left: 700, top: -1550},
{left: 60, top: -1550},
{left: 560, top: -1600},
{left: 60, top: -1750},
{left: 900, top: -1700},
{left: 150, top: -1950},
{left: 200, top: -1960},
{left: 250, top: -1980},
{left: 50, top: -2500},
{left: 100, top: -2500},
{left: 150, top: -2500},
{left: 200, top: -2540},
{left: 250, top: -2580},
{left: 300, top: -2580},
{left: 350, top: -2580}
];

var lifes = [
    {left: 400, top: -600},
    {left: 50, top: -1300}

]


let health = document.getElementById("health");


const drawEnemies = () => {
    document.getElementById("enemies").innerHTML = "";
    for(var i = 0 ; i < enemies.length ; i++){
        document.getElementById('enemies').innerHTML +=
        `
        <div class="enemy" style='
        left:${enemies[i].left}px;
        top: ${enemies[i].top}px;
        '></div>
        `;
    }
}

const drawLifes = () => {
    document.getElementById("lifes").innerHTML = "";
    for(var i = 0 ; i < lifes.length ; i ++){
        document.getElementById('lifes').innerHTML += 
        `
        <div class='life' style='left:${lifes[i].left}px; 
        top:${lifes[i].top}px;'>
        </div>
        `;
    }

}

const drawMissiles = () => {

    document.getElementById("missiles").innerHTML = "";
    for(var i = 0; i < missiles.length ; i++){
        document.getElementById('missiles').innerHTML += 
        `
        <div class='missile' style='left:${missiles[i].left}px; 
        top:${missiles[i].top}px;'>
        </div>
        `;

        missiles[i].top
        missiles[i].left
    }
}

const drawHero = () => {
    document.onkeydown = function(e){
        if(e.keyCode == 65){
            health.value -=10;
        }
        if(e.keyCode == 37){
            hero.left = hero.left - 30;
            moveHero();

        }
        else if(e.keyCode ==39){
            hero.left = hero.left + 30;
            moveHero();

        }
        else if(e.keyCode == 32){
            missiles.push(
                {
                    left: hero.left + 25,
                    top: hero.top - 30
                }
            );
            drawMissiles();          
        }
    }
}



const moveEnemies = () => {

    for(var i = 0 ; i < enemies.length ; i++){
        enemies[i].top += 2;
        if(enemies[i].top > 700){
            health.value -= 10;
            enemies.splice(i,1);
            if(health.value <= 0){
                alert("GAME OVER");
                document.location.reload();
            }

        }
    }

}

const moveHero = () => {
    document.getElementById("hero").style.left = hero.left + "px";
}

const moveMissiles = () =>{
    for(var i = 0 ; i < missiles.length ; i++){
        missiles[i].top -= 10;
    }
}

const moveLifes= () =>{
    for(var i = 0 ; i < lifes.length ; i++){
        lifes[i].top += 1;
    }
}

const explosion = (topEn, leftEn, delay = 300) => {
    const div = document.createElement('div');
    div.id = 'explosion';
    div.style.top = topEn + 'px';
    div.style.left = leftEn + 'px';

    document.getElementById('explosions').append(div);
    setTimeout(() => {
      div.remove()
    }, delay);
  }



const collisionDetector = () => {
    for(var i = 0 ; i < enemies.length ; i++){
        for(var j = 0 ; j < missiles.length ; j++){
            if(
                (missiles[j].top <= enemies[i].top + 50) &&
                (missiles[j].top >= enemies[i].top) &&
                (missiles[j].left >= enemies[i].left) &&
                (missiles[j].left <= enemies[i].left +50)
            ){
                explosion(enemies[i].top, enemies[i].left);
                enemies.splice(i, 1);
                missiles.splice(j,1);
            }
        }
    }
}

const lifeEating = () => {
    for(var i = 0 ; i < lifes.length ; i++){
        if(
            (lifes[i].top >= hero.top -60) &&
            (lifes[i].left >= hero.left) &&
            (lifes[i].left <= hero.left +50)
        ){
            health.value += 20;
            lifes.splice(i,1);
        }

    }
}



const gameLoop = () => {
    setTimeout(gameLoop,20);
    moveMissiles();
    drawMissiles();
    moveEnemies();
    drawEnemies();
    moveLifes();
    drawLifes();
    collisionDetector();
    lifeEating();
}

const app = () => {
    drawHero();
    drawEnemies();
    gameLoop();
}


app();

标签: javascript

解决方案


将对象添加到数组不会真正导致速度变慢,但过度更新页面上的 HTML 会。试试这个作为你的 darwEnemies 函数:

const drawEnemies = () => {
    var htmlToAdd = "";
    for(var i = 0 ; i < enemies.length ; i++){
        htmlToAdd +=
        `
        <div class="enemy" style='
        left:${enemies[i].left}px;
        top: ${enemies[i].top}px;
        '></div>
        `;
    }
    document.getElementById('enemies').innerHTML = htmlToAdd;
}

对于 30 个敌人,这个函数现在更新 HTML 一次而不是 31 次,因为我们现在更新 for 循环中的变量而不是页面的 HTML 本身。你可以用 drawLifes() 和 drawMissles() 做同样的事情。

const drawLifes = () => {
    var htmlToAdd = "";
    for(var i = 0 ; i < lifes.length ; i ++){
        htmlToAdd += 
        `
        <div class='life' style='left:${lifes[i].left}px; 
        top:${lifes[i].top}px;'>
        </div>
        `;
    }
    document.getElementById("lifes").innerHTML = htmlToAdd;

}

const drawMissiles = () => {

    var htmlToAdd = "";
    for(var i = 0; i < missiles.length ; i++){
        htmlToAdd += 
        `
        <div class='missile' style='left:${missiles[i].left}px; 
        top:${missiles[i].top}px;'>
        </div>
        `;

        missiles[i].top
        missiles[i].left
    }
    document.getElementById('missiles').innerHTML = htmlToAdd;
}

要添加更快的敌人,请为敌人中的每个对象添加“帧速率”属性。

var enemies = [
{framerate: 1, left: 700, top: -100},
{framerate: 1, left: 500, top: -200},
{framerate: 1, left: 200, top: -300},
{framerate: 1, left: 700, top: -400},
{framerate: 1, left: 400, top: -500},
{framerate: 2, left: 800, top: -600},
{framerate: 2, left: 200, top: -900},
{framerate: 2, left: 250, top: -900},
{framerate: 2, left: 120, top: -900},
{framerate: 2, left: 160, top: -900},
{framerate: 2, left: 280, top: -900},
{framerate: 2, left: 330, top: -900},
{framerate: 2, left: 330, top: -1100},
{framerate: 2, left: 280, top: -1500},
{framerate: 2, left: 800, top: -1500},
{framerate: 2, left: 500, top: -1500},
{framerate: 2, left: 700, top: -1550},
{framerate: 2, left: 60, top: -1550},
{framerate: 2, left: 560, top: -1600},
{framerate: 2, left: 60, top: -1750},
{framerate: 2, left: 900, top: -1700},
{framerate: 2, left: 150, top: -1950},
{framerate: 2, left: 200, top: -1960},
{framerate: 2, left: 250, top: -1980},
{framerate: 2, left: 50, top: -2500},
{framerate: 2, left: 100, top: -2500},
{framerate: 2, left: 150, top: -2500},
{framerate: 2, left: 200, top: -2540},
{framerate: 2, left: 250, top: -2580},
{framerate: 2, left: 300, top: -2580},
{framerate: 2, left: 350, top: -2580}
];

这将为我们在 moveEnemies 函数中提供参考,告诉我们移动每个敌人的频率。

var frame = 0;
const moveEnemies = () => {
    frame++;
    for(var i = 0 ; i < enemies.length ; i++){
        if(frame % enemies[i].framerate == 0){
            enemies[i].top += 2;
            if(enemies[i].top > 700){
                health.value -= 10;
                enemies.splice(i,1);
                if(health.value <= 0){
                    alert("GAME OVER");
                    document.location.reload();
                }
            }
        }
    }
}

如果敌人的帧率为 2,我们只会每两帧移动一次该敌人。因为你所有的敌人已经在每一帧都在移动,所以这段代码不会真正加速任何敌人,而是减慢其中一些敌人的速度。为了加快速度,增加游戏运行的频率,如下所示:

const gameLoop = () => {
    setTimeout(gameLoop,10);//used to be 20
    moveMissiles();
    drawMissiles();
    moveEnemies();
    drawEnemies();
    moveLifes();
    drawLifes();
    collisionDetector();
    lifeEating();
}

推荐阅读