7
\$\begingroup\$

I'm using the cosine function in C++ to simulate flashing for a sprite in my game. The method looks like this:

(anything in the sf namespace is part of the SFML graphics library)

void Player::update(const float& deltaTime)
{
 mAccumulatedTime += deltaTime;
 float opacity = abs(cosf(5*mAccumulatedTime)) * 255;
 static int numFlashes = 0;
 if (opacity == 255) {
 cout << ++numFlashes << endl;
 }
 mSprite.setFillColor(sf::Color(255, 255, 255, opacity));
}

So every time opacity is equal to 255 (basically the passing of one full period), numFlashes should be incremented. The problem is, cos() isn't perfect, meaning it doesn't exactly reach 1 and 0, so the if condition is rarely met. If I use rough checking like if (opacity > 255*0.9999), then numFlashes becomes really high, really fast.

Does anyone know a way to accurately check when a full period has passed? Or is that just not possible?

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Aug 1, 2012 at 1:36
\$\endgroup\$
4
  • \$\begingroup\$ Is delta time in seconds or milli seconds? \$\endgroup\$ Commented Aug 1, 2012 at 3:08
  • 1
    \$\begingroup\$ @LokiAstari microseconds (SFML supports it) \$\endgroup\$ Commented Aug 1, 2012 at 3:18
  • \$\begingroup\$ @LokiAstari it's actually not supposed to be in microseconds... I just fixed that problem by dividing deltaTime by 1,000,000 in the method-call, so NOW it's in seconds. \$\endgroup\$ Commented Aug 1, 2012 at 3:24
  • \$\begingroup\$ Note: cosf() parameter is in radians. So it will get back to 1 every 2.pi/5 seconds (apprx 1.25 seconds). But since you are using abs() on it 0.625 seconds. \$\endgroup\$ Commented Aug 1, 2012 at 6:04

2 Answers 2

6
\$\begingroup\$

One may use the following closed formula to compute numFlashes:

numFlashes = 5 * mAccumulatedTime / pi.

This follows from the fact that the period of the function abs(cos(x)) is pi and, if an oscillating function in variable x has a period T, then the number of oscillations, n, is given by the formula:

n = x / T.

Thus, your function definition may be corrected, and even simplified, as follows:

const float PI = acosf(-1);
void Player::update(const float& deltaTime)
{
 mAccumulatedTime += deltaTime;
 float opacity = abs(cosf(5*mAccumulatedTime)) * 255;
 int numFlashes = 5 * mAccumulatedTime / PI;
 cout << numFlashes << endl;
 mSprite.setFillColor(sf::Color(255, 255, 255, opacity));
}
answered Aug 1, 2012 at 9:48
\$\endgroup\$
1
\$\begingroup\$

Is it critical that you flash on the maximum? You could change it to flash as it crosses a value if not.

double CalcOpacity( const float& accTime )
{
 return (cosf(PERIOD*mAccumulatedTime)) * AMPLITUDE;
}
void Player::update(const float& deltaTime)
{
 float old_opacity = CalcOpacity( mAccumulatedTime );
 mAccumulatedTime += deltaTime;
 float opacity = CalcOpacity( mAccumulatedTime );
 static int numFlashes = 0;
 if ( ( old_opacity < 0 ) && ( opacity >= 0 ) ) {// and the other direction
 cout << ++numFlashes << endl;
 }
 mSprite.setFillColor(sf::Color(255, 255, 255, abs(opacity)));
}
answered Aug 1, 2012 at 6:59
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.