如何合并网格输出的突出显示单元格的范围数据?

问题描述 投票:0回答:1

我正在开发一款游戏,我需要一个高效的碰撞检测系统。目前,我正在使用一个非常严格的 1 和 0 数组来表示边界。

我编写了一个粗略的网格创建工具,它允许我突出显示我想要指示有边界的单元格,但是,我在如何简化输出以更快地访问方面有点迷失。

目前,我的目的是根据是否有连续突出显示的单元格来重构边界,而在没有突出显示的单元格时则没有条目。因此稀疏矩阵。

例如,假设像元大小为 10 0,0 [_ _ ]- - -[ _ _]

我希望我的输出是

{ x: [0,30], y: [0,10] },
{ x: [60,90], y: [0,10] }

目前,我为每个单元格得到一个空对象..

这是我尝试将突出显示的单元格范围合并到单个对象以表示边界的当前迭代。

    function mergeConsecutiveCells(boundaries) {
        const mergedBoundaries = [];
       
        if (boundaries.length === 0) {
            return mergedBoundaries;
        }
       
        boundaries.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
       
        let currentBoundary = boundaries[0];
       
        for (let i = 1; i < boundaries.length; i++) {

            const nextBoundary = boundaries[i];
       
            if (
                currentBoundary[1] === nextBoundary[1] &&
                currentBoundary[2] === nextBoundary[2] &&
                currentBoundary[3] === nextBoundary[3] &&
                currentBoundary[0] + cellSize === nextBoundary[0]
            ) {

                // Consecutive cells, extend the range
                currentBoundary[0] = nextBoundary[0];
            } else {
               // Non-consecutive cells, add the current boundary to the result
               mergedBoundaries.push({
                   x: { start: currentBoundary[0], end: currentBoundary[0] + cellSize },
                   y: { start: currentBoundary[1], end: currentBoundary[3] }
               });
               currentBoundary = nextBoundary;
            }
        }
        // Add the last boundary
        mergedBoundaries.push({
            x: { start: currentBoundary[0], end: currentBoundary[0] + cellSize },
            y: { start: currentBoundary[1], end: currentBoundary[3] }
        });
        return mergedBoundaries;
    }
javascript object multidimensional-array sparse-matrix
1个回答
0
投票

因此,经过几个小时的试验和摸索,我找到了一个似乎是我所追求的相对直接的解决方案。

我想说我有点接近但不是真的..XD

如果您有兴趣,这里是 codepen 的链接。 ifaus - 二维稀疏矩阵 - 合并范围数据

function combineEntries(entries, cellSize) {
    let combined = true;
    while (combined) {
        combined = false;
        for (let i = 1; i < entries.length; i++) {
            const currentEntry = entries[i];
            const previousEntry = entries[i - 1];
            if (canCombine(previousEntry, currentEntry, cellSize)) {
                previousEntry.x = [
                    previousEntry.x[0],
                    currentEntry.x[1]
                ];
                previousEntry.y = [
                    previousEntry.y[0],
                    currentEntry.y[1]
                ];
                entries.splice(i, 1);
                combined = true;
            }
        }
    }
    return entries;
}

function canCombine(entry1, entry2, cellSize) {
    // Check if the entries overlap
    return (
        entry1.x[1] >= entry2.x[0] &&
        entry1.y[0] === entry2.y[0] &&
        entry1.y[1] === entry2.y[1] &&
        entry2.x[0] - entry1.x[1] <= cellSize
    );
}
* {
    margin:0;
    padding:0;
}

body {
    height: 100vh;
}

div {
    text-align: center;
    margin:0 auto;
}

canvas {
    border: 1px solid #000;
    max-width: 100%;
    max-height: 100%;
    margin-top: 40px;
}

textarea {
    display:inline-block;
    width:200px;
    height:200px
}

table {
    margin:0 auto;
    margin-top: 40px;
}

input[type=number] {
    width: 30px;
}
<div>
    <table>
    <tr><td>
        <input type="file" id="imageInput" accept="image/*">
        <label for="cellSize">Cell Size:</label>
        <input type="number" id="cellSize" value="20">
    </td></tr>
    <tr><td><canvas id="gridCanvas"></canvas></td></tr>
    <tr><td>
        <textarea id="outputRaw" disabled="true"></textarea>
        <textarea id="outputFinal"></textarea>
    </td></tr>
    </table>
    <input type="button" id="bttnOutputFinal" value="Condense">
</div>
© www.soinside.com 2019 - 2024. All rights reserved.