JavaScript 脚本错误

发布于 2024-11-01 16:07:25 字数 3925 浏览 0 评论 0原文

在阅读了视野算法之后,我决定为我正在开发的一款游戏自己创建一个。几个小时后,我想出了以下脚本:

function CalculateFOV() {
    ClearFOV();

    map[player.x][player.y].light = 100;

    var open = new Array();
    var closed = new Array();

    sourceNeighbors = map[player.x][player.y].neighbors;

    for(var i = 0;i<sourceNeighbors.length;i++) {
        open.push(sourceNeighbors[i]);
    }

    while(open.length > 0) {
        var curTile = open[0];

        var highestLightValue = 0;

        for(j in curTile.neighbors) {
            if(curTile.neighbors[j].light > highestLightValue) {
                highestLightValue = neighbors[j];               
            }
        }

        curTile.light = highestLightValue-10;

        if(curTile.light > 10) {
            for(var j = 0;j<curTile.neighbors.length;j++) {
                var addCell = true;

                if(FindValue(closed, open[0].neighbors[j])) addCell = false;

                if(addCell) {
                    open.push(neighbors[j]);
                }
            }
        }

        closed.push(curTile);
        open.shift();
    }
}

function ClearFOV() {
    for(var x = 0;x<mapSizeX;x++) {
        for(var y = 0;y<mapSizeY;y++) {
            map[x][y].lightValue = 0;
        }
    }
}

function FindValue(list, value) {
    for(var i = 0;i<list.length;i++) {
        if(list[i] == value) {
            return true;
        }
    }

    return false;
}

它应该从光源向外传播光值,并随着传播而减小。它使用一个已被赋予光值的图块的封闭列表,以避免多次击中单个单元格。 理论上这应该会大大提高效率。

不幸的是,它似乎存在一个错误,也许不止一个。我疲惫的大脑无法找到它(或它们),所以我真的很感激一些帮助。这还有道理吗?

另外,如果您可能需要它,这里是 Tile 类:

function Tile(x,y,character, thisMap, blocked, blockSight) {
    this.x = x;
    this.y = y;
    this.character = character;
    this.blocked = blocked;
    this.blockSight = blockSight;
    this.lightValue = 25;

    this.neighbors = new Array();
}

Tile.prototype = {
    create: function(blocked, blockSight, character) {
        this.blocked = blocked;
        this.blockSight = blockSight;
        this.character = character;

        var rockTile = RandomRange(1,4);
        var rockTileStr = "rock"+rockTile;
    },

    draw: function() {
        var id = '#t' + this.x + '_' + this.y;

        var lightColor = this.lightValue/100;

        $(id).css("opacity", lightColor); 
    },

    assign: function() {
        var north = this.x-1;
        var south = this.x+1;
        var east = this.y+1;
        var west = this.y-1;

        if(north >= 0 && south <= mapSizeX && west >= 0 && east <= mapSizeY) {

            //1st: we add the northwest neighbor.
            // *|/
            // -#-
            // /|\
            this.neighbors[0] = map[north][west];

            //2nd: we add the north neighbor.
            // \*/
            // -#-
            // /|\
            this.neighbors[1] = map[north][this.y];

            //3rd: we add the northeast neighbor.
            // \|*
            // -#-
            // /|\
            this.neighbors[2] = map[north][east];

            //4th: we add the east neighbor.
            // \|/
            // -#*
            // /|\
            this.neighbors[3] = map[this.x][east];

            //5th: we add the southeast neighbor.
            // \|/
            // -#-
            // /|*
            this.neighbors[4] = map[south][east];

            //6th: we add the south neighbor.
            // \|/
            // -#-
            // /*\
            this.neighbors[5] = map[south][this.y];

            //7th: we add the southwest neighbor.
            // \|/
            // -#-
            // *|\
            this.neighbors[6] = map[south][west];

            //8th: we add the west neighbor.
            // \|/
            // *#-
            // /|\
            this.neighbors[7] = map[this.x][west];
        }
    },
}

谢谢,并对发布这么长的问题表示歉意;我只是不知道现在还能去哪里。

After reading up on Field of View algorithms, I decided to create one myself for a game I'm working on. After a couple of hours, I came up with the following script:

