christopho/solarus — Issue #12: Addition of shaking effects in the engine.
Author: Bertram25
Created: 2011-11-30 10:25:56+00:00
State: open

Hi,

As requested by Christopho,

The engine should be handle tremoring/shaking scriptable effects.

It should also support more than one at a time, because one effect shouldn't cancel the previous one if the case should happen.

The shaking should support different intensity, and duration, but also the difference in x, and y shaking for different effects.

Later on, the engine could also handle continous shaking stoppable through scripting, or tremors with scriptable changing intensity.

Uses cases for the effect that could be nice :

- Make the screen shake when the Hero reaches a wall while running.
- Make the screen shake when a heavy door opens or closes.
- Make the screen shake depending on how near the hero is from a heavy boss.
- Make the screen shake when the hero has dealt heavy damage
...

An algorithm example (not handling the continuous effects):

```c++
In the header:
struct ShakeEffect
{
float x;
float y;
float decay;
unsigned duration;
};
typedef std::list ShakeEffects;
ShakeEffects shakeEffects;

In the main gui drawing loop, for instance in void Camera::update(),
juste before the last statement (position.set_xy(x, y);):
// manage shake effect
for (ShakeEffects::iterator i = shakeEffects.begin();
i != shakeEffects.end(); ++i)
{
// apply the effect to viewpoint
x += i->x *= -i->decay;
y += i->y *= -i->decay;
// check shake effects death conditions
if (abs(i->x) + abs(i->y) < 1.0f ||
(i->duration > 0 && --i->duration == 0))
{
i = shakeEffects.erase(i);
}
}

// Other useful functions.
void shakeScreenStop()
{ shakeEffects.clear(); }

void Camera::shakeScreen(int intensity)
{
float direction = rand()%628 / 100.0f; // random value between 0 and 2PI
float x = std::sin(direction) * intensity;
float y = std::cos(direction) * intensity;
shakeScreen(x, y);
}

void Camera::shakeScreen(float x, float y, float decay, unsigned duration)
{
ShakeEffect effect;
effect.x = x;
effect.y = y;
effect.decay = decay;
effect.duration = duration;
shakeEffects.push_back(effect);
}
```

Thanks in advance and best regards,