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

Raylib游戏地图绘制异常求助:仅显示背景色无地图内容

问题分析与修复方案

你的代码存在多个关键问题,导致地图无法正常渲染,以下是具体问题和修复方案:

1. 文件读取逻辑错误:仅读取一次地图

你把文件读取的do-while循环放在了Raylib的主渲染循环内。第一次执行时,fgetc会一直读到文件末尾(EOF),之后每次主循环执行时,文件指针停留在EOF位置,不会再读取任何内容,自然无法绘制地图。

修复方式:
提前将地图数据加载到内存(比如二维数组),避免在渲染循环中重复读取文件,既提升效率也能保证每次渲染都能获取到地图数据。

2. 换行符处理逻辑冲突

代码中case '\n'分支仅做了break操作,后续又单独判断if(caracter == '\n')来更新坐标,导致遇到换行符时,先执行x += TAMANHO,再重置x和y,造成换行后第一个格子的x坐标偏移错误。

修复方式:
去掉case '\n'分支,直接在switch结构外处理换行逻辑;或者在case分支内完成坐标更新,避免重复执行x偏移。

3. DrawRectangle参数顺序错误

默认分支中的DrawRectangle(LARGURA, ALTURA, x, y, DARKGRAY)参数顺序完全错误,Raylib的DrawRectangle接口定义为DrawRectangle(int posX, int posY, int width, int height, Color color),你把宽高和坐标位置搞反了,导致绘制的矩形不在预期区域。

修复方式:
改为DrawRectangle(x, y, TAMANHO, TAMANHO, DARKGRAY),匹配格子的尺寸。

4. 角色移动后未重新绘制

你仅在读取地图时绘制了一次初始位置的角色,后续移动角色更新坐标后,没有在主循环中重新绘制角色,所以移动操作无法在画面上体现。

修复方式:
在主渲染循环的地图绘制完成后,添加角色绘制代码,使用更新后的坐标重新绘制。

5. 文件打开失败后的错误处理缺失

文件打开失败时,仅打印错误信息但程序继续执行后续代码,会导致fclose(file)操作空指针,引发程序崩溃。

修复方式:
文件打开失败后直接终止程序,避免后续错误操作。


修复后的完整代码

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

#define LARGURA 1200
#define ALTURA 500
#define LINE 100
#define PAREDE 'W'
#define PAREDEDESTRUTIVEL 'D'
#define POCAO 'P'
#define POSINICIALMAGO 'J'
#define POSISINICIALMONSTRO 'M'
#define POSINICIALCRIATURA 'K'
#define TAMANHO 40
#define MAP_ROWS (ALTURA / TAMANHO)
#define MAP_COLS (LARGURA / TAMANHO)

// 存储地图数据的二维数组
char map[MAP_ROWS][MAP_COLS];

int main(void){
    FILE *file;
    char path[] = "Mapa/mapa1.txt";
    int x,y, posInicialMago[2], posMago[2], posInicialCriatura[2], posCriatura[2], posInicialMonstro[2], posMonstro[2];
    char caracter;

    file = fopen(path,"r");

    if(file == NULL)
    {
        printf("Erro na abertura do arquivo! \n");
        return 1; // 文件打开失败,直接终止程序
    }

    // 提前加载地图数据到内存
    x = y = 0;
    while((caracter = fgetc(file)) != EOF)
    {
        if(caracter == '\n')
        {
            y++;
            x = 0;
            continue;
        }
        if(y < MAP_ROWS && x < MAP_COLS)
        {
            map[y][x] = caracter;
            // 记录各类角色初始位置
            switch(caracter)
            {
                case POSINICIALMAGO:
                    posInicialMago[0] = posMago[0] = x * TAMANHO;
                    posInicialMago[1] = posMago[1] = y * TAMANHO;
                    break;
                case POSINICIALCRIATURA:
                    posInicialCriatura[0] = x * TAMANHO;
                    posInicialCriatura[1] = y * TAMANHO;
                    break;
                case POSISINICIALMONSTRO:
                    posInicialMonstro[0] = x * TAMANHO;
                    posInicialMonstro[1] = y * TAMANHO;
                    break;
                default:
                    break;
            }
            x++;
        }
    }
    fclose(file); // 提前关闭文件,无需保持打开状态

    InitWindow(LARGURA, ALTURA, "Jogo");
    SetTargetFPS(60);

    // 加载纹理资源
    Texture2D mage = LoadTexture("./Texturas/mage (1).png");
    Texture2D fairy = LoadTexture("./Texturas/fairy (1).png");
    Texture2D potion = LoadTexture("./Texturas/potion (1).png");
    Texture2D monster = LoadTexture("./Texturas/monster (1).png");
    Texture2D wall = LoadTexture("./Texturas/wall (1).png");
    Texture2D indestructibleWall = LoadTexture("./Texturas/wall (1).png");

    while (!WindowShouldClose())
    {
        // 处理角色移动输入
        if (IsKeyPressed(KEY_RIGHT)) posMago[0] += TAMANHO;
        if (IsKeyPressed(KEY_LEFT)) posMago[0] -= TAMANHO;
        if (IsKeyPressed(KEY_UP)) posMago[1] -= TAMANHO;
        if (IsKeyPressed(KEY_DOWN)) posMago[1] += TAMANHO;

        BeginDrawing();
            ClearBackground(RAYWHITE);

            // 绘制地图
            for(y = 0; y < MAP_ROWS; y++)
            {
                for(x = 0; x < MAP_COLS; x++)
                {
                    caracter = map[y][x];
                    int drawX = x * TAMANHO;
                    int drawY = y * TAMANHO;
                    switch(caracter)
                    {
                        case PAREDE:
                            DrawTexture(indestructibleWall, drawX, drawY, BROWN);
                            break;
                        case PAREDEDESTRUTIVEL:
                            DrawTexture(wall, drawX, drawY, BROWN);
                            break;
                        case POCAO:
                            DrawTexture(potion, drawX, drawY, BLUE);
                            break;
                        case POSINICIALCRIATURA:
                            DrawTexture(fairy, drawX, drawY, PURPLE);
                            break;
                        case POSISINICIALMONSTRO:
                            DrawTexture(monster, drawX, drawY, BLACK);
                            break;
                        default:
                            DrawRectangle(drawX, drawY, TAMANHO, TAMANHO, DARKGRAY);
                            break;
                    }
                }
            }

            // 绘制移动后的法师角色
            DrawTexture(mage, posMago[0], posMago[1], RAYWHITE);

        EndDrawing();
    }

    // 卸载纹理资源,避免内存泄漏
    UnloadTexture(mage);
    UnloadTexture(fairy);
    UnloadTexture(potion);
    UnloadTexture(monster);
    UnloadTexture(wall);
    UnloadTexture(indestructibleWall);

    CloseWindow();
    return 0;
}

额外优化建议

  • 添加纹理加载失败判断:比如通过if(mage.id == 0)检测纹理是否加载成功,避免绘制空纹理。
  • 限制角色移动范围,防止角色移出窗口边界。
  • 将常量、结构体等封装到独立头文件中,提升代码可读性和维护性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 18:24:04