1
0
Fork 0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-12-23 01:59:43 +01:00

Fix text box deltaframe flashing on deltaframes after fully opaque

So #434 didn't end up solving the deltaframe flashing fully, only
reduced the chances that it could happen.

I've had the Level Complete image flash a few times when the Game Saved
text box pops up. This seems to be because the Level Complete image is
based off of the text box being at y-position 12, and the Game Saved
text box is also at y-position 12. Level Complete only gets drawn if the
text box additionally has a red channel value of 165, and the Game Saved
text box has a red channel value of 174. However, there is a check that
the text box be fully opaque first before drawing special images. So
what went wrong?

Well, after thinking about it for a while, I realized that even though
there is indeed an opaqueness check, the alpha of the text box updates
BEFORE it gets drawn. And during the deltaframes immediately after it
gets updated, the text box is considered fully opaque. It's completely
possible for the linear interpolation to end up with a red channel value
of 165 during these deltaframes, while the text box is opaque as well.

As always, it helps if you have a high refresh rate, and run the game
under 40% slowdown.

Anyways, so what's the final fix for this issue? Well, use the text box
'target' RGB values instead - its tr/tg/tb attributes instead of its
r/g/b attributes. They are not subject to interpolation and so are
completely reliable. The opaqueness check should still be kept, though,
because the target values don't account for opaqueness. And this way, we
get no more deltaframe flashes during text box fades.

An even better fix would be to not use magic RGB values to draw special
images... but that'd be something to do later.
This commit is contained in:
Misa 2021-03-21 12:49:14 -07:00 committed by Ethan Lee
parent 415d4790e2
commit 17169320b4

View file

@ -835,6 +835,7 @@ void Graphics::drawgui(void)
{ {
int text_yoff; int text_yoff;
int yp; int yp;
bool opaque;
if (flipmode) if (flipmode)
{ {
text_yoff = textbox[i].line.size() * 8; text_yoff = textbox[i].line.size() * 8;
@ -854,7 +855,7 @@ void Graphics::drawgui(void)
float tl_lerp = lerp(textbox[i].prev_tl, textbox[i].tl); float tl_lerp = lerp(textbox[i].prev_tl, textbox[i].tl);
textbox[i].setcol(textbox[i].tr * tl_lerp, textbox[i].tg * tl_lerp, textbox[i].tb * tl_lerp); textbox[i].setcol(textbox[i].tr * tl_lerp, textbox[i].tg * tl_lerp, textbox[i].tb * tl_lerp);
if (textbox[i].r == 0 && textbox[i].g == 0 && textbox[i].b == 0) if (textbox[i].tr == 0 && textbox[i].tg == 0 && textbox[i].tb == 0)
{ {
for (size_t j = 0; j < textbox[i].line.size(); j++) for (size_t j = 0; j < textbox[i].line.size(); j++)
{ {
@ -888,11 +889,14 @@ void Graphics::drawgui(void)
} }
} }
// Only draw special images when fully opaque opaque = textbox[i].tl >= 1.0;
// This prevents flashes of special images during delta frames
bool drawspecial = textbox[i].tl >= 1.0;
if (textbox[i].yp == 12 && textbox[i].r == 165 && drawspecial) if (!opaque)
{
continue;
}
if (textbox[i].yp == 12 && textbox[i].tr == 165)
{ {
if (flipmode) if (flipmode)
{ {
@ -903,7 +907,7 @@ void Graphics::drawgui(void)
drawimage(0, 0, 12, true); drawimage(0, 0, 12, true);
} }
} }
else if (textbox[i].yp == 12 && textbox[i].g == 165 && drawspecial) else if (textbox[i].yp == 12 && textbox[i].tg == 165)
{ {
if (flipmode) if (flipmode)
{ {
@ -914,27 +918,27 @@ void Graphics::drawgui(void)
drawimage(4, 0, 12, true); drawimage(4, 0, 12, true);
} }
} }
if (textbox[i].r == 175 && textbox[i].g == 175 && drawspecial) if (textbox[i].tr == 175 && textbox[i].tg == 175)
{ {
//purple guy //purple guy
drawsprite(80 - 6, crew_yp, crew_sprite, 220- help.glow/4 - int(fRandom()*20), 120- help.glow/4, 210 - help.glow/4); drawsprite(80 - 6, crew_yp, crew_sprite, 220- help.glow/4 - int(fRandom()*20), 120- help.glow/4, 210 - help.glow/4);
} }
else if (textbox[i].r == 175 && textbox[i].b == 175 && drawspecial) else if (textbox[i].tr == 175 && textbox[i].tb == 175)
{ {
//red guy //red guy
drawsprite(80 - 6, crew_yp, crew_sprite, 255 - help.glow/8, 70 - help.glow/4, 70 - help.glow / 4); drawsprite(80 - 6, crew_yp, crew_sprite, 255 - help.glow/8, 70 - help.glow/4, 70 - help.glow / 4);
} }
else if (textbox[i].r == 175 && drawspecial) else if (textbox[i].tr == 175)
{ {
//green guy //green guy
drawsprite(80 - 6, crew_yp, crew_sprite, 120 - help.glow / 4 - int(fRandom() * 20), 220 - help.glow / 4, 120 - help.glow / 4); drawsprite(80 - 6, crew_yp, crew_sprite, 120 - help.glow / 4 - int(fRandom() * 20), 220 - help.glow / 4, 120 - help.glow / 4);
} }
else if (textbox[i].g == 175 && drawspecial) else if (textbox[i].tg == 175)
{ {
//yellow guy //yellow guy
drawsprite(80 - 6, crew_yp, crew_sprite, 220- help.glow/4 - int(fRandom()*20), 210 - help.glow/4, 120- help.glow/4); drawsprite(80 - 6, crew_yp, crew_sprite, 220- help.glow/4 - int(fRandom()*20), 210 - help.glow/4, 120- help.glow/4);
} }
else if (textbox[i].b == 175 && drawspecial) else if (textbox[i].tb == 175)
{ {
//blue guy //blue guy
drawsprite(80 - 6, crew_yp, crew_sprite, 75, 75, 255- help.glow/4 - int(fRandom()*20)); drawsprite(80 - 6, crew_yp, crew_sprite, 75, 75, 255- help.glow/4 - int(fRandom()*20));