Получить координаты текстуры позиции мыши в SDL2? - PullRequest
1 голос
/ 09 июня 2019

У меня есть строгое требование иметь текстуру с разрешением (скажем) 512x512 всегда (даже если окно больше, а SDL в основном масштабирует текстуру для меня при рендеринге).Это потому, что это эмулятор классического старого компьютера, предполагающего фиксированную текстуру, я не могу переписать код для динамического принятия нескольких размеров текстур и / или соотношений текстур.

Я использую SDL_RenderSetLogicalSize() для цели IВыше описано.

Конечно, когда это отображается в окне, я могу получить координаты мыши (относительное окно), и я могу «масштабировать» обратно до положения текстуры с получением реального размера окна (размер окна может быть изменен).

Однако здесь есть большая проблема .Как только соотношение ширины окна к высоте не совпадает с соотношением текстур (например, в полноэкранном режиме, поскольку соотношение современных дисплеев не будет совпадать с соотношением, которое я хочу использовать), на панели появляются «черные полосы»стороны или верх / низ.Это хорошо, так как я хочу всегда иметь одинаковое соотношение текстур, фиксированное, и SDL делает это для меня и т. Д. Однако я не могу найти способ спросить SDL, где моя текстура отображается именно внутри окна на основе фиксированного соотношения, которое я принудительно установил.Поскольку мне нужна только позиция внутри текстуры, а точный источник текстуры размещается самим SDL, а не мной.

Конечно, я могу написать некоторый код, чтобы выяснить, как эти "черные полосы" изменили быПроисхождение текстуры, но я могу надеяться, что есть более простой и элегантный способ «спросить» SDL об этом, поскольку, безусловно, он имеет код для размещения моей текстуры где-то, поэтому я могу повторно использовать эту информацию.

Мое очень уродливое (можно оптимизировать и избежать математики с плавающей точкой, я думаю, но в качестве первой попытки ...) решение:

static void get_mouse_texture_coords ( int x, int y )
{
    int win_x_size, win_y_size;
    SDL_GetWindowSize(sdl_win, &win_x_size, &win_y_size);
    // I don't know if there is more sane way for this ...
    // But we must figure out where is the texture within the window,
    // which can be changed since the fixed ratio versus the window ratio (especially in full screen mode)
    double aspect_tex = (double)SCREEN_W / (double)SCREEN_H;
    double aspect_win = (double)win_x_size / (double)win_y_size;
    if (aspect_win >= aspect_tex) {
            // side ratio correction bars must be taken account
            double zoom_factor = (double)win_y_size / (double)SCREEN_H;
            int bar_size = win_x_size - (int)((double)SCREEN_W * zoom_factor);
            mouse_x = (x - bar_size / 2) / zoom_factor;
            mouse_y = y / zoom_factor;
    } else {
            // top-bottom ratio correction bars must be taken account
            double zoom_factor = (double)win_x_size / (double)SCREEN_W;
            int bar_size = win_y_size - (int)((double)SCREEN_H * zoom_factor);
            mouse_x = x / zoom_factor;
            mouse_y = (y - bar_size / 2) / zoom_factor;
    }
}

Где SCREEN_W и SCREEN_H - этоРазмеры моей текстуры, довольно вводящие в заблуждение по именам, но все равно.Входные параметры x и y - это положение мыши относительно окна (сообщается SDL).mouse_x и mouse_y - результат, основанный на текстуре координаты.Кажется, это работает хорошо.Однако есть ли вменяемое решение или лучшее?

Код, который вызывает вышеуказанную функцию, находится в моем цикле обработчика событий (который я регулярно вызываю, конечно), что-то вроде этого:

void handle_sdl_events ( void ) {
    SDL_Event event;
    while (SDL_PollEvent(&event)) {
    switch (event.type) {
        case SDL_MOUSEMOTION:
            get_mouse_texture_coords(event.motion.x, event.motion.y);
            break;
        [...]
...