# Cosine function period

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?

-
Is delta time in seconds or milli seconds? –  Loki Astari Aug 1 '12 at 3:08
@LokiAstari microseconds (SFML supports it) –  rcplusplus Aug 1 '12 at 3:18
@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. –  rcplusplus Aug 1 '12 at 3:24
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. –  Loki Astari Aug 1 '12 at 6:04

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));
}
``````
-

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)));
}
``````
-