1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
extends Node

var camera_shake_intensity = 0.0
var camera_shake_duration = 0.0

enum Type { Random, Sine, Noise }
var camera_shake_type = Type.Random

var noise: OpenSimplexNoise


func _ready():
	set_process(false)
	# Generate noise for noise shake
	#
	# This is only generated once when the game starts
	# and then read over and over again
	#
	# These parameters change the shape of the noise
	# and the feel of the shake6
	noise = OpenSimplexNoise.new()
	noise.seed = randi()
	noise.octaves = 4
	noise.period = 20
	noise.persistence = 0.8


func shake(intensity, duration, type = Type.Random):
	# Set the shake parameters
	#
	# A good idea here is to add configuration settings that
	# allow the player to turn off shake
	#
	# if player_no_want:
	# 	intensity = 0

	if intensity > camera_shake_intensity and duration > camera_shake_duration:
		camera_shake_intensity = intensity
		camera_shake_duration = duration
		camera_shake_type = type
		set_process(true)


func _process(delta):
	# Get the camera
	#
	# You'll need to adjust this depending on how you want to
	# keep track of the active camera in your game
	#
	# Maybe your game has two cameras, maybe it has 10, who knows?
	# Do what you like
	var camera = get_tree().current_scene.get_node("Camera2D")
	# Stop shaking if the camera_shake_duration timer is down to zero
	if camera_shake_duration <= 0:
		# Reset the camera when the shaking is done
		camera.offset = Vector2.ZERO
		camera_shake_intensity = 0.0
		camera_shake_duration = 0.0
		set_process(false)
		return

		# Subtract the elapsed time from the camera_shake_duration
		# so that it eventually ends
		#
		# You can do other fun stuff here too like have the intensity
		# decay gradually so that the shake tapers off

		# Shake it

		# Random shake
		# Chaos
		# Madness
		#
		# Personally, I like this best because players don't notice
		# any difference in the thick of battle when the shakes are short
		# and because it's dead simple.

		# Sine wave based shake
		#
		# Play around with the magic numbers to adjust the feel
		#
		# Basing the sine wave off of get_ticks_msec ensures that
		# the returned value is continuous and smooth

		# Noise based shake
		#
		# Accessing the noise based on get_ticks_msec ensures that
		# the returned value is continuous and smooth
	camera_shake_duration = camera_shake_duration - delta

	# Shake it
	var offset = Vector2.ZERO

	if camera_shake_type == Type.Random:
		# Random shake
		# Chaos
		# Madness
		#
		# Personally, I like this best because players don't notice
		# any difference in the thick of battle when the shakes are short
		# and because it's dead simple.
		offset = Vector2(randf(), randf()) * camera_shake_intensity

		# Sine wave based shake
		#
		# Play around with the magic numbers to adjust the feel
		#
		# Basing the sine wave off of get_ticks_msec ensures that
		# the returned value is continuous and smooth

		# Noise based shake
		#
		# Accessing the noise based on get_ticks_msec ensures that
		# the returned value is continuous and smooth
	if camera_shake_type == Type.Sine:
		# Sine wave based shake
		#
		# Play around with the magic numbers to adjust the feel
		#
		# Basing the sine wave off of get_ticks_msec ensures that
		# the returned value is continuous and smooth
		offset = (
			Vector2(sin(OS.get_ticks_msec() * 0.03), sin(OS.get_ticks_msec() * 0.07))
			* camera_shake_intensity
			* 0.5
		)

		# Noise based shake
		#
		# Accessing the noise based on get_ticks_msec ensures that
		# the returned value is continuous and smooth
	if camera_shake_type == Type.Noise:
		# Noise based shake
		#
		# Accessing the noise based on get_ticks_msec ensures that
		# the returned value is continuous and smooth
		var noise_value_x = noise.get_noise_1d(OS.get_ticks_msec() * 0.1)
		var noise_value_y = noise.get_noise_1d(OS.get_ticks_msec() * 0.1 + 100.0)
		offset = Vector2(noise_value_x, noise_value_y) * camera_shake_intensity * 2.0
	camera.offset = offset