【问题标题】:(SDL2) Letting an object render itself gives black screen(SDL2) 让对象自己渲染会导致黑屏
【发布时间】:2017-08-28 21:41:25
【问题描述】:

我正在使用 SDL2 制作一个应用程序,旨在在单独的窗口中显示图形。为此,我有一个名为 figure 的类,其标题如下:

class figure
{
private:
    short window_width;
    short window_height;
    SDL_Window* window = NULL;
    SDL_Renderer* renderer = NULL;
    SDL_Event fig_handler;
public:
    figure(short fig_typ);
    void render();
    short figure_type;
};

以及以下实现:

figure::figure(short fig_typ)
{
    window_width = 840;
    window_height = 680;
    window = SDL_CreateWindow( "Demo Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, window_width, window_height, SDL_WINDOW_SHOWN );
    if (window==NULL)
    {
        std::cout << "Window could not be created! SDL_Error: " << SDL_GetError() << std::endl;
    }

    renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC );
    if (renderer==NULL)
    {
        std::cout << "Window could not be created! SDL_Error: " << SDL_GetError() << std::endl;
    }

    // Set default colour to turquise
    SDL_SetRenderDrawColor(renderer, 45, 164, 132, SDL_ALPHA_OPAQUE);

    figure_type = fig_typ;
}

void figure::render()
{
    while (SDL_PollEvent(&fig_handler))
    {
        if (fig_handler.type == SDL_QUIT)
        {
            // Do things here
        }
    }
    SDL_RenderClear(renderer);
    SDL_RenderPresent(renderer);
    SDL_Delay(0);
}

这一切都很好。我可以只写 while (true){fig1.render();} 并且绿松石窗口会一直保持到我关闭程序为止。但是在我的程序中,我希望这些图形中的许多可以共存,并且为了简化过程,我决定创建一个新的类模型来跟踪这些图形。

标题:

class model
{
public:
    model();
    void add_figure(short index, short fig_typ);
    bool update();
private:
    std::map<short, figure*> figure_map;
};

实现:

model::model()
{
    // Initialize SDL
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        std::cout << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
    }
}

void model::add_figure(short index, short fig_typ)
{
    figure tempFigure(fig_typ);
    std::pair<short, figure*> tempPair(index, &tempFigure);
    figure_map.insert(tempPair);
}

bool model::update()
{
    for (std::map<short, figure*>::iterator it = figure_map.begin(); it != figure_map.end(); ++it)
    {
        it->second->render();
    }
    return true;
}

神秘的是,当我创建一个模型对象并给它一个图形,然后调用 while (true) {model_object.update();} 时,窗口变黑了。当我从图形对象中删除事件处理时(就像我最初打算的那样),SDL 甚至懒得做一个漂亮的窗口:我只得到一个模糊的白色或黑色窗口,这取决于我删除了处理的哪些部分。

似乎 SDL 甚至没有花时间很好地渲染所有内容。另一个 StackOverflow-post 建议在某处添加 SDL_Delay(0) 以使 SDL 屏住呼吸(如您所见,我将其放入 figure::render()),但到目前为止它没有任何区别。

我可以做些什么来渲染我的窗口,但仍然保持这个结构:一个对象调用另一个对象的函数来绘制窗口的结构。

附:我在一台装有 MacOS 的笔记本电脑上工作,并使用 g++ 进行编译。

【问题讨论】:

    标签: c++ macos sdl


    【解决方案1】:

    在 figure::render 中你正在这样做:

    SDL_RenderClear(renderer);
    SDL_RenderPresent(renderer);
    

    您在将渲染器呈现到屏幕之前将其清除,因此它是黑色的。只需在此处更改顺序即可。

    【讨论】:

    • 恐怕这行不通。当我更改订单时,程序会显示完全相同的行为。在 SDL2 中首先清除意味着用最后选择的颜色(在我的示例中为绿松石)填充整个渲染器。这是所有演示程序的工作顺序(以及在我介绍模型类之前工作正常的顺序)。
    【解决方案2】:

    您正在获取指向临时变量的指针并将其保存到地图中。一旦执行流程离开这个函数,这个地址就不再保存有效数据并且不能被可靠地访问。要么使用例如new 或(更好)使您的对象可复制。

    【讨论】:

    • 使用 new 关键字就像魅力一样工作。使对象可复制到底是什么意思?您的意思是将整个对象复制到 std::map 中吗?
    • 是的,通过让地图本身持有对象(而不是指针),因为在这种情况下对象不会太重,并且复制它比new便宜得多。不过,你必须小心构造函数/析构函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-28
    • 2017-02-12
    • 1970-01-01
    相关资源
    最近更新 更多