【问题标题】:Best way to make tiles not have borders in between them?使瓷砖之间没有边框的最佳方法?
【发布时间】:2017-08-23 21:25:11
【问题描述】:

所以我正在尝试使用 SFML 和 Visual c++ 制作游戏。目前,对于每个可能彼此接壤的瓷砖组合,我在某些边上都有不同的没有边框的精灵,然后使用嵌套的 if 语句来检查要使用的精灵。但是,这会使我的游戏速度减慢到我什至无法玩的程度。有没有更好的方法来做到这一点?

这是我的代码:

//Render tiles
            for (int i = 0; i < blockX.size(); i++) {
                    block.setPosition(float(blockX[i]), float(blockY[i]));
                    if (blockType[i] == "metal") {
                            //if block is metal tile
                            block.setTexture(metalBlockSingle);
                            if (doesBlockExist(blockX[i] + 20, blockY[i])) {
                                    //if block is to right
                                    if (doesBlockExist(blockX[i], blockY[i] + 20)) {
                                            //if block is below
                                            if (doesBlockExist(blockX[i] - 20, blockY[i])) {
                                                    //if block is to left
                                                    if (doesBlockExist(blockX[i], blockY[i] - 20)) {
                                                            //if block is above
                                                            block.setTexture(metalBlockCenter);
                                                    }
                                                    else {
                                                            block.setTexture(metalBlockBottomRightLeft);
                                                    }
                                            }
                                            else if (doesBlockExist(blockX[i], blockY[i] - 20)) {
                                                    //if block is above
                                                    block.setTexture(metalBlockTopBottomRight);
                                            }
                                            else {
                                                    //if block is neither above nor to left
                                                    block.setTexture(metalBlockBottomRight);
                                            }
                                    }
                                    else if (doesBlockExist(blockX[i] - 20, blockY[i])) {
                                            //if block is to left
                                            if (doesBlockExist(blockX[i], blockY[i] - 20)) {
                                                    //if block is above
                                                    block.setTexture(metalBlockTopRightLeft);
                                            }
                                            else {
                                                    block.setTexture(metalBlockRightLeft);
                                            }
                                    }
                                    else if (doesBlockExist(blockX[i], blockY[i] - 20)) {
                                            //if block is above
                                            block.setTexture(metalBlockTopRight);
                                    }
                                    else {
                                            //if block is only right
                                            block.setTexture(metalBlockRight);
                                    }
                            }
                            else if (doesBlockExist(blockX[i], blockY[i] + 20)) {
                                    //if block is below
                                    if (doesBlockExist(blockX[i] - 20, blockY[i])) {
                                            //if block is to left
                                            if (doesBlockExist(blockX[i], blockY[i] - 20)) {
                                                    //if block is above
                                                    block.setTexture(metalBlockTopBottomLeft);
                                            }
                                            else {
                                                    //if block is not above
                                                    block.setTexture(metalBlockBottomLeft);
                                            }
                                    }
                                    else {
                                            //if block is not to left
                                            if (doesBlockExist(blockX[i], blockY[i] - 20)) {
                                                    //if block is above
                                                    block.setTexture(metalBlockTopBottom);
                                            }
                                            else {
                                                    //if metal block is not above
                                                    block.setTexture(metalBlockBottom);
                                            }
                                    }
                            }
                            else if (doesBlockExist(blockX[i] - 20, blockY[i])) {
                                    //if block is to left
                                    if (doesBlockExist(blockX[i], blockY[i] - 20)) {
                                            //if block is above
                                            block.setTexture(metalBlockTopLeft);
                                    }
                                    else {
                                            block.setTexture(metalBlockLeft);
                                    }
                            }
                            else if (doesBlockExist(blockX[i], blockY[i] - 20)) {
                                    //if block is above
                                    block.setTexture(metalBlockTop);
                            }
                    }
                    window.draw(block);
            }

编辑:这是“doesBlockExist”函数的代码:

bool doesBlockExist(int x, int y) {
    bool returnVal =  false;
    int findX = int(round(x / 20) * 20);
    int findY = int(round(y / 20) * 20);
    for (int i = 0; i < blockX.size(); i++) {
        if (blockX[i] == findX && blockY[i] == findY) {
            returnVal = true;
        }
    }
    return(returnVal);

    return(true);
}

【问题讨论】:

  • 使用配置文件找出大部分执行时间都花在了哪里。
  • 这是我大部分执行时间花费的部分。
  • doesBlockExist 贵吗?它被称为很多。
  • @cppguy 我对其进行了编辑以包含该功能。
  • 看来你需要重新设计这个逻辑。对于您正在尝试做的事情,它看起来非常昂贵。您正在对 blockX.size() 进行嵌套循环。几乎可以肯定,有一种方法可以只检查周围的 8 个图块来确定您的纹理。

标签: c++ sfml


【解决方案1】:

每当您像这样嵌套了 if 语句(高 cyclomatic complexity)时,您应该立即停下来考虑其他设计。大型嵌套 if 语句不仅容易出错,而且一眼就无法真正理解。

更好的设计可以从将事物拆分为多个功能开始,每个功能都有自己的single responsibility。其他步骤涉及足够努力地思考逻辑以找到消除条件的方法,即当情况 X 成立时,Y 随之而来,无需进一步检查。在某些情况下,您可以构造一个在构造后具有正确设置的对象,而不是使用 if 语句。

至于代码优化:

  • 使用精灵表并且不要使用 x 数量的纹理。 setTextureRect 基本上是一个免费功能,虽然一直在切换纹理,但会导致性能问题。
  • 如果你保留doesBlockExist的实现,至少确保找到块时正确返回,不要继续迭代。这意味着,在 if-body 中只写 return true,在循环之后写 return false 并删除变量 returnVal。
  • 但是,doesBlockExist 函数似乎实现得很糟糕。它究竟检查什么?你只是检查周围的瓷砖吗?如果是这样,那么您可以轻松地检查周围的 8 个图块,而无需遍历所有图块。
  • 由于您经常调用doesBlockExist,因此您必须考虑是否可以只调用一次并立即报告所有周围的图块。
  • int(round(x / 20) * 20); 因为 x 已经是 int x / 20 无论如何都会是整数除法,所以没有理由四舍五入。

或者,您也可以使用 Tiled 之类的图块编辑器,并在设计关卡时相应地放置图块,然后加载图块地图。

至于标题中的问题,我不知道你说的边框是什么意思。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多