SFML 3.0.0 С++ Передвижение с помощью ЛКМ и перемещения мыши

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

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

К примеру я хочу попасть вверх карты начиная снизу, значит нужно задать ЛКМ и повести мышкой вниз. Такая реализация часто используются в играх где ты как будто смотришь сверху на мир.

Я пытался сам реализовать такое с помощью отслеживания изменений координат курсора и вроде добился каких-то успехов но карта вечно подлагивает, карта 6400*6400 пикселей так что не должна по идее сильно нагружать ноутбук а соответственно подлагивать. Можете подсказать реализацию? По возможности на 3.0.0, но подойдёт для любой версии. Возможно у вас какаято своя реализация или идея\совет.

Вот мой код: #include <SFML/Graphics.hpp>

using namespace std; using namespace sf;

int main() { VideoMode desktopMode = VideoMode::getDesktopMode(); const Vector2u winSize = { 800, 600 }, desktopSize = desktopMode.size, mapSize = { 6400, 6400 };

RenderWindow win(VideoMode({ 800, 600 }), "Angry Birds Epic New Start");
win.setFramerateLimit(60);

// Создание карты
RectangleShape GameMap(Vector2f(6400, 6400));
Texture MapTexture;
if (!MapTexture.loadFromFile("images/Objects/Map/MapTemp.png")) {
    return 1;
}
GameMap.setTexture(&MapTexture);

// Настройка камеры
View camera = win.getDefaultView();
camera.setCenter({ float(winSize.x / 2), float(mapSize.y - float(winSize.y / 2)) });

Vector2f targetCameraPos = camera.getCenter();
const float lerpSpeed = 0.3f;

// Переменные для зума
float zoomLevel = 1.0f;
const float minZoom = 1.0f;  // Минимальный зум 
const float maxZoom = 5.0f;  // Максимальный зум
const float zoomSpeed = 0.1f; // Скорость зума

// Переменные для перемещения камеры
bool isDragging = false;
Vector2f lastMousePos;

while (win.isOpen()) {
    while (const optional event = win.pollEvent()) {
        // Закрытие окна
        if (event->is<Event::Closed>())
            win.close();

        // Обработка нажатия ЛКМ
        if (event->is<Event::MouseButtonPressed>()) {
            if (const auto* mouseEvent = event->getIf<Event::MouseButtonPressed>()) {
                if (mouseEvent->button == Mouse::Button::Left) {
                    isDragging = true;
                    lastMousePos = win.mapPixelToCoords(Vector2i(mouseEvent->position));
                }
            }
        }

        // Обработка отпускания ЛКМ
        if (event->is<Event::MouseButtonReleased>()) {
            if (const auto* mouseEvent = event->getIf<Event::MouseButtonReleased>()) {
                if (mouseEvent->button == Mouse::Button::Left) {
                    isDragging = false;
                }
            }
        }

        // Обработка зума колесиком мыши
        if (event->is<Event::MouseWheelScrolled>()) {
            if (const auto* wheelEvent = event->getIf<Event::MouseWheelScrolled>()) {
                if (wheelEvent->wheel == Mouse::Wheel::Vertical) {
                    // Получаем позицию мыши в мировых координатах до зума
                    Vector2f mousePosBeforeZoom = win.mapPixelToCoords(Vector2i(wheelEvent->position));

                    // Изменяем уровень зума
                    float zoomFactor = (wheelEvent->delta > 0) ? (1.0f - zoomSpeed) : (1.0f + zoomSpeed);
                    zoomLevel = clamp(zoomLevel * zoomFactor, minZoom, maxZoom);
                    camera.setSize(win.getDefaultView().getSize()); // Сброс размера
                    camera.zoom(zoomLevel); // Применяем зум

                    // Получаем позицию мыши после зума
                    Vector2f mousePosAfterZoom = win.mapPixelToCoords(Vector2i(wheelEvent->position));

                    // Корректируем позицию камеры для плавного зума к курсору
                    targetCameraPos += (mousePosBeforeZoom - mousePosAfterZoom);
                }
            }
        }
    }

    // Перемещение камеры при зажатой ЛКМ
    if (isDragging && Mouse::isButtonPressed(Mouse::Button::Left)) {
        Vector2f currentMousePos = win.mapPixelToCoords(Mouse::getPosition(win));
        targetCameraPos += lastMousePos - currentMousePos;
        lastMousePos = currentMousePos;

        // Ограничение границ с учетом текущего зума
        const Vector2f viewHalfSize = camera.getSize() / 2.f;
        targetCameraPos = {
            clamp(targetCameraPos.x, viewHalfSize.x, mapSize.x - viewHalfSize.x),
            clamp(targetCameraPos.y, viewHalfSize.y, mapSize.y - viewHalfSize.y)
        };
    }

    // Плавное перемещение камеры к целевой позиции
    camera.setCenter(camera.getCenter() + (targetCameraPos - camera.getCenter()) * lerpSpeed);

    // Отрисовка
    win.clear();
    win.setView(camera);
    win.draw(GameMap);
    win.display();
}

return 0;

}


Ответы (0 шт):