init
This commit is contained in:
commit
b99855351d
434 changed files with 50357 additions and 0 deletions
65
scripts/audio_manager.gd
Normal file
65
scripts/audio_manager.gd
Normal file
|
@ -0,0 +1,65 @@
|
|||
extends Node
|
||||
|
||||
@export var audio_player: AudioStreamPlayer
|
||||
|
||||
@export var audio1: AudioStream
|
||||
@export var audio2l: AudioStream
|
||||
@export var audio3: AudioStream
|
||||
@export var audio4l: AudioStream
|
||||
@export var audio5: AudioStream
|
||||
@export var audio6: AudioStream
|
||||
@export var audio7l: AudioStream
|
||||
@export var audio8: AudioStream
|
||||
|
||||
var characters_talked_to: int = 0
|
||||
var ending: bool = false
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
_play(audio1)
|
||||
DialogueManager.dialogue_finished.connect(_quit_dialogue)
|
||||
|
||||
func _play(audio_source: AudioStream):
|
||||
audio_player.stream = audio_source
|
||||
audio_player.play()
|
||||
|
||||
|
||||
func _on_audio_stream_player_finished():
|
||||
match audio_player.stream:
|
||||
audio1:
|
||||
if characters_talked_to > 0:
|
||||
_play(audio3)
|
||||
else:
|
||||
_play(audio2l)
|
||||
audio2l:
|
||||
if characters_talked_to > 0:
|
||||
_play(audio3)
|
||||
else:
|
||||
_play(audio2l)
|
||||
audio3:
|
||||
if characters_talked_to > 1:
|
||||
_play(audio3)
|
||||
else:
|
||||
_play(audio4l)
|
||||
audio4l:
|
||||
if characters_talked_to > 3:
|
||||
_play(audio5)
|
||||
else:
|
||||
_play(audio4l)
|
||||
audio5:
|
||||
_play(audio6)
|
||||
audio6:
|
||||
_play(audio7l)
|
||||
audio7l:
|
||||
if ending:
|
||||
_play(audio8)
|
||||
else:
|
||||
_play(audio7l)
|
||||
|
||||
func _quit_dialogue(_time_to_add: int):
|
||||
characters_talked_to = (
|
||||
int(DialogueManager.global_variables["Character1"]) +
|
||||
int(DialogueManager.global_variables["Character2"]) +
|
||||
int(DialogueManager.global_variables["Character3"]) +
|
||||
int(DialogueManager.global_variables["Character4"])
|
||||
)
|
20
scripts/counter.gd
Normal file
20
scripts/counter.gd
Normal file
|
@ -0,0 +1,20 @@
|
|||
extends Control
|
||||
|
||||
const MAX_TIME = 99
|
||||
|
||||
@export var start_time = 50
|
||||
@export var decrease_speed = 0.5
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
current_time = start_time;
|
||||
$Label.text = str(int(current_time))
|
||||
|
||||
var current_time: float
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta):
|
||||
current_time -= decrease_speed * delta
|
||||
$Label.text = str(int(current_time))
|
||||
|
||||
func get_percentage() -> float:
|
||||
return inverse_lerp(MAX_TIME, 0, int(current_time))
|
133
scripts/dialogue/ink_handler.gd
Normal file
133
scripts/dialogue/ink_handler.gd
Normal file
|
@ -0,0 +1,133 @@
|
|||
extends Control
|
||||
|
||||
var inkPlayer = load("res://addons/inkgd/ink_player.gd")
|
||||
|
||||
@onready var _ink_player = InkPlayer.new()
|
||||
|
||||
@onready var text_box = $ColorRect/Label
|
||||
|
||||
@export var buttons: Array[Button]
|
||||
@export var type_sounds: Array[AudioStream]
|
||||
|
||||
var displaying_choices = false
|
||||
var active = false
|
||||
|
||||
@onready var timer = $TextDisplayTimer
|
||||
|
||||
var text = ""
|
||||
var character_index = 0
|
||||
|
||||
var character_time = 0.03
|
||||
|
||||
var finished_displaying = true
|
||||
|
||||
var variables: Dictionary
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
_ink_player._add_runtime(get_tree().root)
|
||||
_ink_player.loads_in_background = true
|
||||
_ink_player.connect("loaded", _story_loaded)
|
||||
|
||||
for button in buttons:
|
||||
button.hide()
|
||||
|
||||
func _setup_story(story: Resource):
|
||||
_ink_player.ink_file = story
|
||||
_ink_player.create_story()
|
||||
active = true
|
||||
|
||||
func _process(delta):
|
||||
if displaying_choices:
|
||||
var i = 0
|
||||
for button in buttons:
|
||||
if button.button_pressed:
|
||||
_select_choice(i)
|
||||
i += 1
|
||||
else:
|
||||
if Input.is_action_just_pressed("advance_dialog"):
|
||||
_continue_story()
|
||||
|
||||
func _story_loaded(successfully: bool):
|
||||
if !successfully:
|
||||
return
|
||||
|
||||
for key in variables:
|
||||
var value = variables[key]
|
||||
_ink_player.set_variable(key, value)
|
||||
_continue_story()
|
||||
|
||||
func _continue_story():
|
||||
if !finished_displaying:
|
||||
return
|
||||
if !_ink_player.can_continue and !_ink_player.has_choices:
|
||||
text_box.text = ""
|
||||
#TODO: Hardcodear las variables aquí
|
||||
variables["time_to_add"] = _ink_player.get_variable("time_to_add")
|
||||
variables["Foto1"] = _ink_player.get_variable("Foto1")
|
||||
variables["Foto2"] = _ink_player.get_variable("Foto2")
|
||||
variables["Foto3"] = _ink_player.get_variable("Foto3")
|
||||
variables["Foto4"] = _ink_player.get_variable("Foto4")
|
||||
variables["Foto5"] = _ink_player.get_variable("Foto5")
|
||||
variables["Character1"] = _ink_player.get_variable("Character1")
|
||||
variables["Character2"] = _ink_player.get_variable("Character2")
|
||||
variables["Character3"] = _ink_player.get_variable("Character3")
|
||||
variables["Character4"] = _ink_player.get_variable("Character4")
|
||||
variables["Character5"] = _ink_player.get_variable("Character5")
|
||||
|
||||
#DIALOGUE END
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
||||
active = false
|
||||
return
|
||||
|
||||
if _ink_player.has_choices:
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
|
||||
var i = 0
|
||||
for choice in _ink_player.current_choices:
|
||||
buttons[i].show()
|
||||
buttons[i].text = choice.text
|
||||
i += 1
|
||||
for j in range(4 - i):
|
||||
buttons[j + i].hide()
|
||||
displaying_choices = true
|
||||
return
|
||||
|
||||
text_box.text = ""
|
||||
display_text(_ink_player.continue_story())
|
||||
|
||||
|
||||
func _select_choice(index):
|
||||
for button in buttons:
|
||||
button.hide()
|
||||
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
||||
|
||||
_ink_player.choose_choice_index(index)
|
||||
_continue_story()
|
||||
|
||||
################## ANIMATIONS ###################
|
||||
|
||||
func display_text(text_to_display: String):
|
||||
text = text_to_display
|
||||
character_index = 0
|
||||
finished_displaying = false
|
||||
|
||||
_display_letter()
|
||||
|
||||
func _display_letter():
|
||||
if character_index >= text.length():
|
||||
finished_displaying = true
|
||||
return
|
||||
text_box.text += text[character_index]
|
||||
|
||||
character_index += 1
|
||||
$AudioStreamPlayer.stream = type_sounds.pick_random()
|
||||
$AudioStreamPlayer.play()
|
||||
if character_index >= text.length():
|
||||
finished_displaying = true
|
||||
return
|
||||
|
||||
timer.start(character_time)
|
||||
|
||||
func _on_text_display_timer_timeout():
|
||||
_display_letter()
|
9
scripts/main_menu.gd
Normal file
9
scripts/main_menu.gd
Normal file
|
@ -0,0 +1,9 @@
|
|||
extends Control
|
||||
|
||||
@export var player: CharacterBody3D
|
||||
@export var eyes: Node2D
|
||||
|
||||
func _on_button_button_down():
|
||||
player.enable()
|
||||
eyes.enable()
|
||||
queue_free()
|
23
scripts/npc/npc.gd
Normal file
23
scripts/npc/npc.gd
Normal file
|
@ -0,0 +1,23 @@
|
|||
extends CharacterBody3D
|
||||
|
||||
@export var text: Resource
|
||||
var moving: bool
|
||||
|
||||
func animate_move():
|
||||
$Model/AnimationPlayer.play("walk")
|
||||
|
||||
func animate_idle():
|
||||
$Model/AnimationPlayer.play("idle")
|
||||
|
||||
# Dummy function to avoid having to distinct npc from pickup
|
||||
func pointing(point: bool): pass
|
||||
func destroy(): pass
|
||||
|
||||
func get_text() -> Resource:
|
||||
if moving:
|
||||
return null
|
||||
else:
|
||||
return text
|
||||
|
||||
func is_photo() -> bool:
|
||||
return false
|
29
scripts/npc/npc_path_follow.gd
Normal file
29
scripts/npc/npc_path_follow.gd
Normal file
|
@ -0,0 +1,29 @@
|
|||
extends Path3D
|
||||
|
||||
var can_move: bool
|
||||
@export var maxSpeed = 0.01
|
||||
|
||||
var pos = 0.0;
|
||||
@onready var character_body_3d = $PathFollow3D/CharacterBody3D
|
||||
|
||||
@export var character_id: String
|
||||
|
||||
func _ready():
|
||||
DialogueManager.dialogue_finished.connect(_quit_dialogue)
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta):
|
||||
var previous_pos = pos;
|
||||
character_body_3d.moving = can_move
|
||||
if can_move and pos < 1:
|
||||
pos += maxSpeed * delta
|
||||
|
||||
if previous_pos != pos:
|
||||
character_body_3d.animate_move()
|
||||
else:
|
||||
character_body_3d.animate_idle()
|
||||
|
||||
$PathFollow3D.progress_ratio = clamp(pos, 0, 1)
|
||||
|
||||
func _quit_dialogue(_time_to_add: int):
|
||||
can_move = !character_id.is_empty() && DialogueManager.global_variables[character_id];
|
21
scripts/npc/photo.gd
Normal file
21
scripts/npc/photo.gd
Normal file
|
@ -0,0 +1,21 @@
|
|||
extends Control
|
||||
|
||||
@export var photos: Array[Texture2D]
|
||||
@export var photo_sound: Array[AudioStream]
|
||||
@export var destroy_sound: AudioStream
|
||||
|
||||
var is_visible = false
|
||||
|
||||
func show_picture(index: int):
|
||||
is_visible = true
|
||||
$FotoTest.texture = photos[index]
|
||||
$AnimationPlayer.play("appear")
|
||||
$AudioStreamPlayer.stream = photo_sound.pick_random()
|
||||
$AudioStreamPlayer.play()
|
||||
|
||||
func hide_picture():
|
||||
if !is_visible: return
|
||||
$AnimationPlayer.play("disappear")
|
||||
is_visible = false
|
||||
$AudioStreamPlayer.stream = destroy_sound
|
||||
$AudioStreamPlayer.play()
|
27
scripts/npc/pickup.gd
Normal file
27
scripts/npc/pickup.gd
Normal file
|
@ -0,0 +1,27 @@
|
|||
extends CharacterBody3D
|
||||
|
||||
@export var text: Resource
|
||||
@export var photo_index: int = 0
|
||||
|
||||
@export var animation_payer: AnimationPlayer
|
||||
|
||||
func _ready():
|
||||
animation_payer.play("photo_hover")
|
||||
|
||||
func pointing(point: bool):
|
||||
if point:
|
||||
animation_payer.play("photo_point", 1)
|
||||
else:
|
||||
animation_payer.play("photo_hover", 1)
|
||||
|
||||
func get_text() -> Resource:
|
||||
return text;
|
||||
|
||||
func destroy():
|
||||
queue_free()
|
||||
|
||||
func is_photo():
|
||||
return true
|
||||
|
||||
func get_photo_index():
|
||||
return photo_index
|
93
scripts/player/eyes.gd
Normal file
93
scripts/player/eyes.gd
Normal file
|
@ -0,0 +1,93 @@
|
|||
extends Node2D
|
||||
|
||||
const UP_MAX_POS = -200
|
||||
const UP_MIN_POS = 100
|
||||
const DOWN_MAX_POS = 900
|
||||
const DOWN_MIN_POS = 600
|
||||
|
||||
const MAX_BLINK_VARIATION = 50
|
||||
|
||||
@export var eyeUp: Sprite2D
|
||||
var eyeUpPos = UP_MAX_POS
|
||||
|
||||
@export var eyeDown: Sprite2D
|
||||
var eyeDownPos = DOWN_MIN_POS
|
||||
|
||||
var progress: float
|
||||
|
||||
@export var counter_text: Label
|
||||
const MAX_TIME = 99
|
||||
|
||||
@export var start_time = 50
|
||||
@export var decrease_speed = 0.5
|
||||
var current_time: float
|
||||
|
||||
var timer_going = true
|
||||
|
||||
var enabled = false
|
||||
|
||||
@onready var cutscene = load("res://scenes/ending.tscn")
|
||||
|
||||
func _get_percentage() -> float:
|
||||
return inverse_lerp(MAX_TIME, 0, int(current_time))
|
||||
|
||||
func _quit_dialogue(time_to_add: int):
|
||||
current_time += (time_to_add * 2)
|
||||
current_time = clamp(current_time, 0, MAX_TIME)
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
DialogueManager.dialogue_finished.connect(_quit_dialogue)
|
||||
|
||||
current_time = start_time;
|
||||
counter_text.text = ""
|
||||
|
||||
progress = _get_percentage()
|
||||
|
||||
eyeUpPos = lerp(UP_MAX_POS, UP_MIN_POS, progress)
|
||||
eyeDownPos = lerp(DOWN_MAX_POS, DOWN_MIN_POS, progress)
|
||||
|
||||
func enable():
|
||||
counter_text.text = str(int(current_time))
|
||||
enabled = true
|
||||
|
||||
var time = 0.0
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta):
|
||||
time += delta
|
||||
|
||||
var pos_offset = _sine_operation(time)
|
||||
|
||||
_eye_pos_up(pos_offset)
|
||||
_eye_pos_down(pos_offset)
|
||||
|
||||
if !enabled:
|
||||
return
|
||||
current_time -= decrease_speed * delta * int(timer_going)
|
||||
counter_text.text = str(int(current_time))
|
||||
progress = _get_percentage()
|
||||
|
||||
eyeUpPos = lerp(UP_MAX_POS, UP_MIN_POS, progress)
|
||||
eyeDownPos = lerp(DOWN_MAX_POS, DOWN_MIN_POS, progress)
|
||||
|
||||
if current_time <= 0.5:
|
||||
SceneTransition.change_scene(cutscene)
|
||||
|
||||
#t: time g: gap o: offset
|
||||
func _sine_function(t: float, g: float, o: float) -> float:
|
||||
return sin(t*g+o)
|
||||
|
||||
func _sine_operation(t: float) -> float:
|
||||
return .25 * (
|
||||
_sine_function(t, 1, 4) +
|
||||
_sine_function(t, 2, 3) +
|
||||
_sine_function(t, 3, 2) +
|
||||
_sine_function(t, 4, 1)
|
||||
)
|
||||
|
||||
func _eye_pos_up(t: float):
|
||||
eyeUp.position.y = int(lerp(eyeUpPos - MAX_BLINK_VARIATION/2, eyeUpPos + MAX_BLINK_VARIATION/2, t) / 4.0) * 4
|
||||
|
||||
func _eye_pos_down(t: float):
|
||||
eyeDown.position.y = int(lerp(eyeDownPos + MAX_BLINK_VARIATION/2, eyeDownPos - MAX_BLINK_VARIATION/2, t) / 4.0) * 4
|
84
scripts/player/player.gd
Normal file
84
scripts/player/player.gd
Normal file
|
@ -0,0 +1,84 @@
|
|||
extends CharacterBody3D
|
||||
|
||||
|
||||
@export var SPEED = 5.0
|
||||
const MOUSE_SENSITIVITY_X = 0.3
|
||||
const MOUSE_SENSITIVITY_Y = 0.15
|
||||
|
||||
const MAX_ROTATION = 85.0
|
||||
var rotation_x = 0.0
|
||||
|
||||
var in_dialogue = false
|
||||
|
||||
@export var raycast: RayCast3D
|
||||
|
||||
@export var eyes: Node2D
|
||||
|
||||
@export var photo_preview: Control
|
||||
|
||||
# Get the gravity from the project settings to be synced with RigidBody nodes.
|
||||
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
|
||||
|
||||
var enabled = false
|
||||
|
||||
func enable():
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
||||
enabled = true
|
||||
|
||||
func _input(event):
|
||||
if !enabled || DialogueManager.is_dialog_active:
|
||||
return
|
||||
|
||||
if in_dialogue:
|
||||
photo_preview.hide_picture()
|
||||
eyes.timer_going = true
|
||||
in_dialogue = false
|
||||
|
||||
if event is InputEventMouseMotion:
|
||||
rotation_degrees.y -= MOUSE_SENSITIVITY_X * event.relative.x
|
||||
rotation_x -= MOUSE_SENSITIVITY_Y * event.relative.y
|
||||
rotation_x = clamp(rotation_x, -MAX_ROTATION, MAX_ROTATION)
|
||||
$Camera3D.rotation_degrees.x = rotation_x
|
||||
|
||||
var npc: CharacterBody3D
|
||||
func _process(delta):
|
||||
if !enabled:
|
||||
return
|
||||
if raycast.is_colliding():
|
||||
npc = raycast.get_collider()
|
||||
npc.pointing(true)
|
||||
if Input.is_action_just_pressed("interact"):
|
||||
DialogueManager.start_dialog(raycast.get_collider().get_text())
|
||||
|
||||
if raycast.get_collider().is_photo():
|
||||
photo_preview.show_picture(raycast.get_collider().get_photo_index())
|
||||
|
||||
raycast.get_collider().destroy()
|
||||
in_dialogue = true
|
||||
eyes.timer_going = false
|
||||
elif npc != null:
|
||||
npc.pointing(false)
|
||||
npc = null
|
||||
|
||||
func _physics_process(delta):
|
||||
if !enabled:
|
||||
return
|
||||
# Add the gravity.
|
||||
if not is_on_floor():
|
||||
velocity.y -= gravity * delta
|
||||
|
||||
# Get the input direction and handle the movement/deceleration.
|
||||
# As good practice, you should replace UI actions with custom gameplay actions.
|
||||
var input_dir = Input.get_vector("move_left", "move_right", "move_forwards", "move_backwards")
|
||||
var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
|
||||
if direction:
|
||||
velocity.x = direction.x * SPEED
|
||||
velocity.z = direction.z * SPEED
|
||||
else:
|
||||
velocity.x = move_toward(velocity.x, 0, SPEED)
|
||||
velocity.z = move_toward(velocity.z, 0, SPEED)
|
||||
|
||||
if DialogueManager.is_dialog_active:
|
||||
velocity = Vector3(0, velocity.y, 0)
|
||||
|
||||
move_and_slide()
|
BIN
scripts/shaders/Perlin_noise_example.png
(Stored with Git LFS)
Normal file
BIN
scripts/shaders/Perlin_noise_example.png
(Stored with Git LFS)
Normal file
Binary file not shown.
35
scripts/shaders/Perlin_noise_example.png.import
Normal file
35
scripts/shaders/Perlin_noise_example.png.import
Normal file
|
@ -0,0 +1,35 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cfux36pq3rp1p"
|
||||
path.s3tc="res://.godot/imported/Perlin_noise_example.png-1d87d1cb590d7ea007c419d3f3ff388b.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://scripts/shaders/Perlin_noise_example.png"
|
||||
dest_files=["res://.godot/imported/Perlin_noise_example.png-1d87d1cb590d7ea007c419d3f3ff388b.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
46
scripts/shaders/cloud.gdshader
Normal file
46
scripts/shaders/cloud.gdshader
Normal file
|
@ -0,0 +1,46 @@
|
|||
shader_type spatial;
|
||||
render_mode unshaded;
|
||||
|
||||
uniform sampler2D dissolve_texture : hint_default_transparent;
|
||||
uniform float threshold : hint_range(0,1);
|
||||
uniform vec3 color : source_color;
|
||||
uniform float alpha_add = 1;
|
||||
uniform float speed : hint_range(0, 0.01) = 0.005;
|
||||
|
||||
float fresnel(vec3 Normal, vec3 ViewDir, float Power){
|
||||
return pow((1.0 - clamp(dot(normalize(Normal), normalize(ViewDir)), 0, 1)), Power);
|
||||
}
|
||||
|
||||
float _fresnel(vec2 uv, float Power){
|
||||
return pow((clamp(sin(PI * uv.x) * sin(PI * uv.y), 0, 1)), Power);
|
||||
}
|
||||
|
||||
vec2 loop(vec2 vec){
|
||||
vec2 res = vec;
|
||||
vec2 floors = floor(res);
|
||||
res.x -= floor(res.x);
|
||||
res.y -= floor(res.y);
|
||||
if(int(floors.x) % 2 == 0){
|
||||
res.x = 1.0 - res.x;
|
||||
}
|
||||
if(int(floors.y) % 2 == 0){
|
||||
res.y = 1.0 - res.y;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void fragment(){
|
||||
vec4 noise_texture = texture(dissolve_texture, loop(UV + vec2(TIME, TIME) * speed));
|
||||
noise_texture *= texture(dissolve_texture, loop(UV + vec2(-TIME, -TIME) * speed)) / 0.5;
|
||||
noise_texture *= texture(dissolve_texture, loop(UV + vec2(TIME, -TIME) * speed)) / 0.5;
|
||||
noise_texture *= texture(dissolve_texture, loop(UV + vec2(-TIME, TIME) * speed)) / 0.5;
|
||||
noise_texture *= texture(dissolve_texture, loop(UV * 2.0 + vec2(-TIME, TIME) * speed * 0.3)) / 0.5;
|
||||
noise_texture *= texture(dissolve_texture, loop(UV * 2.0 + vec2(TIME, -TIME) * speed * 0.5)) / 0.5;
|
||||
noise_texture *= texture(dissolve_texture, loop(UV * 2.0 + vec2(TIME, TIME) * speed * 0.8)) / 0.5;
|
||||
noise_texture *= texture(dissolve_texture, loop(UV * 2.0 + vec2(-TIME, -TIME) * speed)) / 0.5;
|
||||
|
||||
ALPHA = clamp(noise_texture.x - threshold, 0, 1);
|
||||
ALPHA *= _fresnel(UV, 3) * alpha_add;
|
||||
ALPHA = clamp(ALPHA, 0, 1);
|
||||
ALBEDO = color;
|
||||
}
|
231
scripts/shaders/crt.gdshader
Normal file
231
scripts/shaders/crt.gdshader
Normal file
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
Shader from Godot Shaders - the free shader library.
|
||||
godotshaders.com/shader/VHS-and-CRT-monitor-effect
|
||||
|
||||
This shader is under CC0 license. Feel free to use, improve and
|
||||
change this shader according to your needs and consider sharing
|
||||
the modified result to godotshaders.com.
|
||||
*/
|
||||
|
||||
shader_type canvas_item;
|
||||
|
||||
//*** IMPORTANT! ***/
|
||||
// - If you are using this shader to affect the node it is applied to set 'overlay' to false (unchecked in the instepctor).
|
||||
// - If you are using this shader as an overlay, and want the shader to affect the nodes below in the Scene hierarchy,
|
||||
// set 'overlay' to true (checked in the inspector).
|
||||
// On Mac there is potentially a bug causing this to not work properly. If that is the case and you want to use the shader as an overlay
|
||||
// change all "overlay ? SCREEN_TEXTURE : TEXTURE" to only "SCREEN_TEXTURE" on lines 129-140, and "vec2 uv = overlay ? warp(SCREEN_UV) : warp(UV);"
|
||||
// to "vec2 uv = warp(SCREEN_UV);" on line 98.
|
||||
uniform bool overlay = false;
|
||||
|
||||
uniform float scanlines_opacity : hint_range(0.0, 1.0) = 0.4;
|
||||
uniform float scanlines_width : hint_range(0.0, 0.5) = 0.25;
|
||||
uniform float grille_opacity : hint_range(0.0, 1.0) = 0.3;
|
||||
uniform vec2 resolution = vec2(640.0, 480.0); // Set the number of rows and columns the texture will be divided in. Scanlines and grille will make a square based on these values
|
||||
|
||||
uniform bool pixelate = true; // Fill each square ("pixel") with a sampled color, creating a pixel look and a more accurate representation of how a CRT monitor would work.
|
||||
|
||||
uniform bool roll = true;
|
||||
uniform float roll_speed = 8.0; // Positive values are down, negative are up
|
||||
uniform float roll_size : hint_range(0.0, 100.0) = 15.0;
|
||||
uniform float roll_variation : hint_range(0.1, 5.0) = 1.8; // This valie is not an exact science. You have to play around with the value to find a look you like. How this works is explained in the code below.
|
||||
uniform float distort_intensity : hint_range(0.0, 0.2) = 0.05; // The distortion created by the rolling effect.
|
||||
|
||||
uniform float noise_opacity : hint_range(0.0, 1.0) = 0.4;
|
||||
uniform float noise_speed = 5.0; // There is a movement in the noise pattern that can be hard to see first. This sets the speed of that movement.
|
||||
|
||||
uniform float static_noise_intensity : hint_range(0.0, 1.0) = 0.06;
|
||||
|
||||
uniform float aberration : hint_range(-1.0, 1.0) = 0.03; // Chromatic aberration, a distortion on each color channel.
|
||||
uniform float brightness = 1.4; // When adding scanline gaps and grille the image can get very dark. Brightness tries to compensate for that.
|
||||
uniform bool discolor = true; // Add a discolor effect simulating a VHS
|
||||
|
||||
uniform float warp_amount :hint_range(0.0, 5.0) = 1.0; // Warp the texture edges simulating the curved glass of a CRT monitor or old TV.
|
||||
uniform bool clip_warp = false;
|
||||
|
||||
uniform float vignette_intensity = 0.4; // Size of the vignette, how far towards the middle it should go.
|
||||
uniform float vignette_opacity : hint_range(0.0, 1.0) = 0.5;
|
||||
|
||||
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
|
||||
|
||||
// Used by the noise functin to generate a pseudo random value between 0.0 and 1.0
|
||||
vec2 random(vec2 uv){
|
||||
uv = vec2( dot(uv, vec2(127.1,311.7) ),
|
||||
dot(uv, vec2(269.5,183.3) ) );
|
||||
return -1.0 + 2.0 * fract(sin(uv) * 43758.5453123);
|
||||
}
|
||||
|
||||
// Generate a Perlin noise used by the distortion effects
|
||||
float noise(vec2 uv) {
|
||||
vec2 uv_index = floor(uv);
|
||||
vec2 uv_fract = fract(uv);
|
||||
|
||||
vec2 blur = smoothstep(0.0, 1.0, uv_fract);
|
||||
|
||||
return mix( mix( dot( random(uv_index + vec2(0.0,0.0) ), uv_fract - vec2(0.0,0.0) ),
|
||||
dot( random(uv_index + vec2(1.0,0.0) ), uv_fract - vec2(1.0,0.0) ), blur.x),
|
||||
mix( dot( random(uv_index + vec2(0.0,1.0) ), uv_fract - vec2(0.0,1.0) ),
|
||||
dot( random(uv_index + vec2(1.0,1.0) ), uv_fract - vec2(1.0,1.0) ), blur.x), blur.y) * 0.5 + 0.5;
|
||||
}
|
||||
|
||||
// Takes in the UV and warps the edges, creating the spherized effect
|
||||
vec2 warp(vec2 uv){
|
||||
vec2 delta = uv - 0.5;
|
||||
float delta2 = dot(delta.xy, delta.xy);
|
||||
float delta4 = delta2 * delta2;
|
||||
float delta_offset = delta4 * warp_amount;
|
||||
|
||||
return uv + delta * delta_offset;
|
||||
}
|
||||
|
||||
// Adds a black border to hide stretched pixel created by the warp effect
|
||||
float border (vec2 uv){
|
||||
float radius = min(warp_amount, 0.08);
|
||||
radius = max(min(min(abs(radius * 2.0), abs(1.0)), abs(1.0)), 1e-5);
|
||||
vec2 abs_uv = abs(uv * 2.0 - 1.0) - vec2(1.0, 1.0) + radius;
|
||||
float dist = length(max(vec2(0.0), abs_uv)) / radius;
|
||||
float square = smoothstep(0.96, 1.0, dist);
|
||||
return clamp(1.0 - square, 0.0, 1.0);
|
||||
}
|
||||
|
||||
// Adds a vignette shadow to the edges of the image
|
||||
float vignette(vec2 uv){
|
||||
uv *= 1.0 - uv.xy;
|
||||
float vignette = uv.x * uv.y * 15.0;
|
||||
return pow(vignette, vignette_intensity * vignette_opacity);
|
||||
}
|
||||
|
||||
void fragment()
|
||||
{
|
||||
vec2 uv = overlay ? warp(SCREEN_UV) : warp(UV); // Warp the uv. uv will be used in most cases instead of UV to keep the warping
|
||||
vec2 text_uv = uv;
|
||||
vec2 roll_uv = vec2(0.0);
|
||||
float time = roll ? TIME : 0.0;
|
||||
|
||||
|
||||
// Pixelate the texture based on the given resolution.
|
||||
if (pixelate)
|
||||
{
|
||||
text_uv = ceil(uv * resolution) / resolution;
|
||||
}
|
||||
|
||||
// Create the rolling effect. We need roll_line a bit later to make the noise effect.
|
||||
// That is why this runs if roll is true OR noise_opacity is over 0.
|
||||
float roll_line = 0.0;
|
||||
if (roll || noise_opacity > 0.0)
|
||||
{
|
||||
// Create the areas/lines where the texture will be distorted.
|
||||
roll_line = smoothstep(0.3, 0.9, sin(uv.y * roll_size - (time * roll_speed) ) );
|
||||
// Create more lines of a different size and apply to the first set of lines. This creates a bit of variation.
|
||||
roll_line *= roll_line * smoothstep(0.3, 0.9, sin(uv.y * roll_size * roll_variation - (time * roll_speed * roll_variation) ) );
|
||||
// Distort the UV where where the lines are
|
||||
roll_uv = vec2(( roll_line * distort_intensity * (1.-UV.x)), 0.0);
|
||||
}
|
||||
|
||||
vec4 text;
|
||||
if (roll)
|
||||
{
|
||||
// If roll is true distort the texture with roll_uv. The texture is split up into RGB to
|
||||
// make some chromatic aberration. We apply the aberration to the red and green channels accorging to the aberration parameter
|
||||
// and intensify it a bit in the roll distortion.
|
||||
text.r = texture(SCREEN_TEXTURE, text_uv + roll_uv * 0.8 + vec2(aberration, 0.0) * .1).r;
|
||||
text.g = texture(SCREEN_TEXTURE, text_uv + roll_uv * 1.2 - vec2(aberration, 0.0) * .1 ).g;
|
||||
text.b = texture(SCREEN_TEXTURE, text_uv + roll_uv).b;
|
||||
text.a = 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If roll is false only apply the aberration without any distorion. The aberration values are very small so the .1 is only
|
||||
// to make the slider in the Inspector less sensitive.
|
||||
text.r = texture(SCREEN_TEXTURE, text_uv + vec2(aberration, 0.0) * .1).r;
|
||||
text.g = texture(SCREEN_TEXTURE, text_uv - vec2(aberration, 0.0) * .1).g;
|
||||
text.b = texture(SCREEN_TEXTURE, text_uv).b;
|
||||
text.a = 1.0;
|
||||
}
|
||||
|
||||
float r = text.r;
|
||||
float g = text.g;
|
||||
float b = text.b;
|
||||
|
||||
uv = warp(UV);
|
||||
|
||||
// CRT monitors don't have pixels but groups of red, green and blue dots or lines, called grille. We isolate the texture's color channels
|
||||
// and divide it up in 3 offsetted lines to show the red, green and blue colors next to each other, with a small black gap between.
|
||||
if (grille_opacity > 0.0){
|
||||
|
||||
float g_r = smoothstep(0.85, 0.95, abs(sin(uv.x * (resolution.x * 3.14159265))));
|
||||
r = mix(r, r * g_r, grille_opacity);
|
||||
|
||||
float g_g = smoothstep(0.85, 0.95, abs(sin(1.05 + uv.x * (resolution.x * 3.14159265))));
|
||||
g = mix(g, g * g_g, grille_opacity);
|
||||
|
||||
float b_b = smoothstep(0.85, 0.95, abs(sin(2.1 + uv.x * (resolution.x * 3.14159265))));
|
||||
b = mix(b, b * b_b, grille_opacity);
|
||||
|
||||
}
|
||||
|
||||
// Apply the grille to the texture's color channels and apply Brightness. Since the grille and the scanlines (below) make the image very dark you
|
||||
// can compensate by increasing the brightness.
|
||||
text.r = clamp(r * brightness, 0.0, 1.0);
|
||||
text.g = clamp(g * brightness, 0.0, 1.0);
|
||||
text.b = clamp(b * brightness, 0.0, 1.0);
|
||||
|
||||
// Scanlines are the horizontal lines that make up the image on a CRT monitor.
|
||||
// Here we are actual setting the black gap between each line, which I guess is not the right definition of the word, but you get the idea
|
||||
float scanlines = 0.5;
|
||||
if (scanlines_opacity > 0.0)
|
||||
{
|
||||
// Same technique as above, create lines with sine and applying it to the texture. Smoothstep to allow setting the line size.
|
||||
scanlines = smoothstep(scanlines_width, scanlines_width + 0.5, abs(sin(uv.y * (resolution.y * 3.14159265))));
|
||||
text.rgb = mix(text.rgb, text.rgb * vec3(scanlines), scanlines_opacity);
|
||||
}
|
||||
|
||||
// Apply the banded noise.
|
||||
if (noise_opacity > 0.0)
|
||||
{
|
||||
// Generate a noise pattern that is very stretched horizontally, and animate it with noise_speed
|
||||
float noise = smoothstep(0.4, 0.5, noise(uv * vec2(2.0, 200.0) + vec2(10.0, (TIME * (noise_speed))) ) );
|
||||
|
||||
// We use roll_line (set above) to define how big the noise should be vertically (multiplying cuts off all black parts).
|
||||
// We also add in some basic noise with random() to break up the noise pattern above. The noise is sized according to
|
||||
// the resolution value set in the inspector. If you don't like this look you can
|
||||
// change "ceil(uv * resolution) / resolution" to only "uv" to make it less pixelated. Or multiply resolution with som value
|
||||
// greater than 1.0 to make them smaller.
|
||||
roll_line *= noise * scanlines * clamp(random((ceil(uv * resolution) / resolution) + vec2(TIME * 0.8, 0.0)).x + 0.8, 0.0, 1.0);
|
||||
// Add it to the texture based on noise_opacity
|
||||
text.rgb = clamp(mix(text.rgb, text.rgb + roll_line, noise_opacity), vec3(0.0), vec3(1.0));
|
||||
}
|
||||
|
||||
// Apply static noise by generating it over the whole screen in the same way as above
|
||||
if (static_noise_intensity > 0.0)
|
||||
{
|
||||
text.rgb += clamp(random((ceil(uv * resolution) / resolution) + fract(TIME)).x, 0.0, 1.0) * static_noise_intensity;
|
||||
}
|
||||
|
||||
// Apply a black border to hide imperfections caused by the warping.
|
||||
// Also apply the vignette
|
||||
text.rgb *= border(uv);
|
||||
text.rgb *= vignette(uv);
|
||||
// Hides the black border and make that area transparent. Good if you want to add the the texture on top an image of a TV or monitor.
|
||||
if (clip_warp)
|
||||
{
|
||||
text.a = border(uv);
|
||||
}
|
||||
|
||||
// Apply discoloration to get a VHS look (lower saturation and higher contrast)
|
||||
// You can play with the values below or expose them in the Inspector.
|
||||
float saturation = 0.5;
|
||||
float contrast = 1.2;
|
||||
if (discolor)
|
||||
{
|
||||
// Saturation
|
||||
vec3 greyscale = vec3(text.r + text.g + text.b) / 3.;
|
||||
text.rgb = mix(text.rgb, greyscale, saturation);
|
||||
|
||||
// Contrast
|
||||
float midpoint = pow(0.5, 2.2);
|
||||
text.rgb = (text.rgb - vec3(midpoint)) * contrast + midpoint;
|
||||
}
|
||||
|
||||
COLOR = text;
|
||||
}
|
11
scripts/shaders/dissolve.gdshader
Normal file
11
scripts/shaders/dissolve.gdshader
Normal file
|
@ -0,0 +1,11 @@
|
|||
shader_type canvas_item;
|
||||
|
||||
uniform sampler2D dissolve_texture : hint_default_transparent;
|
||||
uniform float dissolve_value : hint_range(0,1);
|
||||
|
||||
void fragment(){
|
||||
vec4 main_texture = texture(TEXTURE, UV);
|
||||
vec4 noise_texture = texture(dissolve_texture, UV);
|
||||
main_texture.a *= floor(dissolve_value + min(1, noise_texture.x));
|
||||
COLOR = main_texture;
|
||||
}
|
45
scripts/shaders/pixelation.gdshader
Normal file
45
scripts/shaders/pixelation.gdshader
Normal file
|
@ -0,0 +1,45 @@
|
|||
shader_type canvas_item;
|
||||
uniform int num_colors: hint_range(2,32) = 8;
|
||||
uniform sampler2D PALETTE_TEXTURE: hint_default_black;
|
||||
uniform sampler2D PALETTE_TEXTURE_LOW: hint_default_black;
|
||||
|
||||
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
|
||||
|
||||
uniform int u_dither_size = 4;
|
||||
|
||||
vec3 palette_limiter (in vec3 albedo, in vec2 uv){
|
||||
float estimation_cutoff = 0.001;
|
||||
vec3 closest_color;
|
||||
float min_dist = 2.0;
|
||||
float n = float(num_colors);
|
||||
|
||||
bool palette_low = (int(uv.y)) % 2 == 0;
|
||||
|
||||
for (int i=0; i<num_colors; i++ ){
|
||||
float index = 1.000/(2.000*n)+float(i)/n;
|
||||
vec3 index_color = texture(PALETTE_TEXTURE, vec2(index,0.5)).rgb;
|
||||
float dist = length(index_color - albedo);
|
||||
if (dist < min_dist) {
|
||||
min_dist = dist;
|
||||
if(palette_low){
|
||||
closest_color = texture(PALETTE_TEXTURE_LOW, vec2(index,0.5)).rgb;
|
||||
}else{
|
||||
closest_color = index_color;
|
||||
}
|
||||
if (min_dist < estimation_cutoff){
|
||||
return closest_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return closest_color;
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
vec2 screen_size = vec2(textureSize(SCREEN_TEXTURE, 0)) / float(u_dither_size);
|
||||
vec2 uv_cord = floor(UV * screen_size);
|
||||
vec2 screen_sample_uv = uv_cord / screen_size;
|
||||
vec3 current_color = texture(SCREEN_TEXTURE, screen_sample_uv).rgb;
|
||||
|
||||
COLOR.rgb = palette_limiter(current_color, uv_cord);
|
||||
}
|
199
scripts/shaders/water.gdshader
Normal file
199
scripts/shaders/water.gdshader
Normal file
|
@ -0,0 +1,199 @@
|
|||
// Wind Waker style water - NekotoArts
|
||||
// Adapted from https://www.shadertoy.com/view/3tKBDz
|
||||
// After which I added in some fractal Brownian motion
|
||||
// as well as vertex displacement
|
||||
|
||||
shader_type spatial;
|
||||
render_mode unshaded;
|
||||
|
||||
uniform vec4 WATER_COL : source_color = vec4(0.04, 0.38, 0.88, 1.0);
|
||||
uniform vec4 WATER2_COL : source_color = vec4(0.04, 0.35, 0.78, 1.0);
|
||||
uniform vec4 FOAM_COL : source_color = vec4(0.8125, 0.9609, 0.9648, 1.0);
|
||||
uniform float distortion_speed = 2.0;
|
||||
uniform vec2 tile = vec2(5.0, 5.0);
|
||||
uniform float height = 2.0;
|
||||
uniform vec2 wave_size = vec2(2.0, 2.0);
|
||||
uniform float wave_speed = 1.5;
|
||||
|
||||
const float M_2PI = 6.283185307;
|
||||
const float M_6PI = 18.84955592;
|
||||
|
||||
float random(vec2 uv) {
|
||||
return fract(sin(dot(uv.xy,
|
||||
vec2(12.9898,78.233))) *
|
||||
43758.5453123);
|
||||
}
|
||||
|
||||
float noise(vec2 uv) {
|
||||
vec2 uv_index = floor(uv);
|
||||
vec2 uv_fract = fract(uv);
|
||||
|
||||
// Four corners in 2D of a tile
|
||||
float a = random(uv_index);
|
||||
float b = random(uv_index + vec2(1.0, 0.0));
|
||||
float c = random(uv_index + vec2(0.0, 1.0));
|
||||
float d = random(uv_index + vec2(1.0, 1.0));
|
||||
|
||||
vec2 blur = smoothstep(0.0, 1.0, uv_fract);
|
||||
|
||||
return mix(a, b, blur.x) +
|
||||
(c - a) * blur.y * (1.0 - blur.x) +
|
||||
(d - b) * blur.x * blur.y;
|
||||
}
|
||||
|
||||
float fbm(vec2 uv) {
|
||||
int octaves = 6;
|
||||
float amplitude = 0.5;
|
||||
float frequency = 3.0;
|
||||
float value = 0.0;
|
||||
|
||||
for(int i = 0; i < octaves; i++) {
|
||||
value += amplitude * noise(frequency * uv);
|
||||
amplitude *= 0.5;
|
||||
frequency *= 2.0;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
float circ(vec2 pos, vec2 c, float s)
|
||||
{
|
||||
c = abs(pos - c);
|
||||
c = min(c, 1.0 - c);
|
||||
|
||||
return smoothstep(0.0, 0.002, sqrt(s) - sqrt(dot(c, c))) * -1.0;
|
||||
}
|
||||
|
||||
// Foam pattern for the water constructed out of a series of circles
|
||||
float waterlayer(vec2 uv)
|
||||
{
|
||||
uv = mod(uv, 1.0); // Clamp to [0..1]
|
||||
|
||||
float ret = 1.0;
|
||||
ret += circ(uv, vec2(0.37378, 0.277169), 0.0268181);
|
||||
ret += circ(uv, vec2(0.0317477, 0.540372), 0.0193742);
|
||||
ret += circ(uv, vec2(0.430044, 0.882218), 0.0232337);
|
||||
ret += circ(uv, vec2(0.641033, 0.695106), 0.0117864);
|
||||
ret += circ(uv, vec2(0.0146398, 0.0791346), 0.0299458);
|
||||
ret += circ(uv, vec2(0.43871, 0.394445), 0.0289087);
|
||||
ret += circ(uv, vec2(0.909446, 0.878141), 0.028466);
|
||||
ret += circ(uv, vec2(0.310149, 0.686637), 0.0128496);
|
||||
ret += circ(uv, vec2(0.928617, 0.195986), 0.0152041);
|
||||
ret += circ(uv, vec2(0.0438506, 0.868153), 0.0268601);
|
||||
ret += circ(uv, vec2(0.308619, 0.194937), 0.00806102);
|
||||
ret += circ(uv, vec2(0.349922, 0.449714), 0.00928667);
|
||||
ret += circ(uv, vec2(0.0449556, 0.953415), 0.023126);
|
||||
ret += circ(uv, vec2(0.117761, 0.503309), 0.0151272);
|
||||
ret += circ(uv, vec2(0.563517, 0.244991), 0.0292322);
|
||||
ret += circ(uv, vec2(0.566936, 0.954457), 0.00981141);
|
||||
ret += circ(uv, vec2(0.0489944, 0.200931), 0.0178746);
|
||||
ret += circ(uv, vec2(0.569297, 0.624893), 0.0132408);
|
||||
ret += circ(uv, vec2(0.298347, 0.710972), 0.0114426);
|
||||
ret += circ(uv, vec2(0.878141, 0.771279), 0.00322719);
|
||||
ret += circ(uv, vec2(0.150995, 0.376221), 0.00216157);
|
||||
ret += circ(uv, vec2(0.119673, 0.541984), 0.0124621);
|
||||
ret += circ(uv, vec2(0.629598, 0.295629), 0.0198736);
|
||||
ret += circ(uv, vec2(0.334357, 0.266278), 0.0187145);
|
||||
ret += circ(uv, vec2(0.918044, 0.968163), 0.0182928);
|
||||
ret += circ(uv, vec2(0.965445, 0.505026), 0.006348);
|
||||
ret += circ(uv, vec2(0.514847, 0.865444), 0.00623523);
|
||||
ret += circ(uv, vec2(0.710575, 0.0415131), 0.00322689);
|
||||
ret += circ(uv, vec2(0.71403, 0.576945), 0.0215641);
|
||||
ret += circ(uv, vec2(0.748873, 0.413325), 0.0110795);
|
||||
ret += circ(uv, vec2(0.0623365, 0.896713), 0.0236203);
|
||||
ret += circ(uv, vec2(0.980482, 0.473849), 0.00573439);
|
||||
ret += circ(uv, vec2(0.647463, 0.654349), 0.0188713);
|
||||
ret += circ(uv, vec2(0.651406, 0.981297), 0.00710875);
|
||||
ret += circ(uv, vec2(0.428928, 0.382426), 0.0298806);
|
||||
ret += circ(uv, vec2(0.811545, 0.62568), 0.00265539);
|
||||
ret += circ(uv, vec2(0.400787, 0.74162), 0.00486609);
|
||||
ret += circ(uv, vec2(0.331283, 0.418536), 0.00598028);
|
||||
ret += circ(uv, vec2(0.894762, 0.0657997), 0.00760375);
|
||||
ret += circ(uv, vec2(0.525104, 0.572233), 0.0141796);
|
||||
ret += circ(uv, vec2(0.431526, 0.911372), 0.0213234);
|
||||
ret += circ(uv, vec2(0.658212, 0.910553), 0.000741023);
|
||||
ret += circ(uv, vec2(0.514523, 0.243263), 0.0270685);
|
||||
ret += circ(uv, vec2(0.0249494, 0.252872), 0.00876653);
|
||||
ret += circ(uv, vec2(0.502214, 0.47269), 0.0234534);
|
||||
ret += circ(uv, vec2(0.693271, 0.431469), 0.0246533);
|
||||
ret += circ(uv, vec2(0.415, 0.884418), 0.0271696);
|
||||
ret += circ(uv, vec2(0.149073, 0.41204), 0.00497198);
|
||||
ret += circ(uv, vec2(0.533816, 0.897634), 0.00650833);
|
||||
ret += circ(uv, vec2(0.0409132, 0.83406), 0.0191398);
|
||||
ret += circ(uv, vec2(0.638585, 0.646019), 0.0206129);
|
||||
ret += circ(uv, vec2(0.660342, 0.966541), 0.0053511);
|
||||
ret += circ(uv, vec2(0.513783, 0.142233), 0.00471653);
|
||||
ret += circ(uv, vec2(0.124305, 0.644263), 0.00116724);
|
||||
ret += circ(uv, vec2(0.99871, 0.583864), 0.0107329);
|
||||
ret += circ(uv, vec2(0.894879, 0.233289), 0.00667092);
|
||||
ret += circ(uv, vec2(0.246286, 0.682766), 0.00411623);
|
||||
ret += circ(uv, vec2(0.0761895, 0.16327), 0.0145935);
|
||||
ret += circ(uv, vec2(0.949386, 0.802936), 0.0100873);
|
||||
ret += circ(uv, vec2(0.480122, 0.196554), 0.0110185);
|
||||
ret += circ(uv, vec2(0.896854, 0.803707), 0.013969);
|
||||
ret += circ(uv, vec2(0.292865, 0.762973), 0.00566413);
|
||||
ret += circ(uv, vec2(0.0995585, 0.117457), 0.00869407);
|
||||
ret += circ(uv, vec2(0.377713, 0.00335442), 0.0063147);
|
||||
ret += circ(uv, vec2(0.506365, 0.531118), 0.0144016);
|
||||
ret += circ(uv, vec2(0.408806, 0.894771), 0.0243923);
|
||||
ret += circ(uv, vec2(0.143579, 0.85138), 0.00418529);
|
||||
ret += circ(uv, vec2(0.0902811, 0.181775), 0.0108896);
|
||||
ret += circ(uv, vec2(0.780695, 0.394644), 0.00475475);
|
||||
ret += circ(uv, vec2(0.298036, 0.625531), 0.00325285);
|
||||
ret += circ(uv, vec2(0.218423, 0.714537), 0.00157212);
|
||||
ret += circ(uv, vec2(0.658836, 0.159556), 0.00225897);
|
||||
ret += circ(uv, vec2(0.987324, 0.146545), 0.0288391);
|
||||
ret += circ(uv, vec2(0.222646, 0.251694), 0.00092276);
|
||||
ret += circ(uv, vec2(0.159826, 0.528063), 0.00605293);
|
||||
return max(ret, 0.0);
|
||||
}
|
||||
|
||||
// Procedural texture generation for the water
|
||||
vec3 water(vec2 uv, vec3 cdir, float iTime)
|
||||
{
|
||||
uv *= vec2(0.25);
|
||||
uv += fbm(uv) * 0.2;
|
||||
|
||||
// Parallax height distortion with two directional waves at
|
||||
// slightly different angles.
|
||||
vec2 a = 0.025 * cdir.xz / cdir.y; // Parallax offset
|
||||
float h = sin(uv.x + iTime); // Height at UV
|
||||
uv += a * h;
|
||||
h = sin(0.841471 * uv.x - 0.540302 * uv.y + iTime);
|
||||
uv += a * h;
|
||||
|
||||
// Texture distortion
|
||||
float d1 = mod(uv.x + uv.y, M_2PI);
|
||||
float d2 = mod((uv.x + uv.y + 0.25) * 1.3, M_6PI);
|
||||
d1 = iTime * 0.07 + d1;
|
||||
d2 = iTime * 0.5 + d2;
|
||||
vec2 dist = vec2(
|
||||
sin(d1) * 0.15 + sin(d2) * 0.05,
|
||||
cos(d1) * 0.15 + cos(d2) * 0.05
|
||||
);
|
||||
|
||||
vec3 ret = mix(WATER_COL.rgb, WATER2_COL.rgb, waterlayer(uv + dist.xy));
|
||||
ret = mix(ret, FOAM_COL.rgb, waterlayer(vec2(1.0) - uv - dist.yx));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void vertex(){
|
||||
float time = TIME * wave_speed;
|
||||
vec2 uv = UV * wave_size;
|
||||
float d1 = mod(uv.x + uv.y, M_2PI);
|
||||
float d2 = mod((uv.x + uv.y + 0.25) * 1.3, M_6PI);
|
||||
d1 = time * 0.07 + d1;
|
||||
d2 = time * 0.5 + d2;
|
||||
vec2 dist = vec2(
|
||||
sin(d1) * 0.15 + sin(d2) * 0.05,
|
||||
cos(d1) * 0.15 + cos(d2) * 0.05
|
||||
);
|
||||
VERTEX.y += dist.y * height;
|
||||
}
|
||||
|
||||
void fragment()
|
||||
{
|
||||
vec2 uv = UV;
|
||||
|
||||
ALBEDO = vec3(water(uv * tile, vec3(0,1,0), TIME * distortion_speed));
|
||||
}
|
56
scripts/singletons/dialogue_manager.gd
Normal file
56
scripts/singletons/dialogue_manager.gd
Normal file
|
@ -0,0 +1,56 @@
|
|||
extends Node
|
||||
|
||||
var global_variables = {}
|
||||
|
||||
@onready var text_box_scene = preload("res://prefabs/ink_template.tscn")
|
||||
|
||||
var text_box: Control
|
||||
|
||||
var is_dialog_active = false
|
||||
var can_enter_dialogue = true
|
||||
|
||||
@export var start_time = 50
|
||||
@export var decrease_speed = 0.5
|
||||
|
||||
signal dialogue_finished(time_to_add: int)
|
||||
|
||||
func start_dialog(lines: Resource):
|
||||
if lines == null:
|
||||
return
|
||||
if is_dialog_active or !can_enter_dialogue:
|
||||
return
|
||||
|
||||
_show_text_box()
|
||||
text_box.variables = global_variables
|
||||
text_box._setup_story(lines)
|
||||
|
||||
is_dialog_active = true
|
||||
can_enter_dialogue = false
|
||||
|
||||
func _show_text_box():
|
||||
text_box = text_box_scene.instantiate()
|
||||
get_tree().root.add_child(text_box)
|
||||
|
||||
const DIALOGUE_COOLDOWN = .5
|
||||
var dialogue_cooldown = 0
|
||||
|
||||
func _process(delta):
|
||||
if (
|
||||
Input.is_action_just_pressed("advance_dialog") &&
|
||||
is_dialog_active
|
||||
):
|
||||
text_box._continue_story()
|
||||
if !text_box.active:
|
||||
_quit_dialogue()
|
||||
|
||||
dialogue_cooldown -= delta
|
||||
if !is_dialog_active and dialogue_cooldown < 0:
|
||||
can_enter_dialogue = true
|
||||
|
||||
func _quit_dialogue():
|
||||
is_dialog_active = false
|
||||
global_variables = text_box.variables
|
||||
dialogue_finished.emit(global_variables["time_to_add"])
|
||||
global_variables["time_to_add"] = 0
|
||||
dialogue_cooldown = DIALOGUE_COOLDOWN
|
||||
text_box.queue_free()
|
Loading…
Add table
Add a link
Reference in a new issue