SDL_Rect 大于指定值

SDL_Rect is larger than specified

我在 SDL_Rect 中遇到了一个奇怪的错误。每当我用这个矩形调用 SDL_RenderFillRect 时:

SDL_Rect rect = {100, 100, 100, 100};

我总是以矩形覆盖整个 800 x 600 window。

这是我的程序:

#include "SDL.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <thread>
#include <string>

class Window
{
public:
    Window( std::string title, int width, int height );
    void runEvents( SDL_Event event );
    void drawRect( int x, int y, int h, int w );
    bool closed = false;
    SDL_Renderer *_renderer;
    SDL_Window *_window;

private:
    int colour = 0;
};

Window::Window( std::string title, int width, int height )
{
    _window = SDL_CreateWindow( title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, 0 );
    _renderer = SDL_CreateRenderer( _window, -1, 0 );
}

// this function deals with rects (it's supposed to draw a rect when the mouse button is down):
void Window::runEvents( SDL_Event event )
{
    SDL_Rect rect = { 100, 100, 100, 100 };
    switch( event.type )
    {
    case SDL_QUIT:
        closed = true;
        break;
    case SDL_KEYDOWN:
        switch( event.key.keysym.sym )
        {
        case SDLK_ESCAPE:
            closed = true;
            break;
        case SDLK_KP_1:
            // set colour to blue
            SDL_SetRenderDrawColor( _renderer, 0, 51, 204, 255 );
            std::cout << "Colour set to blue!" << std::endl;
            colour = 1;
            break;
        case SDLK_KP_2:
            // set colour to red
            SDL_SetRenderDrawColor( _renderer, 255, 0, 0, 255 );
            std::cout << "Colour set to red!" << std::endl;
            colour = 2;
            break;
        case SDLK_KP_3:
            // set colour to green
            SDL_SetRenderDrawColor( _renderer, 51, 204, 51, 255 );
            std::cout << "Colour set to green!" << std::endl;
            colour = 3;
            break;
        case SDLK_KP_4:
            SDL_SetRenderDrawColor( _renderer, 153, 0, 153, 255 );
            std::cout << "Colour set to purple!" << std::endl;
            colour = 4;
            break;
        case SDLK_KP_0:
            SDL_SetRenderDrawColor( _renderer, 255, 255, 255, 255 );
            std::cout << "Colour set to white!" << std::endl;
            colour = 0;
            break;
        }
        break;
        //this draws the rectangle:
    case SDL_MOUSEBUTTONDOWN:
        SDL_SetRenderDrawColor( _renderer, 255, 0, 0, 255 );
        drawRect( rect.h, rect.y, rect.h, rect.w );
        break;
        //this removes it
    case SDL_MOUSEBUTTONUP:
        switch( colour )
        {
        case 1:
            SDL_SetRenderDrawColor( _renderer, 0, 51, 204, 255 );
            break;
        case 2:
            SDL_SetRenderDrawColor( _renderer, 255, 0, 0, 255 );
            break;
        case 3:
            SDL_SetRenderDrawColor( _renderer, 51, 204, 51, 255 );
            break;
        case 4:
            SDL_SetRenderDrawColor( _renderer, 153, 0, 153, 255 );
            break;
        case 0:
            SDL_SetRenderDrawColor( _renderer, 255, 255, 255, 255 );
            break;
        }
        drawRect( rect.h, rect.y, rect.h, rect.w );
        break;
    }
}

//this function is supposed to draw the rect
void Window::drawRect( int x, int y, int h, int w )
{
    SDL_Rect rect = { x, y, w, h };
    SDL_RenderFillRect( _renderer, &rect );
}

bool running = true;

void mouseCheck()
{
    while( running )
    {
        int x;
        int y;
        SDL_GetMouseState( &x, &y );
        printf( "Mouse is at x: %i and y: %i\n", x, y );
        SDL_Delay( 5000 );
    }
}

int main( int argc, char *argv[] )
{
    SDL_Init( SDL_INIT_EVERYTHING );

    Window window( "Hello World", 800, 600 );
    SDL_Event event;

    SDL_SetRenderDrawColor( window._renderer, 255, 255, 255, 255 );

    std::thread mousePosition( mouseCheck );
    mousePosition.detach();

    while( !window.closed )
    {
        SDL_RenderClear( window._renderer );
        SDL_RenderPresent( window._renderer );
        if( SDL_PollEvent( &event ) )
        {
            window.runEvents( event );

        }
    }
    return 0;
}

