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

Raylib多文件开发中纹理加载成功却无法绘制的问题求助

Raylib多文件拆分后纹理加载成功但绘制失败问题

问题描述

使用Raylib实现纹理加载与绘制功能,单文件编写时运行正常,拆分为多文件结构后出现异常:编译运行后屏幕仅显示白色背景,控制台输出警告"Attempted to draw player texture before it was loaded!",但日志明确提示纹理加载成功。

代码结构

Player.h

#ifndef PLAYER_H
#define PLAYER_H

#include "raylib.h"

class Player
{
public:
    Player(const char* texturePath);
    ~Player();
    void Draw();

private:
    Texture2D ShipTexture;
    Vector2 position;
    const char* texturePath;
};
#endif

Player.cpp

#include "Player.h"

Player::Player(const char* texturePath)
{
    position = { 0, 0 };
    ShipTexture = LoadTexture(texturePath);
    if (ShipTexture.id == 0)
    {
        TraceLog(LOG_ERROR, "Failed to load texture from path: %s", texturePath);
    }
    else
    {
        TraceLog(LOG_INFO, "Texture loaded successfully from path: %s", texturePath);
    }
}

Player::~Player()
{
    UnloadTexture(ShipTexture);
}

void Player::Draw()
{
    if (ShipTexture.id != 0)
    {
        DrawTexture(ShipTexture, position.x, position.y, WHITE);
    }
    else
    {
        TraceLog(LOG_WARNING, "Attempted to draw player texture before it was loaded!");
    }
}

Game.h

#ifndef GAME_H
#define GAME_H

#include "raylib.h"
#include "Player.h"

class Game
{
public:
    Game(const int screenWidth, const int screenHeight, const char* title);
    ~Game();
    void Init();
    void Draw();
    void Loop();
    void Shutdown();

private:
    int screenWidth;
    int screenHeight;
    const char* title;
    Player player;
};
#endif

Game.cpp

#include "Game.h"

Game::Game(const int screenWidth, const int screenHeight, const char* title)
        : screenWidth(screenWidth), screenHeight(screenHeight), title(title),
        player("texture/path/png")
{
}

void Game::Init()
{
    InitWindow(screenWidth, screenHeight, title);
    SetTargetFPS(60);
}

void Game::Draw()
{
    BeginDrawing();
        ClearBackground(RAYWHITE);
        player.Draw();
    EndDrawing();
}

void Game::Loop()
{
    while(!WindowShouldClose())
    {
        Draw();
    }
}

void Game::Shutdown()
{
    CloseWindow();
}

main.cpp

#include "Game.h"

int main()
{
    Game game(800, 600, "Space Invaders");

    game.Init();
    game.Loop();
    game.Shutdown();

    return 0;
}

问题原因

Raylib的纹理加载依赖OpenGL上下文,而这个上下文是在调用InitWindow时才创建的。当前代码中,Game对象在main函数中先被构造,其成员player也会随之构造,此时LoadTexture被调用,但窗口尚未初始化,OpenGL上下文不存在。

虽然此时LoadTexture可能返回一个非0的id(日志显示加载成功),但实际上并没有在GPU端创建有效的纹理资源。当后续调用InitWindow创建上下文后,之前的纹理id已经失效,导致绘制时检测到纹理无效,触发警告。

单文件运行正常可能是因为代码顺序或编译器优化巧合让纹理加载在窗口初始化之后,但多文件结构下构造顺序明确,问题暴露出来。

解决方案

调整初始化顺序,将纹理加载延迟到窗口初始化完成之后:

  1. 修改Player类,添加Init方法,将纹理加载逻辑从构造函数移到该方法中:
// Player.h
class Player
{
public:
    Player(const char* texturePath);
    ~Player();
    void Init(); // 新增初始化方法
    void Draw();

private:
    Texture2D ShipTexture;
    Vector2 position;
    const char* texturePath;
};

// Player.cpp
Player::Player(const char* texturePath) : texturePath(texturePath)
{
    position = { 0, 0 };
    ShipTexture = {0}; // 初始化空纹理
}

void Player::Init()
{
    ShipTexture = LoadTexture(texturePath);
    if (ShipTexture.id == 0)
    {
        TraceLog(LOG_ERROR, "Failed to load texture from path: %s", texturePath);
    }
    else
    {
        TraceLog(LOG_INFO, "Texture loaded successfully from path: %s", texturePath);
    }
}
  1. 在Game::Init中,调用InitWindow后再执行player.Init():
void Game::Init()
{
    InitWindow(screenWidth, screenHeight, title);
    SetTargetFPS(60);
    player.Init(); // 窗口初始化后再加载纹理
}

这样就能确保纹理加载时OpenGL上下文已经存在,创建的纹理资源有效,绘制时即可正常显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 20:08:14