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

如何用C语言结合raylib加载并渲染Tiled导出的JSON格式2D瓦片地图

用C+raylib加载并渲染Tiled JSON瓦片地图

前置准备

  • 安装raylib库
  • 引入cJSON库(轻量C语言JSON解析库,直接把cJSON.c和cJSON.h加到项目目录即可)
  • Tiled导出的JSON地图(导出时选择"JSON"格式,瓦片集使用单张图片)

步骤1:加载JSON文件

先把JSON文件读取到内存,再传给cJSON解析:

#include <stdio.h>
#include <stdlib.h>
#include "raylib.h"
#include "cJSON.h"

// 读取文件到内存的辅助函数
char* LoadFileToString(const char* filePath) {
    FILE* file = fopen(filePath, "rb");
    if (!file) return NULL;

    // 获取文件大小
    fseek(file, 0, SEEK_END);
    long fileSize = ftell(file);
    fseek(file, 0, SEEK_SET);

    // 分配内存(额外加1字节存字符串终止符)
    char* buffer = (char*)malloc(fileSize + 1);
    if (!buffer) {
        fclose(file);
        return NULL;
    }

    // 读取文件内容
    fread(buffer, 1, fileSize, file);
    buffer[fileSize] = '\0';
    fclose(file);

    return buffer;
}

调用函数加载并解析地图文件:

// 加载JSON文件到内存
char* mapJsonStr = LoadFileToString("assets/map.json");
if (!mapJsonStr) {
    TraceLog(LOG_ERROR, "Failed to load map JSON file");
    return 1;
}

// 解析JSON字符串
cJSON* mapJson = cJSON_Parse(mapJsonStr);
if (!mapJson) {
    TraceLog(LOG_ERROR, "Failed to parse JSON: %s", cJSON_GetErrorPtr());
    free(mapJsonStr);
    return 1;
}

步骤2:解析提取瓦片地图关键信息

从JSON结构中提取地图尺寸、瓦片尺寸、瓦片集路径、图层数据等核心内容:

// 提取地图基础参数
int mapWidth = cJSON_GetObjectItem(mapJson, "width")->valueint;
int mapHeight = cJSON_GetObjectItem(mapJson, "height")->valueint;
int tileWidth = cJSON_GetObjectItem(mapJson, "tilewidth")->valueint;
int tileHeight = cJSON_GetObjectItem(mapJson, "tileheight")->valueint;

// 提取瓦片集信息(假设地图只有一个瓦片集)
cJSON* tilesets = cJSON_GetObjectItem(mapJson, "tilesets");
cJSON* firstTileset = cJSON_GetArrayItem(tilesets, 0);
const char* tilesetPath = cJSON_GetObjectItem(firstTileset, "image")->valuestring;
int firstGid = cJSON_GetObjectItem(firstTileset, "firstgid")->valueint;

// 提取图层数据(假设地图只有一个可见图层)
cJSON* layers = cJSON_GetObjectItem(mapJson, "layers");
cJSON* firstLayer = cJSON_GetArrayItem(layers, 0);
cJSON* layerData = cJSON_GetObjectItem(firstLayer, "data");

注意:Tiled的firstgid是瓦片集第一个瓦片的ID,图层中的瓦片ID需要减去这个值,才能对应到瓦片集里的实际索引。


步骤3:用raylib渲染瓦片地图

加载瓦片集纹理,遍历图层数据逐个绘制瓦片:

int main() {
    // 初始化raylib窗口
    InitWindow(mapWidth * tileWidth, mapHeight * tileHeight, "Tiled Map Demo");
    SetTargetFPS(60);

    // 加载瓦片集纹理
    Texture2D tileset = LoadTexture(tilesetPath);
    if (!tileset.id) {
        TraceLog(LOG_ERROR, "Failed to load tileset image");
        // 提前清理资源
        cJSON_Delete(mapJson);
        free(mapJsonStr);
        return 1;
    }

    // 计算瓦片集每行的瓦片数量
    int tilesetCols = tileset.width / tileWidth;

    while (!WindowShouldClose()) {
        BeginDrawing();
        ClearBackground(RAYWHITE);

        // 遍历地图的每个瓦片位置
        for (int y = 0; y < mapHeight; y++) {
            for (int x = 0; x < mapWidth; x++) {
                // 获取当前位置的瓦片ID(数组索引为 y*mapWidth + x)
                int tileId = cJSON_GetArrayItem(layerData, y*mapWidth + x)->valueint;
                
                // 跳过空瓦片(Tiled中空瓦片ID为0)
                if (tileId == 0) continue;

                // 计算瓦片在瓦片集中的索引
                int tileIndex = tileId - firstGid;
                // 计算瓦片在瓦片集中的坐标
                int tilesetX = (tileIndex % tilesetCols) * tileWidth;
                int tilesetY = (tileIndex / tilesetCols) * tileHeight;

                // 绘制瓦片到屏幕对应位置
                DrawTextureRec(tileset, 
                    (Rectangle){(float)tilesetX, (float)tilesetY, (float)tileWidth, (float)tileHeight},
                    (Vector2){(float)(x*tileWidth), (float)(y*tileHeight)}, 
                    WHITE);
            }
        }

        EndDrawing();
    }

    // 清理所有资源
    UnloadTexture(tileset);
    cJSON_Delete(mapJson);
    free(mapJsonStr);
    CloseWindow();

    return 0;
}

关键注意事项

  • 资源清理:必须释放JSON解析内存、文件缓冲区和raylib纹理,避免内存泄漏。
  • 多图层/多瓦片集扩展:如果地图有多个图层或瓦片集,只需循环遍历layers和tilesets数组,逻辑与单图层/单瓦片集一致。
  • 空瓦片处理:Tiled中空瓦片ID为0,绘制时必须跳过,否则会错误渲染瓦片集的第一个瓦片。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 15:02:47