From 6eed8de736ff18a2aed65cd9ba62c6a7b5d18c59 Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Thu, 21 Dec 2017 11:29:41 +0100 Subject: Vastly improve following. --- src/common.hpp | 22 ++++++++++--- src/game/interface.cpp | 89 ++++++++++++++++++++++++++++---------------------- 2 files changed, 67 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/common.hpp b/src/common.hpp index 7221b44..87706c8 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -266,13 +266,16 @@ namespace interface { float em; struct { + v2f_t zero_point_s = v2f_t(0, 0); v2f_t center = v2f_t(0, 0); - int target_zoom = 3; - float zoom = 3.0f; + + int zoom = 3; + float zoom_s = 3.0f; + bool panning = false; sf::Vector2f pan_ref; + bool following = true; - v2f_t follow_center = v2f_t(0, 0); } camera; struct { @@ -290,6 +293,8 @@ namespace interface { double perf_hist[10] = {0}; size_t perf_hist_index = 0; + void start_following(void); + void stop_following(void); public: state_t(sf::RenderWindow *window_, game::state_t *game); void tick(double dt); @@ -408,7 +413,14 @@ T bilerp(T a, T b, T c, T d, T x, T y) return lerp(ab, cd, y); } -static inline float expfade(float a, float b, float l, float dt) +template +static inline void expfade(T *a, T b, T l, T dt) +{ + *a = b + (*a - b) * exp(-l * dt); +} + +template +static inline void expfade(vec_t *a, vec_t b, float l, float dt) { - return b + (a - b) * exp(-l * dt); + *a = b + (*a - b) * exp(-l * dt); } diff --git a/src/game/interface.cpp b/src/game/interface.cpp index 1300e95..7697a22 100644 --- a/src/game/interface.cpp +++ b/src/game/interface.cpp @@ -35,56 +35,72 @@ static sf::Vector2f compute_pan(sf::RenderWindow *window, sf::Vector2f pan_ref) return -(vmouse - pan_ref); } +void state_t::start_following(void) +{ + camera.following = true; + camera.zero_point_s = camera.center; + camera.center = v2f_t(0, 0); + print(text::get(text::FOLLOWING_ON)); +} + +void state_t::stop_following(void) +{ + camera.following = false; + camera.center += camera.zero_point_s; + camera.zero_point_s = v2f_t(0, 0); + print(text::get(text::FOLLOWING_OFF)); +} + void state_t::tick(double dt) { - sf::Vector2u size; + vec_t window_size; sf::Event event; - sf::Vector2f view_size; - v2f_t wmouse; // Mouse position in world space; + + v2f_t view_size; v2f_t follow_center(0, 0), view_center, pan_delta; float view_scale; + v2f_t wmouse; // Mouse position in world space; - size = window->getSize(); + window_size = window->getSize(); - camera.zoom = expfade(camera.zoom, camera.target_zoom, 15, dt); - view_scale = 4.5 * exp(camera.zoom * 0.12); - if (size.x < size.y) { - view_size.y = view_scale; - view_size.x = view_scale * size.x / size.y; + expfade(&camera.zoom_s, camera.zoom, 15, dt); + view_scale = 4.5 * exp(camera.zoom_s * 0.12); + if (window_size[0] < window_size[1]) { + view_size[1] = view_scale; + view_size[0] = view_scale * window_size[0] / window_size[1]; } else { - view_size.x = view_scale; - view_size.y = view_scale * size.y / size.x; + view_size[0] = view_scale; + view_size[1] = view_scale * window_size[1] / window_size[0]; } - if (!game->selected_units.size() && camera.following) { - camera.center = camera.follow_center; - print(text::get(text::FOLLOWING_OFF)); - camera.following = false; - } + if (!game->selected_units.size() && camera.following) + stop_following(); if (camera.following) { + float limit; + for (entity_t *ent : game->selected_units) follow_center += ent->render_bounds.center(); follow_center /= game->selected_units.size(); - camera.follow_center[0] = expfade(camera.follow_center[0], follow_center[0], dt, 25); - camera.follow_center[1] = expfade(camera.follow_center[1], follow_center[1], dt, 25); - } - - view_center = camera.center; + expfade(&camera.zero_point_s, follow_center, 15, dt); - if (camera.following) - view_center += camera.follow_center; + limit = view_scale * 0.2f; + if (camera.center.len() > limit * 2.0f) + stop_following(); + else if (camera.center.len() > limit) + expfade(&camera.center, camera.center.norm() * limit, 3, dt); + } + view_center = camera.zero_point_s + camera.center; window->setView(sf::View(view_center, view_size)); if (camera.panning) { pan_delta = compute_pan(window, camera.pan_ref); view_center += compute_pan(window, camera.pan_ref); + window->setView(sf::View(view_center, view_size)); } - window->setView(sf::View(view_center, view_size)); - wmouse = window->mapPixelToCoords(sf::Mouse::getPosition(*window)); while (window->pollEvent(event)) { @@ -134,11 +150,11 @@ void state_t::tick(double dt) break; case sf::Event::MouseWheelScrolled: - camera.target_zoom -= event.mouseWheelScroll.delta; - if (camera.target_zoom < 0) - camera.target_zoom = 0; - if (camera.target_zoom > 17) - camera.target_zoom = 17; + camera.zoom -= event.mouseWheelScroll.delta; + if (camera.zoom < 0) + camera.zoom = 0; + if (camera.zoom > 17) + camera.zoom = 17; break; case sf::Event::KeyPressed: @@ -152,15 +168,10 @@ void state_t::tick(double dt) break; case sf::Keyboard::Key::F: - camera.following ^= 1; - - if (!camera.following) { - camera.center = view_center; - print(text::get(text::FOLLOWING_OFF)); - } else { - camera.center = v2f_t(0, 0); - print(text::get(text::FOLLOWING_ON)); - } + if (camera.following) + stop_following(); + else + start_following(); break; case sf::Keyboard::Key::H: -- cgit