generated from krampus/template-godot4
	Compare commits
	
		
			2 Commits
		
	
	
		
			b633ceb0c4
			...
			495e29c487
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 495e29c487 | |||
| f2a7b75e43 | 
| @ -57,6 +57,16 @@ Asset credits | |||||||
| 
 | 
 | ||||||
| *** Retrieved from https://github.com/AlphaZTX/Two-Weekends-Sans | *** Retrieved from https://github.com/AlphaZTX/Two-Weekends-Sans | ||||||
| 
 | 
 | ||||||
|  | *** Author: AlphaZTX | ||||||
|  | 
 | ||||||
|  | *** License: OFL 1.1 | ||||||
|  | 
 | ||||||
|  | ** CLASSIC Better VCR | ||||||
|  | 
 | ||||||
|  | *** Retrieved from https://fontstruct.com/fontstructions/show/2505236/classic-better-vcr | ||||||
|  | 
 | ||||||
|  | *** Author: Artdzyk | ||||||
|  | 
 | ||||||
| *** License: OFL 1.1 | *** License: OFL 1.1 | ||||||
| 
 | 
 | ||||||
| * Sound | * Sound | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								assets/fonts/classic-better-vcr/classic-better-vcr.otf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/fonts/classic-better-vcr/classic-better-vcr.otf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | [remap] | ||||||
|  | 
 | ||||||
|  | importer="font_data_dynamic" | ||||||
|  | type="FontFile" | ||||||
|  | uid="uid://dwy8k2w7vt64x" | ||||||
|  | path="res://.godot/imported/classic-better-vcr.otf-78a95e88b4c7ad31748ba0a4ef1b3b0b.fontdata" | ||||||
|  | 
 | ||||||
|  | [deps] | ||||||
|  | 
 | ||||||
|  | source_file="res://assets/fonts/classic-better-vcr/classic-better-vcr.otf" | ||||||
|  | dest_files=["res://.godot/imported/classic-better-vcr.otf-78a95e88b4c7ad31748ba0a4ef1b3b0b.fontdata"] | ||||||
|  | 
 | ||||||
|  | [params] | ||||||
|  | 
 | ||||||
|  | Rendering=null | ||||||
|  | antialiasing=1 | ||||||
|  | generate_mipmaps=false | ||||||
|  | disable_embedded_bitmaps=true | ||||||
|  | multichannel_signed_distance_field=false | ||||||
|  | msdf_pixel_range=8 | ||||||
|  | msdf_size=48 | ||||||
|  | allow_system_fallback=true | ||||||
|  | force_autohinter=false | ||||||
|  | hinting=1 | ||||||
|  | subpixel_positioning=1 | ||||||
|  | oversampling=0.0 | ||||||
|  | Fallbacks=null | ||||||
|  | fallbacks=[] | ||||||
|  | Compress=null | ||||||
|  | compress=true | ||||||
|  | preload=[] | ||||||
|  | language_support={} | ||||||
|  | script_support={} | ||||||
|  | opentype_features={} | ||||||
							
								
								
									
										93
									
								
								assets/fonts/classic-better-vcr/license.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								assets/fonts/classic-better-vcr/license.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,93 @@ | |||||||
|  | Copyright (c) 2024,  Artdzyk  | ||||||
|  | (https://fontstruct.com/fontstructors/2103201/siroutyugist) | ||||||
|  | 
 | ||||||
|  | This Font Software is licensed under the SIL Open Font License, Version 1.1. | ||||||
|  | This license is copied below, and is also available with a FAQ at: | ||||||
|  | http://scripts.sil.org/OFL | ||||||
|  | 
 | ||||||
|  | ----------------------------------------------------------- | ||||||
|  | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 | ||||||
|  | ----------------------------------------------------------- | ||||||
|  | 
 | ||||||
|  | PREAMBLE | ||||||
|  | The goals of the Open Font License (OFL) are to stimulate worldwide | ||||||
|  | development of collaborative font projects, to support the font creation | ||||||
|  | efforts of academic and linguistic communities, and to provide a free and | ||||||
|  | open framework in which fonts may be shared and improved in partnership | ||||||
|  | with others. | ||||||
|  | 
 | ||||||
|  | The OFL allows the licensed fonts to be used, studied, modified and | ||||||
|  | redistributed freely as long as they are not sold by themselves. The | ||||||
|  | fonts, including any derivative works, can be bundled, embedded,  | ||||||
|  | redistributed and/or sold with any software provided that any reserved | ||||||
|  | names are not used by derivative works. The fonts and derivatives, | ||||||
|  | however, cannot be released under any other type of license. The | ||||||
|  | requirement for fonts to remain under this license does not apply | ||||||
|  | to any document created using the fonts or their derivatives. | ||||||
|  | 
 | ||||||
|  | DEFINITIONS | ||||||
|  | "Font Software" refers to the set of files released by the Copyright | ||||||
|  | Holder(s) under this license and clearly marked as such. This may | ||||||
|  | include source files, build scripts and documentation. | ||||||
|  | 
 | ||||||
|  | "Reserved Font Name" refers to any names specified as such after the | ||||||
|  | copyright statement(s). | ||||||
|  | 
 | ||||||
|  | "Original Version" refers to the collection of Font Software components as | ||||||
|  | distributed by the Copyright Holder(s). | ||||||
|  | 
 | ||||||
|  | "Modified Version" refers to any derivative made by adding to, deleting, | ||||||
|  | or substituting -- in part or in whole -- any of the components of the | ||||||
|  | Original Version, by changing formats or by porting the Font Software to a | ||||||
|  | new environment. | ||||||
|  | 
 | ||||||
|  | "Author" refers to any designer, engineer, programmer, technical | ||||||
|  | writer or other person who contributed to the Font Software. | ||||||
|  | 
 | ||||||
|  | PERMISSION & CONDITIONS | ||||||
|  | Permission is hereby granted, free of charge, to any person obtaining | ||||||
|  | a copy of the Font Software, to use, study, copy, merge, embed, modify, | ||||||
|  | redistribute, and sell modified and unmodified copies of the Font | ||||||
|  | Software, subject to the following conditions: | ||||||
|  | 
 | ||||||
|  | 1) Neither the Font Software nor any of its individual components, | ||||||
|  | in Original or Modified Versions, may be sold by itself. | ||||||
|  | 
 | ||||||