多个问题:

  • 现在你的主要绘制循环是:

    1. Draw
    2. Clear
    3. Present
    

    你想要:

    1. (re)Set clear color
    2. Clear
    3. Draw
    4. Present
    
  • 不确定您要用那个 mouseCheck() 线程做什么,但要避免从其他线程调用与 GUI 相关的 SDL 函数。如果您需要在另一个线程中使用该信息,请使用线程安全 atomics/queues/messages 进行通信。

  • 您在两个地方调用 drawRect(),第一个参数是 rect.h 而不是 rect.x

  • 我建议不要像您在 runEvents() 中那样交错输入处理和渲染。在清空事件队列 (while(SDL_PollEvent())) 的同时更新系统状态 (shouldDrawRect & colour),然后使用新状态 (Window::drawScene()) 绘制帧。

  • 您每帧只处理一个事件。通过 while(SDL_PollEvent()) 清空每一帧的事件队列,这样事件就不会被备份和丢弃。

总计:

#include "SDL.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <thread>
#include <string>

class Window
{
public:
    Window( std::string title, int width, int height );
    void runEvents( SDL_Event event );
    void drawScene();
    void drawRect( int x, int y, int h, int w );
    bool closed = false;
    SDL_Renderer *_renderer;
    SDL_Window *_window;

private:
    bool shouldDrawRect;
    int colour = 0;
};

Window::Window( std::string title, int width, int height )
{
    _window = SDL_CreateWindow( title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, 0 );
    _renderer = SDL_CreateRenderer( _window, -1, 0 );
    shouldDrawRect = false;
}

void Window::drawScene()
{
    if( shouldDrawRect )
    {
        switch( colour )
        {
        case 0:
            SDL_SetRenderDrawColor( _renderer, 255, 0, 0, 255 );
            break;
        case 1:
            SDL_SetRenderDrawColor( _renderer, 0, 51, 204, 255 );
            break;
        case 2:
            SDL_SetRenderDrawColor( _renderer, 255, 0, 0, 255 );
            break;
        case 3:
            SDL_SetRenderDrawColor( _renderer, 51, 204, 51, 255 );
            break;
        case 4:
            SDL_SetRenderDrawColor( _renderer, 153, 0, 153, 255 );
            break;
        }

        SDL_Rect rect = { 100, 100, 100, 100 };
        drawRect( rect.x, rect.y, rect.h, rect.w );
    }
}

//this function deals with rects (it's supposed to draw a rect when the mouse button is down):
void Window::runEvents( SDL_Event event )
{
    switch( event.type )
    {
    case SDL_QUIT:
        closed = true;
        break;
    case SDL_KEYDOWN:
        switch( event.key.keysym.sym )
        {
        case SDLK_ESCAPE:
            closed = true;
            break;
        case SDLK_KP_1:
            // set colour to blue
            std::cout << "Colour set to blue!" << std::endl;
            colour = 1;
            break;
        case SDLK_KP_2:
            // set colour to red
            std::cout << "Colour set to red!" << std::endl;
            colour = 2;
            break;
        case SDLK_KP_3:
            // set colour to green
            std::cout << "Colour set to green!" << std::endl;
            colour = 3;
            break;
        case SDLK_KP_4:
            std::cout << "Colour set to purple!" << std::endl;
            colour = 4;
            break;
        case SDLK_KP_0:
            std::cout << "Colour set to white!" << std::endl;
            colour = 0;
            break;
        }
        break;
        //this draws the rectangle:
    case SDL_MOUSEBUTTONDOWN:
        shouldDrawRect = true;
        break;
        //this removes it
    case SDL_MOUSEBUTTONUP:
        shouldDrawRect = false;
        break;
    }
}

//this function is supposed to draw the rect
void Window::drawRect( int x, int y, int h, int w )
{
    SDL_Rect rect = { x, y, w, h };
    SDL_RenderFillRect( _renderer, &rect );
}

bool running = true;

int main( int argc, char *argv[] )
{
    SDL_Init( SDL_INIT_EVERYTHING );

    Window window( "Hello World", 800, 600 );
    SDL_Event event;

    while( !window.closed )
    {
        SDL_SetRenderDrawColor( window._renderer, 255, 255, 255, 255 );
        SDL_RenderClear( window._renderer );

        while( SDL_PollEvent( &event ) )
        {
            window.runEvents( event );
        }
        window.drawScene();

        SDL_RenderPresent( window._renderer );
    }
    return 0;
}