1. ホーム
  2. c++

[解決済み] SDL_BlitSurface() を SDL_CreateRGBSurface() と共に正しく使用するにはどうしたらよいですか?

2022-02-27 02:56:47

質問

(解答は下記の「編集2"」を参照)

SDLサーフェスをファイルから読み込むのではなく、ゼロから作成する必要があります。残念ながら SDL_BlitSurface() によって生成されたサーフェスを使用すると、すべての色が黒にレンダリングされるようです。 SDL_CreateRGBSurface() . これは私のコードです。

int main(int argc, char** argv)
{
    SDL_Surface* screen = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE);
    SDL_Surface* layer = SDL_CreateRGBSurface(SDL_HWSURFACE, 100, 100,
        screen->format->BitsPerPixel,
        screen->format->Rmask,
        screen->format->Gmask,
        screen->format->Bmask,
        screen->format->Amask
    );
    SDL_Rect rect;

    rect.x = 0;
    rect.y = 0;
    rect.w = 100;
    rect.h = 100;

    Uint32 blue = SDL_MapRGB(screen->format, 0, 0, 255);
    SDL_FillRect(layer, &rect, blue);
    SDL_BlitSurface(screen, NULL, layer, NULL);
    SDL_Flip(screen);
    SDL_Delay(3000);
    return 0;
}

100x100の青い長方形ではなく、黒い画面が表示されるのです。私がググって見つけたものは、これらの質問が8ビット表面(および設定パレット-私のbppはここで32です)に適用されるか、または未回答のままであるため、私を助けるように思われません。

そこで、生成されたサーフェスをSDLの画面に正しくブリットする方法を知りたいのですが、どうすればよいのでしょうか。

編集する パラメータの並び順のミスだったんですね。問題の行は次のようになります。

SDL_BlitSurface(layer, NULL, screen, NULL);

しかし、もっと複雑なC++のプログラムでは、同じ効果を得ることができず、困っています。ここにコードの関連部分を掲載します。

main.cpp。

int main(int argc, char** argv)
{
    SDLScreen screen(1024, 700, "Hello, SDL!");
SDL_Event event;
    SDLMenu menu;
    bool shouldQuit = false;

    menu.setBounds(200, 100, 200, 600);
    menu.setFontName("NK211.otf");
    menu.setFontSize(36);
    menu.setEffect(sdlteShadowText);
    menu.addItem("New game");
    menu.addItem("Load game");
    menu.addItem("Save game");
    menu.addItem("Exit");
    menu.render();

    while (!shouldQuit)
    {
        menu.draw(screen.getSurface());
        SDL_Flip(screen.getSurface());
        SDL_Delay(10);
        while (SDL_PollEvent(&event))
        {
            if (event.type == SDL_QUIT)
            {
                shouldQuit = true;
            }
            else if (event.type == SDL_KEYUP)
            {
                if (event.key.keysym.sym == SDLK_q)
                {
                    shouldQuit = true;
                }
            }
        }
    }
}

SDLMenu.cpp。

void
SDLMenu::setSelectionColorRGB(int r, int g, int b)
{
    SDL_VideoInfo* info = (SDL_VideoInfo*)SDL_GetVideoInfo();
    selectionColor = SDL_MapRGB(info->vfmt, r, g, b);
}

void
SDLMenu::render()
{
    SDLText* current = NULL;
    SDL_VideoInfo* info = (SDL_VideoInfo*)SDL_GetVideoInfo();

    if (!items->empty())
    {
        current = getItemAt(currentItem);
        selectionRect = getItemRect(current);
        setSelectionColorRGB(0,0,255);
        selectionCanvas = SDL_CreateRGBSurface(SDL_HWSURFACE,
            selectionRect->w, selectionRect->h,
            info->vfmt->BitsPerPixel,
            info->vfmt->Rmask,
            info->vfmt->Gmask,
            info->vfmt->Bmask,
            info->vfmt->Amask);
        SDL_FillRect(selectionCanvas, selectionRect, selectionColor);
        SDL_SaveBMP(selectionCanvas, "selection.bmp"); // debug
    }

    for (list<SDLText*>::iterator i = items->begin();
        i != items->end(); i++)
    {
        (*i)->render();
    }
}

void
SDLMenu::draw(SDL_Surface* canvas)
{
    int currentY = bounds.y;

    if (selectionCanvas != NULL)
    {
        SDL_BlitSurface(selectionCanvas, NULL, canvas, selectionRect);
    }

    for (list<SDLText*>::iterator i = items->begin();
        i != items->end(); i++)
    {
        (*i)->draw(bounds.x, currentY, canvas);
        currentY += fontSize + itemGap;
    }
}

SDLScreen.cpp。

SDLScreen::SDLScreen(int w, int h, string t, int d)
    : width(w), height(h), depth(d), title(t)
{
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_WM_SetCaption(title.c_str(), NULL);
    refresh();
}

void
SDLScreen::refresh()
{
    screen = SDL_SetVideoMode(width, height, 32, SDL_HWSURFACE);
}

アクティブなメニュー項目の選択矩形は青色であるべきですが、黒色で表示されます。そのため、ファイル selection.bmp も黒一色です。

2を編集します。 何が問題を発生させたのかがわかりました。その selectionRect は画面に対して相対的に設定されていましたが selectionCanvas には、特定のメニュー項目の幅と高さがありました。そのため、塗りつぶしは selectionCanvas . 別の SDL_Rect を充填することで、問題を解決しました。

SDL_Rect fillRect;
fillRect.x = 0;
fillRect.y = 0;
fillRect.w = selectionRect->w;
fillRect.h = selectionRect->h;
SDL_FillRect(selectionCanvas, &fillRect, selectionColor);

// and later...

SDL_BlitSurface(selectionCanvas, NULL, canvas, selectionRect);

解決方法は?

ソースとデスティネーションが逆になっています。画面に表示させるには

SDL_BlitSurface(layer, NULL, screen, NULL);

SDL_BlitSurface 用の doc。