+3 votes

How do you make the camera shake when an event happens like an explosion, etc

in Engine by (117 points)

4 Answers

0 votes
by (1,468 points)
+9 votes

Just set the offset property of the camera with small random values every frames, like this:

    # Animate this to increase/decrease/fade the shaking
var shake_amount = 1.0

func _process(delta):
    camera.set_offset(Vector2( \
        rand_range(-1.0, 1.0) * shake_amount, \
        rand_range(-1.0, 1.0) * shake_amount \
    ))

This will move the camera relatively to its center without interfering with its pivot, producing a shake effect.

by (28,733 points)

Thank you all for the helpful answers

Hi there, with the code above, how is camera assigned?

If I try to use camera it fails. If I try and use Camera it fails also. Do I need to assign it somehow to the camera that you've used? Thank you.

EDIT: I'm assuming of course you can do this with the default camera in any scene? If not, then I guess I will need to create one, place it in the hierarchy, then manipulate that? I'll do that to test, but I thought I'd be able to manipulate the default scenes camera rather than creating one.

camera is a variable in which you should have put a reference to whatever camera you want, before _process gets called. The way you do that depends on your game. It can be the result of something like get_node("Camera") for example. Because a game can have multiple cameras there is no default variable for this. There is a default "camera", but it's not a Camera node (see Viewport documentation).

Thank you. Yes I see that now. You have to create a camera to use it it seems, you can't just use the one that is part of the viewport ("default" camera). I created a camera2d and life was better. :-)

+2 votes
extends Camera2D

export var shake_power = 4
export var shake_time = 0.4
var isShake = false
var curPos
var elapsedtime = 0

func _ready():
    randomize()
    curPos = offset

func _process(delta):
    if isShake:
        shake(delta)    

func _input(event):
    if Input.is_mouse_button_pressed(BUTTON_LEFT) and not isShake:
        elapsedtime = 0
        isShake = true

func shake(delta):
    if elapsedtime<shake_time:
        offset =  Vector2(randf(), randf()) * shake_power
        elapsedtime += delta
    else:
        isShake = false
        elapsedtime = 0
        offset = curPos     
by (18 points)

Wow! This code actually works like a charm, this helped me a lot in my game, so I just wanted to say thanks!

0 votes

I just made a quick, clear, and simple tutorial on how to do this:

https://www.youtube.com/watch?v=eWhglfQFYOk&t=1s

by (586 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.