|  | 2) Original or Modified Versions of the Font Software may be bundled, | ||||||
|  | redistributed and/or sold with any software, provided that each copy | ||||||
|  | contains the above copyright notice and this license. These can be | ||||||
|  | included either as stand-alone text files, human-readable headers or | ||||||
|  | in the appropriate machine-readable metadata fields within text or | ||||||
|  | binary files as long as those fields can be easily viewed by the user. | ||||||
|  | 
 | ||||||
|  | 3) No Modified Version of the Font Software may use the Reserved Font | ||||||
|  | Name(s) unless explicit written permission is granted by the corresponding | ||||||
|  | Copyright Holder. This restriction only applies to the primary font name as | ||||||
|  | presented to the users. | ||||||
|  | 
 | ||||||
|  | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font | ||||||
|  | Software shall not be used to promote, endorse or advertise any | ||||||
|  | Modified Version, except to acknowledge the contribution(s) of the | ||||||
|  | Copyright Holder(s) and the Author(s) or with their explicit written | ||||||
|  | permission. | ||||||
|  | 
 | ||||||
|  | 5) The Font Software, modified or unmodified, in part or in whole, | ||||||
|  | must be distributed entirely under this license, and must not be | ||||||
|  | distributed under any other license. The requirement for fonts to | ||||||
|  | remain under this license does not apply to any document created | ||||||
|  | using the Font Software. | ||||||
|  | 
 | ||||||
|  | TERMINATION | ||||||
|  | This license becomes null and void if any of the above conditions are | ||||||
|  | not met. | ||||||
|  | 
 | ||||||
|  | DISCLAIMER | ||||||
|  | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||||
|  | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF | ||||||
|  | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT | ||||||
|  | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE | ||||||
|  | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||||||
|  | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL | ||||||
|  | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||||||
|  | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM | ||||||
|  | OTHER DEALINGS IN THE FONT SOFTWARE. | ||||||
							
								
								
									
										22
									
								
								assets/fonts/classic-better-vcr/readme.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								assets/fonts/classic-better-vcr/readme.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | |||||||
|  | The font file in this archive was created using Fontstruct the free, online | ||||||
|  | font-building tool. | ||||||
|  | This font was created by Artdzyk *. | ||||||
|  | This font has a homepage where this archive and other versions may be found: | ||||||
|  | https://fontstruct.com/fontstructions/show/2505236 | ||||||
|  | 
 | ||||||
|  | *NOTE: “CLASSIC Better VCR” was originally cloned (copied) from the | ||||||
|  | FontStruction “12x16 iskra” | ||||||
|  | (https://fontstruct.com/fontstructions/show/2274822) by Artdzyk , which is | ||||||
|  | licensed under a Open Font License license | ||||||
|  | (https://fontstruct.com/fontstructions/license/2274822). | ||||||
|  | 
 | ||||||
|  | Try Fontstruct at https://fontstruct.com | ||||||
|  | It’s easy and it’s fun. | ||||||
|  | 
 | ||||||
|  | Fontstruct is copyright ©2024 Rob Meek | ||||||
|  | 
 | ||||||
|  | LEGAL NOTICE: | ||||||
|  | In using this font you must comply with the licensing terms described in the | ||||||
|  | file “license.txt” included with this archive. | ||||||
|  | If you redistribute the font file in this archive, it must be accompanied by all | ||||||
|  | the other files from this archive, including this one. | ||||||
| @ -124,6 +124,7 @@ ACTION_club_previous,"Select previous club" | |||||||
| ACTION_pause,Pause | ACTION_pause,Pause | ||||||
| ACTION_ball_next,"Select next ball" | ACTION_ball_next,"Select next ball" | ||||||
| ACTION_ball_previous,"Select previous ball" | ACTION_ball_previous,"Select previous ball" | ||||||
|  | ACTION_fast_forward,Fast-forward | ||||||
| , | , | ||||||
| ACTION_FREE_CAMERA,"Free Camera" | ACTION_FREE_CAMERA,"Free Camera" | ||||||
| ACTION_AIM,Aim | ACTION_AIM,Aim | ||||||
|  | |||||||
| 
 | 
| @ -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