浏览器在运行JavaScript时冻结

Browser freezes up when running JavaScript

本文关键字:冻结 JavaScript 运行 浏览器      更新时间:2023-09-26

当我运行此代码时,窗口/选项卡会冻结,我不知道如何调试/修复它,好吗?

http://jsfiddle.net/z3DjY/1/

var levelArray = new Array();
var canvas;
var ctx;
var playerLocation;
var edge;
var elementEdge = 10; // Each element is 10x10 pixels
var workerArray;
var ghostLocationArray;
var levelArray = [
["player", "empty", "empty", "empty", "wall", "wall", "empty",
    "empty", "wall", "wall", "empty", "empty", "empty", "empty",
    "empty", "empty", "empty", "wall", "empty", "wall", "wall",
    "wall", "wall", "empty", "wall", "empty", "wall", "empty",
    "box", "wall", "empty", "wall", "empty", "empty", "empty",
    "empty", "empty", "empty", "wall", "wall", "wall", "empty",
    "wall", "wall", "empty", "empty", "ghost", "wall", "ghost"]
];
$(function () {
aBoyandhisBox.music = document.getElementById("music");
aBoyandhisBox.music.volume = 0.25;
// set the game state as "starting screen"
aBoyandhisBox.state = aBoyandhisBox.STATE_STARTING_SCREEN;
// start the game when clicking anywhere in starting screen
$('#game').click(function () {
    setTimeout(playMusic, 1000);
    if (aBoyandhisBox.state == aBoyandhisBox.STATE_STARTING_SCREEN) {
        $("#help").fadeOut();
        // change the state to playing.
        aBoyandhisBox.state = aBoyandhisBox.STATE_PLAYING;
        gameLoop();
    }
});
// get the reference of the context
canvas = document.getElementById('game');
ctx = canvas.getContext('2d');
console.log(levelArray[0]);
});

//一旦页面加载完,此功能就会启动

function gameLoop() {
// Initializing all Global Variables
edge = Math.sqrt(levelArray.length);
// Canvas setup function calls here, including calls to assign input handlers
setupGhostWorkerArray();
setupCanvas(levelArray);
// Adding direct user input to a Canvas Element
canvas.addEventListener("keyup", keyHandler, false);

//实际游戏循环

while (isPlayerAlive && boxFound) {
    addHumanPause();
    hauntLevel(levelArray);
}
}
function setupGhostWorkerArray() {
workerArray = new Array();
ghostLocationArray = new Array();
// Assuming a level has 2 ghosts
for (i = 0, j = 0; i < levelArray[0].length; i++) {
    if (levelArray[i] == "ghost") {
        ghostArray[j] = i;
        workerArray[j] = new Worker("gameWorker.js");
        j++;
    }
}
}
function setupCanvas(levelArray) {
var currentX = 0,
    currentY = 0;
emptyTile = document.getElementById('empty');
ghostTile = document.getElementById('ghost');
playerTile = document.getElementById('boy');
wallTile = document.getElementById('wall');
boxTile = document.getElementById('box');
for (var i = 0; i < edge; i++) {
    for (var j = 0; j < edge; j++) {
        switch (levelArray[i][j]) {
            case "empty":
                // empty location
                ctx.drawImage(emptyTile, currentX, currentY);
                break;
            case "wall":
                // wall block
                ctx.drawImage(wallTile, currentX, currentY);
                break;
            case "box":
                // box block
                ctx.drawImage(boxTile, currentX, currentY);
                break;
            case "ghost":
                // enemy sprite
                ctx.drawImage(ghostTile, currentX, currentY);
                break;
            case "player":
                // player sprite
                ctx.drawImage(playerTile, currentX, currentY);
                break;
        }
        currentX += elementEdge;
    }
    currentY += elementEdge;
}
}

//处理移动的功能:为
中的精灵提供移动方向级别,以及该级别

//将在画布上反映这些更改。移动包括将对象移动一个
在指定的任何方向阻塞

//返回更新后的数组;这里没有游戏逻辑,物品只是在周围移动

