Friday, April 15, 2016

Shaky Camera Effect 2D


The camera in my game engine can be modified by following a rectangle properties, that can be scaled, moved and even rotated. I need this effect for the shaking of the screen when a zombie attacks a character.



How should I go about implementing this?



Answer



Store the logical screen position and the actual screen position in separate containers... The logical screen position is the position, where the screen should be, when no shaking happens... When shaking happens apply some offset to the logical screen position to get the actual screen position.


I made a little example (not tested and not completly implemented, but it should show how you could make the shake effect). Below I have added some thoughts about whats currently missing in my example.


class Viewport
{
float xOffset = 0;
float yOffset = 0;
int shakeTimer = 0;


public Vector2f actual;
public Vector2f logical;

//Shaking will take 200ms
public final int SHAKE_TIME_MS = 200;

//The screen will be moved 20 pixels forth and back
public final int SHAKE_OFFSET = 20;

//Indicates the shake move direction

public boolean shakeDirection = false;

//Indicates if the screen is currently shaking
public boolean shaking;

//delta is the ms passed since last update
public void update(int delta)
{
if(shaking)
{

updateShake(delta);
}
else
{
actual.x = logical.x;
actual.y = logical.y;
}
}

private void updateShake(int delta) {

if(shakeTimer == 0)
{
//If its the first run from the current shake, initialise x and y offset to 0
xOffset = 0;
yOffset = 0;
}

//Add passed milliseconds to timer... If timer exceeds configuration, shaking ends
shakeTimer += delta;
if(shakeTimer > SHAKE_TIME_MS)

{
//Shaking ends
shakeTimer = 0;
shaking = false;
xOffset = 0;
yOffset = 0;
}
else
{
applyScreenShake(delta);

}
}

private void applyScreenShake(int delta) {
//Depending on shake direction, the screen is moved either to the top left, or the bottom right
if(shakeDirection)
{
xOffset -= 1.5f * delta;
if(xOffset < -SHAKE_OFFSET)
{

//SWITCH DIRECTION
xOffset = -SHAKE_OFFSET;
shakeDirection = !shakeDirection;
}
yOffset = xOffset;
}
else
{
xOffset += 1.5f * delta;
if(xOffset > SHAKE_OFFSET)

{
//SWITCH DIRECTION
xOffset = SHAKE_OFFSET;
shakeDirection = !shakeDirection;
}
yOffset = xOffset;
}
actual.x = logical.x + xOffset;
actual.y = logical.y + yOffset;
}

}

I hope this gets you going... Some things you can consider:



  • Currently the screen only shakes linear to the top left and the bottom right... You could make this more interesting, by adding random move directions, as long as the x and y offset stays in a given distance.

  • When the shaking ends, the x and y offset are abruptly set to 0/0... This causes the shake to end abruptly... You could smooth this out by handling the stopped case separately.

  • When you want to scroll on the screen (map etc.) you have to change the logical position of the viewport.

  • Your rendering logic needs to use the actual position and not the logical position as render offset.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...