Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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?

share|improve this question
    
Really, really hard to tell what you're asking here. Modified by a rectangle? Modified how? Also, I think you mean 'shake / shakey'. 'shack' means something completely different. –  MrCranky Jul 10 '12 at 10:45
    
@MrCranky Thank you for your notification. I have editted my question. –  DatVM Jul 10 '12 at 10:50
2  
possible duplicate of Realistic Camera/Screen Shake from Explosion –  bummzack Jul 10 '12 at 13:18

1 Answer 1

up vote 3 down vote accepted

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.
share|improve this answer
    
Just noticed that I forgot to set the actual screen position in the applyScreenShake method... I corrected the code example... –  tom van green Jul 10 '12 at 14:48
    
See in the link in the comment for the possible duplicate if you want a more advanced (but harder to implement) solution. Basically the principle of keeping a logical and actual viewport would be the same, but the generation of movement is not liniear but more organical, because its based on a noise. But it looks quiet advanced to implement, so if you are a beginner, I would stay with a simpler solution at first. –  tom van green Jul 12 '12 at 7:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.