SFML community forums

Help => System => Topic started by: The Terminator on December 30, 2013, 03:49:52 am

Title: How would I do this every millisecond?
Post by: The Terminator on December 30, 2013, 03:49:52 am
Hi there,

For a label that I'm creating on my main menu, I want it to animate over 3 colors in 9 seconds. The 3 color RGBA values are: (255, 255, 255, 50), (0, 161, 94, 50), (102, 0, 0, 50). To give it the "gradual" effect, I want it to increase or decrease the RGBA values of an sf::Color every millisecond. In order to get the value to increase or decrease per millisecond, I just found the difference of the respected values and divided it by 1000. Here's my (unworking) code that I've written:

(FYI: m_totalTime is a private float value in a class, m_animated_label_clock is a sf::Clock private member, and m_label_color is a sf::Color private member.)

if (m_totalTime <= 3)
        {
            if (m_animated_label_clock.getElapsedTime().asMilliseconds() == 0.001)
            {
                m_label_color.r -= 0.085;
                m_label_color.b -= 0.0313;
                m_label_color.g -= 0.0683;
            }
        }

        else if (m_totalTime > 3 && m_totalTime <= 6)
        {
            if (m_animated_label_clock.getElapsedTime().asMilliseconds() == 0.001)
            {
                m_label_color.r += 0.034;
                m_label_color.b -= 0.0536;
                m_label_color.g -= 0.0313;
            }
        }

        else if (m_totalTime > 6 && m_totalTime <= 9)
        {
            if (m_animated_label_clock.getElapsedTime().asMilliseconds() == 0.001)
            {
                m_label_color.r += 0.102;
                m_label_color.b -= 0.161;
                m_label_color.g -= 0.094;
            }
        }

        m_totalTime += m_animated_label_clock.getElapsedTime().asMilliseconds();
        m_animated_label_clock.restart();

Thanks for any and all help!
Title: Re: How would I do this every millisecond?
Post by: G. on December 30, 2013, 04:20:04 am
asMilliseconds() returns an int, why do you compare it with 0.001?

If you want something done every millisecond but your elapsed time is x milliseconds, do your thing x times.
Or you could compute the color values to add or remove for x milliseconds. (you already computed it for 1 millisecond)
Or you could do proper interpolations between your colors.
Title: Re: How would I do this every millisecond?
Post by: eigenbom on December 30, 2013, 04:50:51 am
There's a much simpler way to do that. Here's some code that gradually shifts from colour1 at 0 seconds, to colour2 at 3 seconds, to colour3 at 10 seconds;

Code: [Select]
// use vector2f's for our colours (0=min, 1=max)
sf::Vector2f c1, c2, c3;
sf::Clock clock;

// handy linear interpolation
sf::Vector2f lerp(sf::Vector2f a, sf::Vector2f b, float t){
  return a*(1-t) + b*t;
}

// main loop

const double seconds = clock.getElapsedTime.asSeconds();
sf::Vector2f c;
if (seconds <= 3){
  double t = seconds / 3; // t goes from 0 to 1
  c = lerp(c1, c2, t);
}
else if (seconds <= 10){
  double t = (seconds - 3) / (10-3);
  c = lerp(c2, c3, t);
}
else {
  // after 6 seconds stay as colour 3
  c = c3;
}

// transform c into an sf::Color which we can then use to draw something
sf::Color colour = sf::Color(255*c.x, 255*c.y, 255*c.z);



You can also replace the lerp with other easing functions, such as cubic, easeIn, quadratic, etc, to change how the colour shift behaves. See e.g., this page  (http://easings.net/) for other easing functions.
Title: Re: How would I do this every millisecond?
Post by: The Terminator on December 30, 2013, 05:50:24 am
There's a much simpler way to do that. Here's some code that gradually shifts from colour1 at 0 seconds, to colour2 at 3 seconds, to colour3 at 10 seconds;

Code: [Select]
// use vector2f's for our colours (0=min, 1=max)
sf::Vector2f c1, c2, c3;
sf::Clock clock;

// handy linear interpolation
sf::Vector2f lerp(sf::Vector2f a, sf::Vector2f b, float t){
  return a*(1-t) + b*t;
}

// main loop

const double seconds = clock.getElapsedTime.asSeconds();
sf::Vector2f c;
if (seconds <= 3){
  double t = seconds / 3; // t goes from 0 to 1
  c = lerp(c1, c2, t);
}
else if (seconds <= 10){
  double t = (seconds - 3) / (10-3);
  c = lerp(c2, c3, t);
}
else {
  // after 6 seconds stay as colour 3
  c = c3;
}

// transform c into an sf::Color which we can then use to draw something
sf::Color colour = sf::Color(255*c.x, 255*c.y, 255*c.z);



You can also replace the lerp with other easing functions, such as cubic, easeIn, quadratic, etc, to change how the colour shift behaves. See e.g., this page  (http://easings.net/) for other easing functions.

Thanks for the info! On transforming c, you use c.z which is nonexistent in a sf::Vector2f. Did you mean to put sf::Vector3f?

Thanks
Title: Re: How would I do this every millisecond?
Post by: eigenbom on January 01, 2014, 09:09:28 am
Oops, yep Vector3f. :)