You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何更新基于Vertex Array的Tile Map?求教单/全tile更新方法

SFML Vertex Array Tile Map 局部/全局更新方案

Vertex Array的核心优势是一次性将所有顶点数据提交给GPU,实现高效渲染。要更新Tile的属性(比如颜色、纹理坐标),本质就是定位到对应顶点并修改其数据,后续渲染时SFML会自动提交更新后的内容。

单个Tile更新逻辑

每个Tile对应Vertex Array中的4个顶点(组成四边形),首先通过Tile的坐标计算出顶点起始索引:
起始索引 = (TileX + TileY * 地图宽度) * 4
之后遍历该索引开始的4个顶点,修改目标属性即可。

全部Tile更新逻辑

两种常见方式:

  1. 遍历Vertex Array的所有顶点,批量修改属性(适合全局统一更新,比如全局变色);
  2. 清空现有Vertex Array,重新填充所有顶点数据(适合大规模重置,比如切换地图场景)。

极简示例代码

#include <SFML/Graphics.hpp>

class TileMap {
private:
    sf::VertexArray m_vertices;
    sf::Vector2u m_mapSize;    // 地图Tile数量(宽×高)
    sf::Vector2u m_tilePixelSize; // 单个Tile的像素尺寸

public:
    TileMap(sf::Vector2u mapSize, sf::Vector2u tileSize) 
        : m_mapSize(mapSize), m_tilePixelSize(tileSize) {
        m_vertices.setPrimitiveType(sf::Quads);
        m_vertices.resize(mapSize.x * mapSize.y * 4);

        // 初始化所有Tile的位置与默认颜色
        for (unsigned int y = 0; y < mapSize.y; ++y) {
            for (unsigned int x = 0; x < mapSize.x; ++x) {
                unsigned int vertexStartIdx = (x + y * mapSize.x) * 4;
                // 设置四个顶点的位置
                m_vertices[vertexStartIdx + 0].position = sf::Vector2f(x * tileSize.x, y * tileSize.y);
                m_vertices[vertexStartIdx + 1].position = sf::Vector2f((x+1)*tileSize.x, y * tileSize.y);
                m_vertices[vertexStartIdx + 2].position = sf::Vector2f((x+1)*tileSize.x, (y+1)*tileSize.y);
                m_vertices[vertexStartIdx + 3].position = sf::Vector2f(x * tileSize.x, (y+1)*tileSize.y);
                // 默认灰色
                for (int i = 0; i < 4; ++i) {
                    m_vertices[vertexStartIdx + i].color = sf::Color(150, 150, 150);
                }
            }
        }
    }

    // 更新单个Tile的颜色
    void updateSingleTileColor(unsigned int tileX, unsigned int tileY, sf::Color newColor) {
        if (tileX >= m_mapSize.x || tileY >= m_mapSize.y) return; // 边界校验
        unsigned int startIdx = (tileX + tileY * m_mapSize.x) * 4;
        for (int i = 0; i < 4; ++i) {
            m_vertices[startIdx + i].color = newColor;
        }
    }

    // 更新所有Tile的颜色
    void updateAllTilesColor(sf::Color newColor) {
        for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i) {
            m_vertices[i].color = newColor;
        }
    }

    void draw(sf::RenderWindow& window) {
        window.draw(m_vertices);
    }
};

int main() {
    sf::RenderWindow window(sf::VideoMode(800, 600), "Tile Map Update Demo");
    TileMap map(sf::Vector2u(20, 15), sf::Vector2u(40, 40));

    // 模拟碰撞后修改单个Tile颜色
    map.updateSingleTileColor(7, 5, sf::Color::Red);
    // 若需要全局更新,取消下方注释
    // map.updateAllTilesColor(sf::Color(100, 120, 140));

    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear();
        map.draw(window);
        window.display();
    }

    return 0;
}

关键提示

  • 修改Vertex Array后无需额外"刷新"操作,直接调用draw即可,SFML会自动提交更新后的顶点数据;
  • 必须做边界校验,避免访问超出Vertex Array范围的索引导致程序崩溃;
  • 若需要修改Tile的纹理坐标,逻辑与修改颜色完全一致,只需操作vertex.texCoords属性。

内容的提问来源于stack exchange,提问作者xy1qw1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 08:50:09