mirror of
https://github.com/wesnoth/wesnoth
synced 2025-04-22 20:39:29 +00:00
gui/outro: New clock-based timing logic for the text fading (#8454)
This version uses SDL_GetTicks() as a monotonic source to avoid the previous version's pitfalls, namely the fact that the game's framerate may not necessarily be a constant, and in particular, the old code assumed a completely different framerate than what we ended up with after the texture-based rendering changes in 1.17.x, resulting in an almost-unnoticeable text fade due to the update() function being called WAY more often than before. Note that the reliance on SDL_GetTicks() means the timings break at some point after 49 days of game runtime, exactly once. This should result in a visible "jitter" effect if the 32-bits ticks value wraps around in the middle of a fade sequence, but other than that it's not that big of a deal to warrant requiring SDL 2.0.18+ for the 64-bit version. I for one hope players wouldn't be running Wesnoth for that long anyway. The game isn't exciting enough to justify it.
This commit is contained in:
parent
43dd442a4f
commit
db30ca53ae
3
changelog_entries/ui-outro-text-fading.md
Normal file
3
changelog_entries/ui-outro-text-fading.md
Normal file
@ -0,0 +1,3 @@
|
||||
### User interface
|
||||
* Fixed timing issue with the outro screen's text fading effect that made it so fast as
|
||||
to be unnoticeable on many hardware configurations.
|
@ -33,7 +33,7 @@
|
||||
font_size = 80
|
||||
font_family = "script"
|
||||
|
||||
color = "([215, 215, 215, min(ceil(as_decimal(fade_step * 25.5)), 255)])"
|
||||
color = "([215, 215, 215, fade_alpha])"
|
||||
|
||||
text = "(outro_text)"
|
||||
text_markup = true
|
||||
|
@ -28,6 +28,14 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// How long text fading should take - currently a hardcoded value.
|
||||
const unsigned FADE_DURATION_MS = 500;
|
||||
|
||||
} // end unnamed namespace
|
||||
|
||||
namespace gui2::dialogs
|
||||
{
|
||||
REGISTER_DIALOG(outro)
|
||||
@ -38,7 +46,8 @@ outro::outro(const game_classification& info)
|
||||
, current_text_()
|
||||
, text_index_(0)
|
||||
, duration_(info.end_text_duration)
|
||||
, fade_step_(0)
|
||||
, fade_alpha_(0)
|
||||
, fade_start_(0)
|
||||
, fading_in_(true)
|
||||
, timer_id_(0)
|
||||
{
|
||||
@ -105,16 +114,18 @@ void outro::update()
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we've faded fully in...
|
||||
*
|
||||
* NOTE: we want fading to take around half a second. Given this function runs about every 3 frames, we
|
||||
* limit ourselves to a reasonable 10 fade steps with an alpha difference (rounded up) of 25.5 each cycle.
|
||||
* The actual calculation for alpha is done in the window definition in WFL.
|
||||
*/
|
||||
if(fading_in_ && fade_step_ > 10) {
|
||||
if(fade_start_ == 0) {
|
||||
fade_start_ = SDL_GetTicks();
|
||||
}
|
||||
|
||||
// If we've faded fully in...
|
||||
if(fading_in_ && fade_alpha_ >= 255) {
|
||||
// Schedule the fadeout after the provided delay.
|
||||
if(timer_id_ == 0) {
|
||||
timer_id_ = add_timer(duration_, [this](std::size_t) { fading_in_ = false; });
|
||||
timer_id_ = add_timer(duration_, [this](std::size_t) {
|
||||
fading_in_ = false;
|
||||
fade_start_ = 0;
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
@ -123,7 +134,7 @@ void outro::update()
|
||||
canvas& window_canvas = window::get_canvas(0);
|
||||
|
||||
// If we've faded fully out...
|
||||
if(!fading_in_ && fade_step_ < 0) {
|
||||
if(!fading_in_ && fade_alpha_ == 0) {
|
||||
// ...and we've just showed the last text bit, close the window.
|
||||
text_index_++;
|
||||
if(text_index_ >= text_.size()) {
|
||||
@ -136,20 +147,31 @@ void outro::update()
|
||||
window_canvas.set_variable("outro_text", wfl::variant(current_text_));
|
||||
|
||||
fading_in_ = true;
|
||||
fade_step_ = 0;
|
||||
|
||||
remove_timer(timer_id_);
|
||||
timer_id_ = 0;
|
||||
|
||||
fade_start_ = SDL_GetTicks();
|
||||
}
|
||||
|
||||
window_canvas.set_variable("fade_step", wfl::variant(fade_step_));
|
||||
window_canvas.set_variable("fade_alpha", wfl::variant(fade_alpha_));
|
||||
window_canvas.update_size_variables();
|
||||
queue_redraw();
|
||||
|
||||
if(fading_in_) {
|
||||
fade_step_++;
|
||||
} else {
|
||||
fade_step_--;
|
||||
auto current_ticks = SDL_GetTicks();
|
||||
|
||||
if(fade_start_ > current_ticks) {
|
||||
// 32-bit ticks counter wraps around after about 49 days, the 64-bit version
|
||||
// requires SDL 2.0.18+. Just restart the counter in the worst case and let
|
||||
// the player deal with the sheer ridiculousness of their predicament.
|
||||
fade_start_ = current_ticks;
|
||||
}
|
||||
|
||||
fade_alpha_ = std::clamp<int>(
|
||||
std::round(255.0 * double(current_ticks - fade_start_) / double(FADE_DURATION_MS)),
|
||||
0, 255);
|
||||
if(!fading_in_) {
|
||||
fade_alpha_ = 255 - fade_alpha_;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,8 @@ private:
|
||||
std::size_t text_index_;
|
||||
|
||||
unsigned int duration_;
|
||||
int fade_step_;
|
||||
int fade_alpha_;
|
||||
uint32_t fade_start_;
|
||||
|
||||
bool fading_in_;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user