function CalculateFOV() {
    ClearFOV();

    map[player.x][player.y].light = 100;

    var open = new Array();
    var closed = new Array();

    sourceNeighbors = map[player.x][player.y].neighbors;

    for(var i = 0;i<sourceNeighbors.length;i++) {
        open.push(sourceNeighbors[i]);
    }

    while(open.length > 0) {
        var curTile = open[0];

        var highestLightValue = 0;

        for(j in curTile.neighbors) {
            if(curTile.neighbors[j].light > highestLightValue) {
                highestLightValue = neighbors[j];               
            }
        }

        curTile.light = highestLightValue-10;

        if(curTile.light > 10) {
            for(var j = 0;j<curTile.neighbors.length;j++) {
                var addCell = true;

                if(FindValue(closed, open[0].neighbors[j])) addCell = false;

                if(addCell) {
                    open.push(neighbors[j]);
                }
            }
        }

        closed.push(curTile);
        open.shift();
    }
}

function ClearFOV() {
    for(var x = 0;x<mapSizeX;x++) {
        for(var y = 0;y<mapSizeY;y++) {
            map[x][y].lightValue = 0;
        }
    }
}

function FindValue(list, value) {
    for(var i = 0;i<list.length;i++) {
        if(list[i] == value) {
            return true;
        }
    }

    return false;
}

It's supposed to spread a light-value outward from a source, decreasing as it goes. It uses a Closed list of tiles which have already been given a light value in order to avoid hitting a single cell multiple times. This should theoretically increase the efficiency a lot.

Unfortunately, there seems to be an error, perhaps more than one, with it. My tired brain is failing to locate it (or them), so I would really appreciate some help with this. Does it even make sense?

Also, in case you might need it, here's the Tile class:

function Tile(x,y,character, thisMap, blocked, blockSight) {
    this.x = x;
    this.y = y;
    this.character = character;
    this.blocked = blocked;
    this.blockSight = blockSight;
    this.lightValue = 25;

    this.neighbors = new Array();
}

Tile.prototype = {
    create: function(blocked, blockSight, character) {
        this.blocked = blocked;
        this.blockSight = blockSight;
        this.character = character;

        var rockTile = RandomRange(1,4);
        var rockTileStr = "rock"+rockTile;
    },

    draw: function() {
        var id = '#t' + this.x + '_' + this.y;

        var lightColor = this.lightValue/100;

        $(id).css("opacity", lightColor); 
    },

    assign: function() {
        var north = this.x-1;
        var south = this.x+1;
        var east = this.y+1;
        var west = this.y-1;

        if(north >= 0 && south <= mapSizeX && west >= 0 && east <= mapSizeY) {

            //1st: we add the northwest neighbor.
            // *|/
            // -#-
            // /|\
            this.neighbors[0] = map[north][west];

            //2nd: we add the north neighbor.
            // \*/
            // -#-
            // /|\
            this.neighbors[1] = map[north][this.y];

            //3rd: we add the northeast neighbor.
            // \|*
            // -#-
            // /|\
            this.neighbors[2] = map[north][east];

            //4th: we add the east neighbor.
            // \|/
            // -#*
            // /|\
            this.neighbors[3] = map[this.x][east];

            //5th: we add the southeast neighbor.
            // \|/
            // -#-
            // /|*
            this.neighbors[4] = map[south][east];

            //6th: we add the south neighbor.
            // \|/
            // -#-
            // /*\
            this.neighbors[5] = map[south][this.y];

            //7th: we add the southwest neighbor.
            // \|/
            // -#-
            // *|\
            this.neighbors[6] = map[south][west];

            //8th: we add the west neighbor.
            // \|/
            // *#-
            // /|\
            this.neighbors[7] = map[this.x][west];
        }
    },
}

Thanks, and apologies for posting such a long question; I just don't know where else to turn at the moment.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

尹雨沫 2024-11-08 16:07:25

我可以看到以下错字:

highestLightValue = 邻居[j];

应该是

highestLightValue = Neighbors[j].light;

此外,如果您担心效率,您可能需要重新设计存储封闭元素集的方式。对于闭合图块数组,您需要 O(n) 时间来执行 FindValue(事实上,对于 JavaScript 数组的当前实现,O(n*log(n)))。如果您使用由tile id索引的真/假数组,您将获得O(1)(或在真实的JavaScript世界中O(log(n)))。由于这是在计算的内循环中,因此加速可能会很明显。

I can see the following typo:

highestLightValue = neighbors[j];

should be

highestLightValue = neighbors[j].light;

Furthermore, if you are concerned about efficiency, you might want to redesign how you store the set of closed elements. With the array of closed tiles you need O(n) time to execute FindValue (in fact, with current implementations of javascript arrays, O(n*log(n))). If you use an array of true/false indexed by a tile id, you get O(1) (or O(log(n)) in the real javascript world). Since this is in the inner loop of the calculation, the speedup may be noticeable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文