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;
}