【问题标题】:C++ SDL2: How to render rects into multiple viewportsC++ SDL2:如何将矩形渲染到多个视口中
【发布时间】:2020-01-27 00:36:01
【问题描述】:

我是 SDL2(版本 2.0.10)的新手,我从 Lazy Foo 教程中教授它。在Lesson of The ViewPort 示例代码中,我只呈现左视口中的第一张图像,而其他则不呈现。在不同视口中渲染矩形也不起作用。当我想像这样在不同的视口中渲染矩形时,我做错了什么:

while( !quit ){

while( SDL_PollEvent( &e ) != 0 ){
if( e.type == SDL_QUIT ){
 quit = true;
}
}

//Clear screen
SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
SDL_RenderClear( gRenderer );

//Top left corner viewport
SDL_Rect topLeftViewport;
topLeftViewport.x = 0;
topLeftViewport.y = 0;
topLeftViewport.w = SCREEN_WIDTH / 2;
topLeftViewport.h = SCREEN_HEIGHT / 2;
SDL_RenderSetViewport( gRenderer, &topLeftViewport );

SDL_Rect fillRect = { 10, 10, 100, 100 };
SDL_SetRenderDrawColor( gRenderer, 0xFF, 0x00, 0x00, 0xFF );
SDL_RenderFillRect( gRenderer, &fillRect );

SDL_Rect topRightViewport;
topRightViewport.x = SCREEN_WIDTH / 2;
topRightViewport.y = 0;
topRightViewport.w = SCREEN_WIDTH / 2;
topRightViewport.h = SCREEN_HEIGHT / 2;
SDL_RenderSetViewport( gRenderer, &topRightViewport );

SDL_Rect fillRect2 = { 10, 10, 100, 100 };
SDL_SetRenderDrawColor( gRenderer, 0x00, 0xFF, 0x00, 0xFF );
SDL_RenderFillRect( gRenderer, &fillRect2 );

SDL_RenderPresent( gRenderer );
}

【问题讨论】:

  • 这段代码是你写的吗?还是原版有一些改动?能否将整个代码发给我,以便我找出问题所在?
  • 你知道绘制部分的代码只有在while循环结束时才会执行,而且只有在你点击窗口上的x后才会执行。我需要你把完整的代码发给我,否则我看不到这个部分之后程序会做什么。

标签: c++ viewport sdl-2 game-development


【解决方案1】:

正如我所见,您在 100x100 的 10、10 处绘制了两次矩形,此坐标不考虑视口坐标。在某种程度上,如果你想通过改变视口裁剪来做到这一点是不相关的......只需在你想要的地方画一个正方形。

更新:我尝试了多个视口。这是一个工作示例。您可以在渲染器(带视口)或经典方式之间进行选择。

main.cpp:

#include "Application.hpp"

int
main (int argc, char * argv[])
{
    Application app("SDL 2 Test", 800, 600, true);

    return app.mainLoop();
}

应用程序.hpp:

#ifndef APPLICATION_HPP
#define APPLICATION_HPP

#include <SDL2/SDL.h>

class Application
{
    public:

        Application (const char * title = "UnknownApplication", int baseWidth = 640, int baseHeight = 480, bool useRenderer = false) noexcept;

        ~Application ();

        int mainLoop () noexcept;

    private:

        int m_width = 0;
        int m_height = 0;
        SDL_Window * m_window = nullptr;
        SDL_Renderer * m_renderer = nullptr;
        bool m_useRenderer = false;
        bool m_isRunning = false;
};

#endif /* APPLICATION_HPP */

应用程序.cpp:

#include "Application.hpp"

#include <iostream>

#include <SDL2/SDL_image.h>

Application::Application (const char * title, int baseWidth, int baseHeight, bool useRenderer) noexcept
    : m_width(baseWidth), m_height(baseHeight), m_useRenderer(useRenderer)
{
    if ( SDL_Init(SDL_INIT_VIDEO) != 0 )
    {
        std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;

        return;
    }

    m_window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, m_width, m_height, SDL_WINDOW_SHOWN);

    if ( m_window == nullptr )
    {
        std::cerr << "Window could not be created! SDL_Error: " << SDL_GetError() << std::endl;

        return;
    }

    if ( m_useRenderer )
    {
        m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE);

        if ( m_renderer == nullptr )
        {
            std::cerr << "Renderer could not be created! SDL_Error: " << SDL_GetError() << std::endl;

            return;
        }
    }

    m_isRunning = true;
}

int
Application::mainLoop () noexcept
{
    SDL_Event event;

    const auto filepath = "SET_IMAGE_YOU_WANT_HERE";

    auto surface = IMG_Load(filepath);

    if ( surface == nullptr )
    {
        std::cerr << "Unable to read image file : " << filepath << std::endl;

        return 1;
    }

    SDL_Rect logoPosition = {8, 8, 32, 32};

    if ( m_useRenderer )
    {
        auto texture = SDL_CreateTextureFromSurface(m_renderer, surface);

        SDL_Rect screenA = {0, 0, m_width / 2, m_height / 2};
        SDL_Rect screenB = {m_width / 2, 0, m_width / 2, m_height / 2};

        while ( m_isRunning )
        {
            while ( SDL_PollEvent(&event) != 0 )
            {
                if ( event.type == SDL_QUIT )
                    m_isRunning = false;
            }

            SDL_SetRenderDrawColor(m_renderer, 0, 0, 0, 255);
            SDL_RenderClear(m_renderer);

            SDL_RenderSetViewport(m_renderer, &screenA);
            SDL_SetRenderDrawColor(m_renderer, 255, 0, 0, 255);
            SDL_RenderFillRect(m_renderer, nullptr);
            SDL_RenderCopy(m_renderer, texture, nullptr, &logoPosition);

            SDL_RenderSetViewport(m_renderer, &screenB);
            SDL_SetRenderDrawColor(m_renderer, 0, 255, 0, 255);
            SDL_RenderFillRect(m_renderer, nullptr);
            SDL_RenderCopy(m_renderer, texture, nullptr, &logoPosition);

            SDL_RenderPresent(m_renderer);
        }

        SDL_DestroyTexture(texture);
    }
    else
    {
        auto windowSurface = SDL_GetWindowSurface(m_window);

        while ( m_isRunning )
        {
            while ( SDL_PollEvent(&event) != 0 )
            {
                if ( event.type == SDL_QUIT )
                    m_isRunning = false;
            }

            SDL_FillRect(windowSurface, nullptr, SDL_MapRGB(windowSurface->format, 0xFF, 0x00, 0xFF));

            //SDL_BlitSurface(surface, nullptr, windowSurface, &logoPosition);
            SDL_BlitScaled(surface, nullptr, windowSurface, &logoPosition);

            SDL_UpdateWindowSurface(m_window);
        }
    }

    SDL_FreeSurface(surface);

    return 0;
}

Application::~Application (void)
{
    if ( m_renderer != nullptr )
        SDL_DestroyRenderer(m_renderer);

    if ( m_window != nullptr )
        SDL_DestroyWindow(m_window);

    SDL_Quit();
}

【讨论】:

  • 我知道仅仅绘制一个矩形我不需要视口。但是我想学习使用视口的工作,并且来自网络的示例代码不能正常工作(在图像上),我认为了解原因很重要。 (因为它应该可以正常工作)
  • 我亲自尝试过,效果很好,你应该看看如何创建渲染器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多