# Demo of camera shake
# Hold space to shake and release to stop
class ScreenShake
attr_gtk
def tick
defaults
calc_camera
outputs.labels << { x: 600, y: 400, text: "Hold Space!" }
# Add outputs to :scene
outputs[:scene].transient!
outputs[:scene].sprites << { x: 100, y: 100, w: 80, h: 80, path: 'sprites/square/blue.png' }
outputs[:scene].sprites << { x: 200, y: 300.from_top, w: 80, h: 80, path: 'sprites/square/blue.png' }
outputs[:scene].sprites << { x: 900, y: 200, w: 80, h: 80, path: 'sprites/square/blue.png' }
# Describe how to render :scene
outputs.sprites << { x: 0 - state.camera.x_offset,
y: 0 - state.camera.y_offset,
w: 1280,
h: 720,
angle: state.camera.angle,
path: :scene }
end
def defaults
state.camera.trauma ||= 0
state.camera.angle ||= 0
state.camera.x_offset ||= 0
state.camera.y_offset ||= 0
end
def calc_camera
if inputs.keyboard.key_held.space
state.camera.trauma += 0.02
end
next_camera_angle = 180.0 / 20.0 * state.camera.trauma**2
next_offset = 100.0 * state.camera.trauma**2
# Ensure that the camera angle always switches from
# positive to negative and vice versa
# which gives the effect of shaking back and forth
state.camera.angle = state.camera.angle > 0 ?
next_camera_angle * -1 :
next_camera_angle
state.camera.x_offset = next_offset.randomize(:sign, :ratio)
state.camera.y_offset = next_offset.randomize(:sign, :ratio)
# Gracefully degrade trauma
state.camera.trauma *= 0.95
end
end
def tick args
$screen_shake ||= ScreenShake.new
$screen_shake.args = args
$screen_shake.tick
end