function moveObject(objectIndex, direction) {
// Calculate current X & Y co-ordinates based on objectIndex
var currentX = objectIndex % edge;
var currentY = parseInt(objectIndex / edge);
var changeY, changeX, indexChange;
switch (direction) {
    case "up":
        indexChange = objectIndex - edge;
        changeX = 0;
        changeY = elementEdge * -1;
        break;
    case "down":
        indexChange = objectIndex + edge;
        changeX = 0;
        changeY = elementEdge;
        break;
    case "left":
        indexChange = objectIndex - 1;
        changeX = elementEdge * -1;
        changeY = 0;
        break;
    case "right":
        indexChange = objectIndex + 1;
        changeX = elementEdge;
        changeY = 0;
        break;
}
var newIndex = objectIndex + indexChange;
//Only empty locations (or locations with a player on them) are valid for movement purposes
if (levelArray[newIndex] == "empty" || levelArray[newIndex] == "player" || levelArray[newIndex] == "box") {
    var appropriateTile;
    if (levelArray[ObjectIndex] == "ghost") {
        appropriateTile = document.getElementById("ghostTile");
        for (var i = 0; i < ghostLocationArray.length; i++) {
            if (ghostLocationArray[i] == objectIndex) ghostLocationArray[i] = newIndex;
        }
    } else {
        //Only other thing that can move is the player
        appropriateTile = document.getElementById("playerTile");
        playerLocation = objectIndex + indexChange;
    }
    levelArray[newIndex] = levelArray[objectIndex];
    levelArray[objectIndex] = "empty";
    ctx.drawImage(emptyTile, currentX, currentY);
    currentY += changeY;
    currentX += changeX;
    ctx.drawImage(appropriateTile, currentX, currentY);
}
}

//玩家没有被幽灵吃掉

function isPlayerAlive(levelArray) {
return checkFor("player");
}

//玩家没有踩到盒子

function boxFound(levelArray) {
return checkFor("box");
}
function checkFor(checkFor) {
var found = false;
for (var i = 0; i < levelArray.length; i++) {
    if (levelArray[i] == checkFor);
    found = true;
}
return found;
}

//将数组传递到工作人员的漫游()中,以在地图上为重影获取新位置

function hauntLevel(levelArray) {
var subArrayEdge = 7;
var arrayEdge = Math.sqrt(levelArray.length);
var ghostFound = false,
    subArray;
for (var i = 0, l = 0; i < levelArray.length; i++) {
    ghostFound = false;
    if (levelArray[i] == "ghost") {
        subArray = new Array();
        ghostFound = true;
        // Ghost found, start constructing a 7x7 composed of the blocks surrounding
        // the ghost (blocks out of bounds on the levelArray are represented as walls).
        // Start from the upper left corner, left to right, top to bottom(like a page in a book)
        var blockIndex = i - (arrayEdge * 3) - 3;
        for (var j = 0; j < 49; j++) //A 7x7 array will have 0-48 indices
        {
            for (var k = 0; k < subArrayEdge; k++) {
                if (blockIndex < 0 || blockIndex > (levelArray.length - 1)) {
                    subArray[j] = "wall";
                } else {
                    subArray[j] = levelArray[blockIndex];
                }
                blockIndex++;
            }
            // Next row, start from the left again
            blockIndex = blockIndex + arrayEdge - subArrayEdge;
        }
    }
    if (ghostFound) {
        workerArray[l].onmessage = function (event) {
            moveObject(ghostLocationArray[l], event.data);
        }
        workerArray[l].postMessage(subArray);
        l++;
    }
}
}
function keyHandler(theEvent) {
var direction;
switch (theEvent.keyCode) {
    case 87:
        // w key to move up
        direction = "up";
        break;
    case 83:
        // s key to move down
        direction = "down";
        break;
    case 65:
        // a key to move left
        direction = "left";
        break;
    case 68:
        // d key to move right
        direction = "right";
        break;
    case 82:
        // r key to restart the level
        // NOT IMPLEMENTED
        break;
    case 81:
        // q key to restart the game
        // NOT IMPLEMENTED
        break;
}
moveObject(playerLocation, direction);
}

这会无限期地阻止。

while (isPlayerAlive && boxFound) {
    addHumanPause();
    hauntLevel(levelArray);
}

你想把你的游戏循环设置为一个每隔一段时间就会触发的"滴答"事件。在这段时间里做所有的逻辑和更新。

你已经写了很多代码来证明你的能力,所以我只想让你看看setInterval或setTimeout,而不是试图为你拼凑所有这些。

祝你好运!

此外,永远不要这样做:

// Slow down the game to a human playable level
// Long Working Loop
function addHumanPause() {
    for (var i = 0; i < 10000; i++) {
        for (var j = 0; j < 10000; j++) {
            // Do Nothing
        }
    }
}

所做的只是让CPU旋转一段时间,并且不让浏览器对任何事件做出响应。即使是像按键、点击或"关闭这个%#@$,它让我的腿燃烧起来!"

这样的重要操作也不例外