generated from krampus/template-godot4
	Shot fast-forward control with VCR effect
This commit is contained in:
		
							parent
							
								
									f2a7b75e43
								
							
						
					
					
						commit
						495e29c487
					
				@ -187,12 +187,12 @@ select_putter={
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
club_next={
 | 
					club_next={
 | 
				
			||||||
"deadzone": 0.5,
 | 
					"deadzone": 0.5,
 | 
				
			||||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194306,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
 | 
					"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194306,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
club_previous={
 | 
					club_previous={
 | 
				
			||||||
"deadzone": 0.5,
 | 
					"deadzone": 0.5,
 | 
				
			||||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194306,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
 | 
					"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194306,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
ball_next={
 | 
					ball_next={
 | 
				
			||||||
@ -205,6 +205,11 @@ ball_previous={
 | 
				
			|||||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":71,"key_label":0,"unicode":71,"location":0,"echo":false,"script":null)
 | 
					"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":71,"key_label":0,"unicode":71,"location":0,"echo":false,"script":null)
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					fast_forward={
 | 
				
			||||||
 | 
					"deadzone": 0.5,
 | 
				
			||||||
 | 
					"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":70,"key_label":0,"unicode":102,"location":0,"echo":false,"script":null)
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
pause={
 | 
					pause={
 | 
				
			||||||
"deadzone": 0.5,
 | 
					"deadzone": 0.5,
 | 
				
			||||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
 | 
					"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
 | 
				
			||||||
 | 
				
			|||||||
@ -81,6 +81,8 @@ func _unload_content() -> void:
 | 
				
			|||||||
func _finish_scene_load(instance: Node) -> void:
 | 
					func _finish_scene_load(instance: Node) -> void:
 | 
				
			||||||
	# Unpause in case the previous scene was paused.
 | 
						# Unpause in case the previous scene was paused.
 | 
				
			||||||
	get_tree().paused = false
 | 
						get_tree().paused = false
 | 
				
			||||||
 | 
						# Reset time scale in case it's been changed.
 | 
				
			||||||
 | 
						Engine.time_scale = 1.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	content.add_child(instance)
 | 
						content.add_child(instance)
 | 
				
			||||||
	instance.reparent(content)
 | 
						instance.reparent(content)
 | 
				
			||||||
 | 
				
			|||||||
@ -21,6 +21,8 @@ var projection_gravity: bool
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var default_text_speed: float
 | 
					var default_text_speed: float
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var default_physics_ticks_per_second: int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func _init() -> void:
 | 
					func _init() -> void:
 | 
				
			||||||
	ProjectSettings.settings_changed.connect(_read_settings)
 | 
						ProjectSettings.settings_changed.connect(_read_settings)
 | 
				
			||||||
@ -54,6 +56,9 @@ func _read_settings() -> void:
 | 
				
			|||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default_text_speed = ProjectSettings.get_setting("game/config/text/default_text_speed")
 | 
						default_text_speed = ProjectSettings.get_setting("game/config/text/default_text_speed")
 | 
				
			||||||
 | 
						default_physics_ticks_per_second = ProjectSettings.get_setting(
 | 
				
			||||||
 | 
							"physics/common/physics_ticks_per_second"
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func _load_audio_bus_override() -> void:
 | 
					func _load_audio_bus_override() -> void:
 | 
				
			||||||
 | 
				
			|||||||
@ -485,6 +485,8 @@ func _on_phase_change(new_phase: Phase) -> void:
 | 
				
			|||||||
	idle_prompt_timer.start()
 | 
						idle_prompt_timer.start()
 | 
				
			||||||
	hud.hide_idle_prompts()
 | 
						hud.hide_idle_prompts()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						world.fast_forward = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	match new_phase:
 | 
						match new_phase:
 | 
				
			||||||
		Phase.AIM:
 | 
							Phase.AIM:
 | 
				
			||||||
			hud.show_hud()
 | 
								hud.show_hud()
 | 
				
			||||||
@ -660,6 +662,9 @@ func _process(_delta: float) -> void:
 | 
				
			|||||||
				hud.stop_curve_bar()
 | 
									hud.stop_curve_bar()
 | 
				
			||||||
				phase = Phase.DOWNSWING
 | 
									phase = Phase.DOWNSWING
 | 
				
			||||||
		Phase.SHOT:
 | 
							Phase.SHOT:
 | 
				
			||||||
 | 
								# Fast-forward when input is held:
 | 
				
			||||||
 | 
								world.fast_forward = Input.is_action_pressed("fast_forward", true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if reset_enabled and Input.is_action_just_pressed("shot_reset", true):
 | 
								if reset_enabled and Input.is_action_just_pressed("shot_reset", true):
 | 
				
			||||||
				phase = Phase.SHOT_RESET
 | 
									phase = Phase.SHOT_RESET
 | 
				
			||||||
				reset_enabled = false
 | 
									reset_enabled = false
 | 
				
			||||||
@ -750,3 +755,5 @@ func _on_idle_prompt_timer_timeout() -> void:
 | 
				
			|||||||
			hud.show_power_prompt()
 | 
								hud.show_power_prompt()
 | 
				
			||||||
		Phase.CURVE_ADJUST:
 | 
							Phase.CURVE_ADJUST:
 | 
				
			||||||
			hud.show_curve_prompt()
 | 
								hud.show_curve_prompt()
 | 
				
			||||||
 | 
							Phase.SHOT:
 | 
				
			||||||
 | 
								hud.show_shot_prompt()
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										108
									
								
								src/shaders/vcr_distortion.gdshader
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/shaders/vcr_distortion.gdshader
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,108 @@
 | 
				
			|||||||
 | 
					// https://www.shadertoy.com/view/MdffD7
 | 
				
			||||||
 | 
					// Fork of FMS_Cat's VCR distortion shader
 | 
				
			||||||
 | 
					// Retrieved from https://godotshaders.com/shader/vhs-post-processing/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shader_type canvas_item;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: Add uniforms for tape crease discoloration and image jiggle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uniform sampler2D screen_texture: hint_screen_texture, filter_linear_mipmap, repeat_disable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uniform vec2 vhs_resolution = vec2(320.0, 240.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uniform int samples = 2;
 | 
				
			||||||
 | 
					uniform float crease_noise: hint_range(0.0, 2.0, 0.1) = 1.0;
 | 
				
			||||||
 | 
					uniform float crease_opacity: hint_range(0.0, 1.0, 0.1) = 0.5;
 | 
				
			||||||
 | 
					uniform float filter_intensity: hint_range(0.0, 1.0, 0.1) = 0.1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					group_uniforms tape_crease;
 | 
				
			||||||
 | 
					uniform float tape_crease_smear: hint_range(0.0, 2.0, 0.1) = 0.2;
 | 
				
			||||||
 | 
					uniform float tape_crease_intensity: hint_range(0.0, 1.0, 0.1) = 0.2;
 | 
				
			||||||
 | 
					uniform float tape_crease_jitter: hint_range(0.0, 1.0, 0.01) = 0.10;
 | 
				
			||||||
 | 
					uniform float tape_crease_speed: hint_range(-2.0, 2.0, 0.1) = 0.5;
 | 
				
			||||||
 | 
					uniform float tape_crease_discoloration: hint_range(0.0, 2.0, 0.1) = 1.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					group_uniforms bottom_border;
 | 
				
			||||||
 | 
					uniform float bottom_border_thickness: hint_range(0.0,32.0, 0.1) = 6.0;
 | 
				
			||||||
 | 
					uniform float bottom_border_jitter: hint_range(0.0, 24.0, 0.5) = 6.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					group_uniforms noise;
 | 
				
			||||||
 | 
					uniform float noise_intensity: hint_range(0.0, 1.0, 0.1) = 0.1;
 | 
				
			||||||
 | 
					uniform sampler2D noise_texture: filter_linear_mipmap, repeat_enable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					float v2random(vec2 uv) {
 | 
				
			||||||
 | 
						return texture(noise_texture, mod(uv, vec2(1.0))).x;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mat2 rotate2D(float t) {
 | 
				
			||||||
 | 
						return mat2(vec2(cos(t), sin(t)), vec2(-sin(t), cos(t)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					vec3 rgb2yiq(vec3 rgb) {
 | 
				
			||||||
 | 
						return mat3(vec3(0.299, 0.596, 0.211), vec3(0.587, -0.274, -0.523), vec3(0.114, -0.322, 0.312)) * rgb;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					vec3 yiq2rgb(vec3 yiq) {
 | 
				
			||||||
 | 
						return mat3(vec3(1.0, 1.0, 1.0), vec3(0.956, -0.272, -1.106), vec3(0.621, -0.647, 1.703)) * yiq;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					vec3 vhx_tex_2D(sampler2D tex, vec2 uv, float rot) {
 | 
				
			||||||
 | 
						vec3 yiq = vec3(0.0);
 | 
				
			||||||
 | 
						for (int i = 0; i < samples; i++) {
 | 
				
			||||||
 | 
							yiq += rgb2yiq(texture(tex, uv - vec2(float(i), 0.0) / vhs_resolution).xyz) *
 | 
				
			||||||
 | 
									vec2(float(i), float(samples - 1 - i)).yxx / float(samples - 1)
 | 
				
			||||||
 | 
									/ float(samples) * 2.0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (rot != 0.0) {
 | 
				
			||||||
 | 
							yiq.yz *= rotate2D(rot * tape_crease_discoloration);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return yiq2rgb(yiq);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void fragment() {
 | 
				
			||||||
 | 
						vec2 uvn = UV;
 | 
				
			||||||
 | 
						vec3 col = vec3(0.0, 0.0, 0.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Tape wave.
 | 
				
			||||||
 | 
						uvn.x += (v2random(vec2(uvn.y / 10.0, TIME / 10.0) / 1.0) - 0.5) / vhs_resolution.x * 1.0;
 | 
				
			||||||
 | 
						uvn.x += (v2random(vec2(uvn.y, TIME * 10.0)) - 0.5) / vhs_resolution.x * 1.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// tape crease
 | 
				
			||||||
 | 
						float tc_phase = smoothstep(0.9, 0.96, sin(uvn.y * 8.0 - (TIME * tape_crease_speed + tape_crease_jitter * v2random(TIME * vec2(0.67, 0.59))) * PI * 1.2));
 | 
				
			||||||
 | 
						float tc_noise = smoothstep(0.3, 1.0, v2random(vec2(uvn.y * 4.77, TIME)));
 | 
				
			||||||
 | 
						float tc = tc_phase * tc_noise;
 | 
				
			||||||
 | 
						uvn.x = uvn.x - tc / vhs_resolution.x * 8.0 * tape_crease_smear;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// switching noise
 | 
				
			||||||
 | 
						float sn_phase = smoothstep(1.0 - bottom_border_thickness / vhs_resolution.y, 1.0, uvn.y);
 | 
				
			||||||
 | 
						uvn.x += sn_phase * (v2random(vec2(UV.y * 100.0, TIME * 10.0)) - 0.5) / vhs_resolution.x * bottom_border_jitter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// fetch
 | 
				
			||||||
 | 
						col = vhx_tex_2D(screen_texture, uvn, tc_phase * 0.2 + sn_phase * 2.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// crease noise
 | 
				
			||||||
 | 
						float cn = tc_noise * crease_noise * (0.7 * tc_phase * tape_crease_intensity + 0.3);
 | 
				
			||||||
 | 
						if (0.29 < cn) {
 | 
				
			||||||
 | 
							vec2 V = vec2(0.0, crease_opacity);
 | 
				
			||||||
 | 
							vec2 uvt = (uvn + V.yx * v2random(vec2(uvn.y, TIME))) * vec2(0.1, 1.0);
 | 
				
			||||||
 | 
							float n0 = v2random(uvt);
 | 
				
			||||||
 | 
							float n1 = v2random(uvt + V.yx / vhs_resolution.x);
 | 
				
			||||||
 | 
							if (n1 < n0) {
 | 
				
			||||||
 | 
								col = mix(col, 2.0 * V.yyy, pow(n0, 10.0));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ac beat
 | 
				
			||||||
 | 
						col *= 1.0 + 0.1 * smoothstep(0.4, 0.6, v2random(vec2(0.0, 0.1 * (UV.y + TIME * 0.2)) / 10.0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// color noise
 | 
				
			||||||
 | 
						col *= 1.0 - noise_intensity * 0.5 + noise_intensity * texture(noise_texture, mod(uvn * vec2(1.0, 1.0) + TIME * vec2(5.97, 4.45), vec2(1.0))).xyz;
 | 
				
			||||||
 | 
						col = clamp(col, 0.0, 1.0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// yiq
 | 
				
			||||||
 | 
						col = rgb2yiq(col);
 | 
				
			||||||
 | 
						col = vec3(0.9, 1.1, 1.5) * col + vec3(0.1, -0.1, 0.0) * filter_intensity;
 | 
				
			||||||
 | 
						col = yiq2rgb(col);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						COLOR = vec4(col, 1.0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -16,6 +16,7 @@ var _freeze_input := false
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func _ready() -> void:
 | 
					func _ready() -> void:
 | 
				
			||||||
	Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
 | 
						Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
 | 
				
			||||||
 | 
						Engine.time_scale = 1.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func _unhandled_key_input(event: InputEvent) -> void:
 | 
					func _unhandled_key_input(event: InputEvent) -> void:
 | 
				
			||||||
 | 
				
			|||||||
@ -17,6 +17,7 @@ var player: WorldPlayer
 | 
				
			|||||||
var _aim_prompt_shown := false
 | 
					var _aim_prompt_shown := false
 | 
				
			||||||
var _power_prompt_shown := false
 | 
					var _power_prompt_shown := false
 | 
				
			||||||
var _curve_prompt_shown := false
 | 
					var _curve_prompt_shown := false
 | 
				
			||||||
 | 
					var _shot_prompt_shown := false
 | 
				
			||||||
var _free_cam_prompts_shown := false
 | 
					var _free_cam_prompts_shown := false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@onready var power_bar: TextureProgressBar = %PowerBar
 | 
					@onready var power_bar: TextureProgressBar = %PowerBar
 | 
				
			||||||
@ -45,6 +46,7 @@ var _free_cam_prompts_shown := false
 | 
				
			|||||||
@onready var _aim_prompt_animation: AnimationPlayer = %AimPromptAnimation
 | 
					@onready var _aim_prompt_animation: AnimationPlayer = %AimPromptAnimation
 | 
				
			||||||
@onready var _power_prompt_animation: AnimationPlayer = %PowerPromptAnimation
 | 
					@onready var _power_prompt_animation: AnimationPlayer = %PowerPromptAnimation
 | 
				
			||||||
@onready var _curve_prompt_animation: AnimationPlayer = %CurvePromptAnimation
 | 
					@onready var _curve_prompt_animation: AnimationPlayer = %CurvePromptAnimation
 | 
				
			||||||
 | 
					@onready var _shot_prompt_animation: AnimationPlayer = %ShotPromptAnimation
 | 
				
			||||||
@onready var _free_cam_util_prompt_animation: AnimationPlayer = %FreeCamUtilPromptAnimation
 | 
					@onready var _free_cam_util_prompt_animation: AnimationPlayer = %FreeCamUtilPromptAnimation
 | 
				
			||||||
@onready var _free_cam_motion_prompt_animation: AnimationPlayer = %FreeCamMotionPromptAnimation
 | 
					@onready var _free_cam_motion_prompt_animation: AnimationPlayer = %FreeCamMotionPromptAnimation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -181,10 +183,23 @@ func hide_free_cam_prompts() -> void:
 | 
				
			|||||||
		_free_cam_util_prompt_animation.play_backwards("show")
 | 
							_free_cam_util_prompt_animation.play_backwards("show")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func show_shot_prompt() -> void:
 | 
				
			||||||
 | 
						if not _shot_prompt_shown:
 | 
				
			||||||
 | 
							_shot_prompt_shown = true
 | 
				
			||||||
 | 
							_shot_prompt_animation.play("show")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func hide_shot_prompt() -> void:
 | 
				
			||||||
 | 
						if _shot_prompt_shown:
 | 
				
			||||||
 | 
							_shot_prompt_shown = false
 | 
				
			||||||
 | 
							_shot_prompt_animation.play_backwards("show")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func hide_idle_prompts() -> void:
 | 
					func hide_idle_prompts() -> void:
 | 
				
			||||||
	hide_aim_prompt()
 | 
						hide_aim_prompt()
 | 
				
			||||||
	hide_power_prompt()
 | 
						hide_power_prompt()
 | 
				
			||||||
	hide_curve_prompt()
 | 
						hide_curve_prompt()
 | 
				
			||||||
 | 
						hide_shot_prompt()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Set the value of the life bar, potentially playing some kind of effect in response.
 | 
					## Set the value of the life bar, potentially playing some kind of effect in response.
 | 
				
			||||||
 | 
				
			|||||||
@ -1242,6 +1242,30 @@ libraries = {
 | 
				
			|||||||
"": SubResource("AnimationLibrary_o70c6")
 | 
					"": SubResource("AnimationLibrary_o70c6")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[node name="ShotPrompt" type="MarginContainer" parent="Prompts"]
 | 
				
			||||||
 | 
					layout_mode = 1
 | 
				
			||||||
 | 
					anchors_preset = -1
 | 
				
			||||||
 | 
					anchor_left = 0.5
 | 
				
			||||||
 | 
					anchor_top = 1.0
 | 
				
			||||||
 | 
					anchor_right = 0.5
 | 
				
			||||||
 | 
					anchor_bottom = 1.0
 | 
				
			||||||
 | 
					offset_bottom = 55.0
 | 
				
			||||||
 | 
					grow_horizontal = 2
 | 
				
			||||||
 | 
					grow_vertical = 0
 | 
				
			||||||
 | 
					theme_override_constants/margin_right = 16
 | 
				
			||||||
 | 
					theme_override_constants/margin_bottom = 16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[node name="InputPrompt" parent="Prompts/ShotPrompt" instance=ExtResource("14_ik4gg")]
 | 
				
			||||||
 | 
					layout_mode = 2
 | 
				
			||||||
 | 
					text = "❓ - ACTION_fast_forward"
 | 
				
			||||||
 | 
					action = &"fast_forward"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[node name="ShotPromptAnimation" type="AnimationPlayer" parent="Prompts/ShotPrompt"]
 | 
				
			||||||
 | 
					unique_name_in_owner = true
 | 
				
			||||||
 | 
					libraries = {
 | 
				
			||||||
 | 
					"": SubResource("AnimationLibrary_o70c6")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[node name="FreeCamUtilPrompts" type="MarginContainer" parent="Prompts"]
 | 
					[node name="FreeCamUtilPrompts" type="MarginContainer" parent="Prompts"]
 | 
				
			||||||
layout_mode = 1
 | 
					layout_mode = 1
 | 
				
			||||||
anchors_preset = -1
 | 
					anchors_preset = -1
 | 
				
			||||||
 | 
				
			|||||||
@ -52,6 +52,9 @@ func _finish_winner_sequence() -> void:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func pause() -> void:
 | 
					func pause() -> void:
 | 
				
			||||||
 | 
						# Turn off fast-forward, if it's on
 | 
				
			||||||
 | 
						world.fast_forward = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Switch to demo cam, if there is one.
 | 
						# Switch to demo cam, if there is one.
 | 
				
			||||||
	var democams: Array[Node] = get_tree().get_nodes_in_group(DEMO_CAMERA_GROUP)
 | 
						var democams: Array[Node] = get_tree().get_nodes_in_group(DEMO_CAMERA_GROUP)
 | 
				
			||||||
	if democams:
 | 
						if democams:
 | 
				
			||||||
 | 
				
			|||||||
@ -6,18 +6,23 @@ class_name World extends Node
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const SCENE := "res://src/world/world.tscn"
 | 
					const SCENE := "res://src/world/world.tscn"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const FF_TIME_SCALE := 4.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@export var initial_level: PackedScene
 | 
					@export var initial_level: PackedScene
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@export var manager: PlayManager
 | 
					@export var manager: PlayManager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@export var spawn_group := "PlayerSpawn"
 | 
					@export var spawn_group := "PlayerSpawn"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var fast_forward: bool:
 | 
				
			||||||
 | 
						set = _set_fast_forward
 | 
				
			||||||
var _spawns_available: Array[Node3D] = []
 | 
					var _spawns_available: Array[Node3D] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@onready var level: Node3D = %Level
 | 
					@onready var level: Node3D = %Level
 | 
				
			||||||
@onready var ui: WorldUI = %UI
 | 
					@onready var ui: WorldUI = %UI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@onready var world_transition: AnimationPlayer = %WorldTransition
 | 
					@onready var world_transition: AnimationPlayer = %WorldTransition
 | 
				
			||||||
 | 
					@onready var fast_forward_effect: Control = %FastForwardEffect
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@onready var game: Game = get_tree().get_first_node_in_group(Game.group)
 | 
					@onready var game: Game = get_tree().get_first_node_in_group(Game.group)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -62,6 +67,26 @@ func _on_winner(_player: WorldPlayer) -> void:
 | 
				
			|||||||
	# TODO announce winner?
 | 
						# TODO announce winner?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Set the state of the world-wide fast-forward feature
 | 
				
			||||||
 | 
					func _set_fast_forward(value: bool) -> void:
 | 
				
			||||||
 | 
						if value == fast_forward:
 | 
				
			||||||
 | 
							# Ignore if not a change from the previous value
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fast_forward = value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if fast_forward:
 | 
				
			||||||
 | 
							Engine.time_scale = FF_TIME_SCALE
 | 
				
			||||||
 | 
							Engine.physics_ticks_per_second = int(
 | 
				
			||||||
 | 
								Game.settings.default_physics_ticks_per_second * FF_TIME_SCALE
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
							fast_forward_effect.show()
 | 
				
			||||||
 | 
						else:
 | 
				
			||||||
 | 
							Engine.time_scale = 1.0
 | 
				
			||||||
 | 
							Engine.physics_ticks_per_second = Game.settings.default_physics_ticks_per_second
 | 
				
			||||||
 | 
							fast_forward_effect.hide()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func fade_to_title() -> void:
 | 
					func fade_to_title() -> void:
 | 
				
			||||||
	world_transition.play("fade_to_title")
 | 
						world_transition.play("fade_to_title")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
[gd_scene load_steps=16 format=3 uid="uid://cwnwcd8kushl3"]
 | 
					[gd_scene load_steps=24 format=3 uid="uid://cwnwcd8kushl3"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[ext_resource type="Script" path="res://src/world/world.gd" id="1_ybjyx"]
 | 
					[ext_resource type="Script" path="res://src/world/world.gd" id="1_ybjyx"]
 | 
				
			||||||
[ext_resource type="Script" path="res://src/player/world_player.gd" id="2_e743i"]
 | 
					[ext_resource type="Script" path="res://src/player/world_player.gd" id="2_e743i"]
 | 
				
			||||||
@ -10,6 +10,8 @@
 | 
				
			|||||||
[ext_resource type="PackedScene" uid="uid://byvjsvavbg5xe" path="res://src/ui/menus/pause_menu/pause_menu.tscn" id="7_0gd42"]
 | 
					[ext_resource type="PackedScene" uid="uid://byvjsvavbg5xe" path="res://src/ui/menus/pause_menu/pause_menu.tscn" id="7_0gd42"]
 | 
				
			||||||
[ext_resource type="PackedScene" uid="uid://biokiug3e0ipk" path="res://src/ui/shot_hud/death_alert.tscn" id="8_fuyxc"]
 | 
					[ext_resource type="PackedScene" uid="uid://biokiug3e0ipk" path="res://src/ui/shot_hud/death_alert.tscn" id="8_fuyxc"]
 | 
				
			||||||
[ext_resource type="PackedScene" uid="uid://dwyy7tt3nose1" path="res://src/ui/shot_hud/winner_alert.tscn" id="9_lln1k"]
 | 
					[ext_resource type="PackedScene" uid="uid://dwyy7tt3nose1" path="res://src/ui/shot_hud/winner_alert.tscn" id="9_lln1k"]
 | 
				
			||||||
 | 
					[ext_resource type="FontFile" uid="uid://dwy8k2w7vt64x" path="res://assets/fonts/classic-better-vcr/classic-better-vcr.otf" id="11_uv5b5"]
 | 
				
			||||||
 | 
					[ext_resource type="Shader" path="res://src/shaders/vcr_distortion.gdshader" id="11_xag32"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[sub_resource type="Resource" id="Resource_mbhdy"]
 | 
					[sub_resource type="Resource" id="Resource_mbhdy"]
 | 
				
			||||||
script = ExtResource("2_e743i")
 | 
					script = ExtResource("2_e743i")
 | 
				
			||||||
@ -26,6 +28,68 @@ _balls = {
 | 
				
			|||||||
script = ExtResource("5_h6mje")
 | 
					script = ExtResource("5_h6mje")
 | 
				
			||||||
players = Array[ExtResource("2_e743i")]([ExtResource("3_pyw81"), SubResource("Resource_mbhdy")])
 | 
					players = Array[ExtResource("2_e743i")]([ExtResource("3_pyw81"), SubResource("Resource_mbhdy")])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[sub_resource type="Animation" id="Animation_xfpfm"]
 | 
				
			||||||
 | 
					resource_name = "blink"
 | 
				
			||||||
 | 
					loop_mode = 1
 | 
				
			||||||
 | 
					tracks/0/type = "value"
 | 
				
			||||||
 | 
					tracks/0/imported = false
 | 
				
			||||||
 | 
					tracks/0/enabled = true
 | 
				
			||||||
 | 
					tracks/0/path = NodePath(".:visible")
 | 
				
			||||||
 | 
					tracks/0/interp = 1
 | 
				
			||||||
 | 
					tracks/0/loop_wrap = true
 | 
				
			||||||
 | 
					tracks/0/keys = {
 | 
				
			||||||
 | 
					"times": PackedFloat32Array(0, 0.5),
 | 
				
			||||||
 | 
					"transitions": PackedFloat32Array(1, 1),
 | 
				
			||||||
 | 
					"update": 1,
 | 
				
			||||||
 | 
					"values": [true, false]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[sub_resource type="Animation" id="Animation_6350f"]
 | 
				
			||||||
 | 
					length = 0.001
 | 
				
			||||||
 | 
					tracks/0/type = "value"
 | 
				
			||||||
 | 
					tracks/0/imported = false
 | 
				
			||||||
 | 
					tracks/0/enabled = true
 | 
				
			||||||
 | 
					tracks/0/path = NodePath(".:visible")
 | 
				
			||||||
 | 
					tracks/0/interp = 1
 | 
				
			||||||
 | 
					tracks/0/loop_wrap = true
 | 
				
			||||||
 | 
					tracks/0/keys = {
 | 
				
			||||||
 | 
					"times": PackedFloat32Array(0),
 | 
				
			||||||
 | 
					"transitions": PackedFloat32Array(1),
 | 
				
			||||||
 | 
					"update": 1,
 | 
				
			||||||
 | 
					"values": [true]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[sub_resource type="AnimationLibrary" id="AnimationLibrary_7gn8c"]
 | 
				
			||||||
 | 
					_data = {
 | 
				
			||||||
 | 
					"RESET": SubResource("Animation_6350f"),
 | 
				
			||||||
 | 
					"blink": SubResource("Animation_xfpfm")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[sub_resource type="FastNoiseLite" id="FastNoiseLite_txttc"]
 | 
				
			||||||
 | 
					noise_type = 5
 | 
				
			||||||
 | 
					frequency = 1.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_p8oo3"]
 | 
				
			||||||
 | 
					seamless = true
 | 
				
			||||||
 | 
					noise = SubResource("FastNoiseLite_txttc")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[sub_resource type="ShaderMaterial" id="ShaderMaterial_m76ua"]
 | 
				
			||||||
 | 
					shader = ExtResource("11_xag32")
 | 
				
			||||||
 | 
					shader_parameter/vhs_resolution = Vector2(320, 240)
 | 
				
			||||||
 | 
					shader_parameter/samples = 3
 | 
				
			||||||
 | 
					shader_parameter/crease_noise = 1.4
 | 
				
			||||||
 | 
					shader_parameter/crease_opacity = 0.5
 | 
				
			||||||
 | 
					shader_parameter/filter_intensity = 0.2
 | 
				
			||||||
 | 
					shader_parameter/tape_crease_smear = 0.2
 | 
				
			||||||
 | 
					shader_parameter/tape_crease_intensity = 0.2
 | 
				
			||||||
 | 
					shader_parameter/tape_crease_jitter = 0.21
 | 
				
			||||||
 | 
					shader_parameter/tape_crease_speed = 0.5
 | 
				
			||||||
 | 
					shader_parameter/tape_crease_discoloration = 1.0
 | 
				
			||||||
 | 
					shader_parameter/bottom_border_thickness = 6.0
 | 
				
			||||||
 | 
					shader_parameter/bottom_border_jitter = 6.0
 | 
				
			||||||
 | 
					shader_parameter/noise_intensity = 0.2
 | 
				
			||||||
 | 
					shader_parameter/noise_texture = SubResource("NoiseTexture2D_p8oo3")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[sub_resource type="Animation" id="Animation_ihq1m"]
 | 
					[sub_resource type="Animation" id="Animation_ihq1m"]
 | 
				
			||||||
length = 0.001
 | 
					length = 0.001
 | 
				
			||||||
tracks/0/type = "value"
 | 
					tracks/0/type = "value"
 | 
				
			||||||
@ -143,6 +207,55 @@ grow_horizontal = 2
 | 
				
			|||||||
grow_vertical = 2
 | 
					grow_vertical = 2
 | 
				
			||||||
mouse_filter = 2
 | 
					mouse_filter = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[node name="FastForwardEffect" type="Control" parent="UI/EffectContainer"]
 | 
				
			||||||
 | 
					unique_name_in_owner = true
 | 
				
			||||||
 | 
					visible = false
 | 
				
			||||||
 | 
					layout_mode = 1
 | 
				
			||||||
 | 
					anchors_preset = 15
 | 
				
			||||||
 | 
					anchor_right = 1.0
 | 
				
			||||||
 | 
					anchor_bottom = 1.0
 | 
				
			||||||
 | 
					grow_horizontal = 2
 | 
				
			||||||
 | 
					grow_vertical = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[node name="MarginContainer" type="MarginContainer" parent="UI/EffectContainer/FastForwardEffect"]
 | 
				
			||||||
 | 
					layout_mode = 0
 | 
				
			||||||
 | 
					offset_right = 176.0
 | 
				
			||||||
 | 
					offset_bottom = 96.0
 | 
				
			||||||
 | 
					theme_override_constants/margin_left = 128
 | 
				
			||||||
 | 
					theme_override_constants/margin_top = 128
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[node name="HBoxContainer" type="HBoxContainer" parent="UI/EffectContainer/FastForwardEffect/MarginContainer"]
 | 
				
			||||||
 | 
					layout_mode = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[node name="Label" type="Label" parent="UI/EffectContainer/FastForwardEffect/MarginContainer/HBoxContainer"]
 | 
				
			||||||
 | 
					layout_mode = 2
 | 
				
			||||||
 | 
					theme_override_fonts/font = ExtResource("11_uv5b5")
 | 
				
			||||||
 | 
					theme_override_font_sizes/font_size = 96
 | 
				
			||||||
 | 
					text = "FF"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[node name="Label2" type="Label" parent="UI/EffectContainer/FastForwardEffect/MarginContainer/HBoxContainer"]
 | 
				
			||||||
 | 
					layout_mode = 2
 | 
				
			||||||
 | 
					theme_override_fonts/font = ExtResource("11_uv5b5")
 | 
				
			||||||
 | 
					theme_override_font_sizes/font_size = 128
 | 
				
			||||||
 | 
					text = "⏩"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[node name="AnimationPlayer" type="AnimationPlayer" parent="UI/EffectContainer/FastForwardEffect/MarginContainer/HBoxContainer"]
 | 
				
			||||||
 | 
					libraries = {
 | 
				
			||||||
 | 
					"": SubResource("AnimationLibrary_7gn8c")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					autoplay = "blink"
 | 
				
			||||||
 | 
					speed_scale = 0.25
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[node name="Overlay" type="ColorRect" parent="UI/EffectContainer/FastForwardEffect"]
 | 
				
			||||||
 | 
					material = SubResource("ShaderMaterial_m76ua")
 | 
				
			||||||
 | 
					layout_mode = 1
 | 
				
			||||||
 | 
					anchors_preset = 15
 | 
				
			||||||
 | 
					anchor_right = 1.0
 | 
				
			||||||
 | 
					anchor_bottom = 1.0
 | 
				
			||||||
 | 
					grow_horizontal = 2
 | 
				
			||||||
 | 
					grow_vertical = 2
 | 
				
			||||||
 | 
					mouse_filter = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[node name="PauseContainer" type="Control" parent="UI"]
 | 
					[node name="PauseContainer" type="Control" parent="UI"]
 | 
				
			||||||
unique_name_in_owner = true
 | 
					unique_name_in_owner = true
 | 
				
			||||||
layout_mode = 1
 | 
					layout_mode = 1
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user