Rectangle C++ 和 SDL2 中的鼠标有多深(位置在两个位置之间闪烁)

How deep is mouse in Rectangle C++ & SDL2 (Position flickers between two positions)

我正在创建一个程序,我有一个矩形。基本上,我在 SDL2 window 中创建一个自定义 window,它是一个 Rect,另一个 Rect 是它的工具栏。我苦苦挣扎了几个小时,试图弄清楚如何检测鼠标在 Rect 中的深度,但我每次都失败了。对我来说最明显的等式是 int deep = mousePos.x - x,但每次我移动鼠标时它都会在两个位置之间闪烁。然后我尝试了很多其他计算,但其中 none 成功了。它们要么在两个值递减的位置之间闪烁,要么完全静止不动,或者总是在特定方向上移动很多。我已经直观地表示了计算结果,这些计算结果大部分是正确的,但两个位置之间的闪烁总是会破坏它。谢谢你的帮助。我也提供源代码。

来源:

//
//  main.cpp
//  Open
//
//  Created by Fildom on 28.12.2021.
//

// Library includes
#include <SDL2/SDL.h>
#include <stdio.h>

bool isdown = false;

// Screen rendering helper
void on_render(SDL_Window* window, SDL_Renderer* renderer);

// Concatenation (probably not spelt correctly but idrc) for easier use
const char * concat(const char * one, const char * two) {
    char * buffer = new char[strlen(one) + strlen(two) + 1];
    strcpy(buffer, one);
    strcat(buffer, two);
    return buffer;
}

// Main method, required for performing application run
int main(int argc, const char * argv[]) {
    SDL_Renderer    *renderer = NULL;   // Initialize the renderer
    SDL_Event       event = { 0 };      // Create a null event
    SDL_Window      *win = NULL;        // Initialize a window
    int             exit = 0;           // If exit is 1, win closes
    
    // Window pre-modifiers
    const char * appName = "test";

    // SDL VIDEO mode initialization and error check
    if(SDL_Init(SDL_INIT_VIDEO) == -1) {
        printf("SDL_Init() failed with \"%s.\"", SDL_GetError());
        return 1;
    }
    
    // Create the window and load it into a previously defined variable
    win = SDL_CreateWindow(concat(appName, " - Initialization in progress"), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
    
    // Window creation was unsuccessfull
    if(!win) {
        printf("SDL_CreateWindow() failed with \"%s.\"", SDL_GetError());
        return -1;
    }

    // Creating renderer
    renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
    
    // If renderer failed to load...
    if(!renderer) {
        printf("SDL_CreateRenderer() failed with \"%s.\"", SDL_GetError());
        return -1;
    }
    // Everything has gone OK, thus the window can be renamed
    SDL_SetWindowTitle(win, appName);

    // Game loop, as said previously, false = 0, true = 1.
    // while !exit                |
    // while not exit            <- |
    // while exit is 0 (false)     <-
    while (!exit) {
        // Event loop
        if (SDL_WaitEvent(&event)) {
            // Event types
            switch(event.type) {
            case SDL_QUIT:
                exit = 1; // Exit = 1, thus app is being exitted
                break;
            case SDL_KEYDOWN:
                if(event.key.keysym.sym == SDLK_ESCAPE) exit = 1; // If ESC is pressed
                break;
            case SDL_MOUSEBUTTONUP:
                isdown = false;
                break;
            case SDL_MOUSEBUTTONDOWN:
                isdown = true;
                break;
            case SDL_MOUSEMOTION:
                break;
            case SDL_WINDOWEVENT:
                switch(event.window.event) {
                case SDL_WINDOWEVENT_CLOSE: // macOS and/or other OSes rely on right click + Quit to fully exit out of an application. This makes it easier by just hitting the close button.
                    exit = 1;
                    break;
                }
                break;
            default: break;
            }
        }
        // Render the screen
        on_render(win, renderer);

        // Swap buffers to display
        SDL_RenderPresent(renderer);
    }

    // Cleanup
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(win);
    SDL_Quit();

    return 0;
}

class Window {
public:
    int x, y, w, h;
    SDL_Color winc, wintc;
    bool draggable;
    int titleh;
    Window(int wx, int wy, int ww, int wh, SDL_Color window_color = {255, 255, 255, 255}, SDL_Color window_title_color = {200, 200, 200, 255}) {
        x = wx;
        y = wy;
        w = ww;
        h = wh;
        winc = window_color;
        wintc = window_title_color;
        draggable = true;
        titleh = 50;
    }
    int tx, ty = 0;
    void Render(SDL_Renderer* renderer) {
        SDL_Rect _t;
        _t.x = x;
        _t.y = y;
        _t.w = w;
        _t.h = h;
        SDL_Rect title;
        title.x = x;
        title.y = y;
        title.w = w;
        title.h = titleh;
        SDL_SetRenderDrawColor(renderer, winc.r, winc.g, winc.b, winc.a);
        SDL_RenderFillRect(renderer, &_t);
        SDL_SetRenderDrawColor(renderer, wintc.r, wintc.g, wintc.b, wintc.a);
        SDL_RenderFillRect(renderer, &title);
        int mx, my;
        SDL_PumpEvents();
        SDL_GetMouseState(&mx, &my);
        SDL_Point ms;
        ms.x = mx;
        ms.y = my;
        if (SDL_PointInRect(&ms, &title) and isdown) {
            x = mx - tx;
            y = my - ty;
            tx = x;
            ty = y;
        }
    }
};

Window test1 = Window(200, 100, 300, 200);

void on_render(SDL_Window* window, SDL_Renderer* renderer) {
    SDL_Rect wind = { 0 };
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);
    SDL_GetWindowSize(window, &wind.w, &wind.h);
    test1.Render(renderer);
}

我最终以不同的方式做到了。我没有使用 mousePosition.x 和 y,而是使用了完美的相对 X 和 Y。

代码是

mousePosition.relX and mousePosition.relY;