des indices d'intéractions à base de shaders et de bulles

This commit is contained in:
Thomas
2025-03-19 17:13:57 +01:00
parent 65af087d46
commit 0b805448ee
19 changed files with 1616 additions and 44 deletions

90
UI/clues/bubble_clue.tscn Normal file
View File

@@ -0,0 +1,90 @@
[gd_scene load_steps=7 format=3 uid="uid://dn10ervwv15oo"]
[ext_resource type="Texture2D" uid="uid://cwbhdira3w8qx" path="res://assest/ui/UI_48x48.png" id="1_o6ktm"]
[ext_resource type="Script" path="res://UI/clues/button_clue.gd" id="2_iwm3w"]
[sub_resource type="LabelSettings" id="LabelSettings_yr8f5"]
font_color = Color(0, 0, 0, 1)
[sub_resource type="Animation" id="Animation_srt4p"]
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:offset")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(0, 0)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Label:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(-18, -14)]
}
[sub_resource type="Animation" id="Animation_puwvl"]
resource_name = "move"
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:offset")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.266667, 0.533333, 0.733333),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [Vector2(0, 0), Vector2(0, 1), Vector2(0, 2), Vector2(0, 1)]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Label:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.266667, 0.533333, 0.733333),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [Vector2(-18, -14), Vector2(-18, -13), Vector2(-18, -12), Vector2(-18, -13)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_kli7q"]
_data = {
"RESET": SubResource("Animation_srt4p"),
"move": SubResource("Animation_puwvl")
}
[node name="Sprite2D" type="Sprite2D"]
texture = ExtResource("1_o6ktm")
hframes = 18
vframes = 9
frame = 5
script = ExtResource("2_iwm3w")
[node name="Label" type="Label" parent="."]
offset_left = -18.0
offset_top = -14.0
offset_right = 18.0
offset_bottom = 19.0
text = "E"
label_settings = SubResource("LabelSettings_yr8f5")
horizontal_alignment = 1
vertical_alignment = 1
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_kli7q")
}

9
UI/clues/button_clue.gd Normal file
View File

@@ -0,0 +1,9 @@
extends Sprite2D
class_name Clue
func setVisible(isV: bool):
visible = isV
if isV:
$AnimationPlayer.play("move")
else:
$AnimationPlayer.stop()

87
UI/clues/button_clue.tscn Normal file
View File

@@ -0,0 +1,87 @@
[gd_scene load_steps=6 format=3 uid="uid://clqdxhwojbkwp"]
[ext_resource type="Texture2D" uid="uid://b7k2x0bnxlhwh" path="res://assest/ui/Modern_UI_Style_2_48x48.png" id="1_cr0we"]
[ext_resource type="Script" path="res://UI/clues/button_clue.gd" id="2_md8cj"]
[sub_resource type="Animation" id="Animation_srt4p"]
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.233333, 0.5, 0.733333),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [432, 433, 434, 433]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Label:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.233333, 0.5, 0.733333),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [Vector2(-18, 3), Vector2(-18, 5), Vector2(-18, 7), Vector2(-18, 5)]
}
[sub_resource type="Animation" id="Animation_puwvl"]
resource_name = "move"
length = 0.75
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:frame")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.266667, 0.533333),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 1,
"values": [432, 433, 434]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Label:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.266667, 0.533333),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 1,
"values": [Vector2(-18, 3), Vector2(-18, 5), Vector2(-18, 7)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_kli7q"]
_data = {
"RESET": SubResource("Animation_srt4p"),
"move": SubResource("Animation_puwvl")
}
[node name="Sprite2D" type="Sprite2D"]
texture = ExtResource("1_cr0we")
hframes = 49
vframes = 17
frame = 432
script = ExtResource("2_md8cj")
[node name="Label" type="Label" parent="."]
offset_left = -18.0
offset_top = 3.0
offset_right = 18.0
offset_bottom = 36.0
text = "E"
horizontal_alignment = 1
vertical_alignment = 1
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_kli7q")
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

View File

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b7k2x0bnxlhwh"
path="res://.godot/imported/Modern_UI_Style_2_48x48.png-8fd28b9a4f551fa871cd26e907396b1b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assest/ui/Modern_UI_Style_2_48x48.png"
dest_files=["res://.godot/imported/Modern_UI_Style_2_48x48.png-8fd28b9a4f551fa871cd26e907396b1b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
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=1

BIN
assest/ui/UI_48x48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cwbhdira3w8qx"
path="res://.godot/imported/UI_48x48.png-a74dc45591fe65edc9542a52dfb2774e.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assest/ui/UI_48x48.png"
dest_files=["res://.godot/imported/UI_48x48.png-a74dc45591fe65edc9542a52dfb2774e.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
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=1

1217
assest/ui/ui.tres Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
shader_type canvas_item;
uniform vec4 line_color : source_color = vec4(1);
uniform float line_thickness : hint_range(0, 10) = 1.0;
const vec2 OFFSETS[8] = {
vec2(-1, -1), vec2(-1, 0), vec2(-1, 1), vec2(0, -1), vec2(0, 1),
vec2(1, -1), vec2(1, 0), vec2(1, 1)
};
void fragment() {
vec2 size = TEXTURE_PIXEL_SIZE * line_thickness / 2.0;
vec4 color = texture(TEXTURE, UV);
float inline = 1.0;
float outline = 0.0;
for (int i = 0; i < OFFSETS.length(); i++) {
float sample = texture(TEXTURE, UV + size * OFFSETS[i]).a;
outline += sample;
inline *= sample;
}
outline = min(1.0, outline) - color.a;
inline = (1.0 - inline) * color.a;
vec4 outlined_result = mix(color, line_color, outline + inline);
COLOR = mix(color, outlined_result, outlined_result.a);
}

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=13 format=3 uid="uid://bleadp4yrdgj"]
[gd_scene load_steps=17 format=3 uid="uid://bleadp4yrdgj"]
[ext_resource type="Script" path="res://caracters/human.gd" id="1_x3vfc"]
[ext_resource type="AnimationNodeStateMachine" uid="uid://ddr1ltkievtku" path="res://animations/human/human_state_machine.tres" id="2_86nrf"]
@@ -6,7 +6,10 @@
[ext_resource type="PackedScene" uid="uid://cg4dhp7qe68pt" path="res://animations/human/human.tscn" id="4_25owg"]
[ext_resource type="Texture2D" uid="uid://c3lal83o1trpd" path="res://assest/persos/bob.png" id="5_e15yd"]
[ext_resource type="PackedScene" uid="uid://brh7cqaxc13ie" path="res://zindex/ZIndexControler.tscn" id="5_g2w7l"]
[ext_resource type="Script" path="res://caracters/npc.gd" id="7_xosjn"]
[ext_resource type="Shader" path="res://caracters/bob/bob.gdshader" id="5_tpu8c"]
[ext_resource type="PackedScene" uid="uid://07byq4mh8uwv" path="res://caracters/npc_controler.tscn" id="8_uueub"]
[ext_resource type="PackedScene" uid="uid://x2asns3kiqwg" path="res://interactable/interaction_zone.tscn" id="9_35f01"]
[ext_resource type="PackedScene" uid="uid://dn10ervwv15oo" path="res://UI/clues/bubble_clue.tscn" id="10_rm4iv"]
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_a4vmx"]
radius = 5.0
@@ -15,7 +18,6 @@ height = 48.0
[sub_resource type="AnimationNodeTimeScale" id="AnimationNodeTimeScale_85jde"]
[sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_iwsa7"]
graph_offset = Vector2(0, -4)
nodes/HumanState/node = ExtResource("2_86nrf")
nodes/HumanState/position = Vector2(133.333, 120)
nodes/TimeScale/node = SubResource("AnimationNodeTimeScale_85jde")
@@ -23,10 +25,15 @@ nodes/TimeScale/position = Vector2(453.333, 53.3333)
nodes/output/position = Vector2(640, 146.667)
node_connections = [&"TimeScale", 0, &"HumanState", &"output", 0, &"TimeScale"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_ilky1"]
shader = ExtResource("5_tpu8c")
shader_parameter/line_color = Color(1, 1, 1, 1)
shader_parameter/line_thickness = 0.0
[sub_resource type="RectangleShape2D" id="RectangleShape2D_1kv0e"]
size = Vector2(40, 10)
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_6n4r3"]
[sub_resource type="CapsuleShape2D" id="CapsuleShape2D_i362a"]
radius = 52.0
height = 108.0
@@ -52,6 +59,7 @@ parameters/TimeScale/scale = 1.0
[node name="AnimationPlayer" parent="." instance=ExtResource("3_lb4ws")]
[node name="Sprite2D" parent="." instance=ExtResource("4_25owg")]
material = SubResource("ShaderMaterial_ilky1")
texture = ExtResource("5_e15yd")
frame = 1
@@ -63,32 +71,28 @@ position = Vector2(1, -13)
shape = SubResource("RectangleShape2D_1kv0e")
target_position = Vector2(0, -48)
[node name="Area2D" type="Area2D" parent="."]
[node name="detector" type="Area2D" parent="."]
collision_layer = 4
collision_mask = 4
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="detector"]
position = Vector2(0, 43)
rotation = 1.5708
shape = SubResource("CapsuleShape2D_a4vmx")
[node name="npcControler" type="Node2D" parent="." node_paths=PackedStringArray("controled")]
script = ExtResource("7_xosjn")
controled = NodePath("..")
[node name="npcControler" parent="." instance=ExtResource("8_uueub")]
[node name="Label" type="Label" parent="npcControler"]
visible = false
offset_right = 40.0
offset_bottom = 23.0
[node name="interaction zone" parent="." node_paths=PackedStringArray("clue") instance=ExtResource("9_35f01")]
clue = NodePath("../clue")
[node name="interactable" type="Area2D" parent="."]
collision_layer = 8
collision_mask = 8
[node name="CollisionShape2D" type="CollisionShape2D" parent="interactable"]
[node name="CollisionShape2D2" type="CollisionShape2D" parent="interaction zone"]
position = Vector2(0, 12)
shape = SubResource("CapsuleShape2D_6n4r3")
shape = SubResource("CapsuleShape2D_i362a")
[node name="clue" parent="." instance=ExtResource("10_rm4iv")]
z_index = 1000
position = Vector2(44, -38)
[connection signal="start_intracting" from="." to="npcControler" method="_on_character_body_2d_start_intracting"]
[connection signal="area_entered" from="Area2D" to="." method="_on_area_2d_area_entered"]
[connection signal="body_entered" from="Area2D" to="." method="_on_area_2d_body_entered"]
[connection signal="area_entered" from="detector" to="." method="_on_area_2d_area_entered"]
[connection signal="body_entered" from="detector" to="." method="_on_area_2d_body_entered"]

View File

@@ -1,5 +0,0 @@
extends Area2D
func start_interaction(askingForInteraction: Human):
(get_parent() as Human).start_interaction(askingForInteraction)

View File

@@ -11,6 +11,7 @@ var humanInteractionTarget: Human = null
@onready var animation_tree := $AnimationTree
@onready var animation_player := $AnimationPlayer
@onready var state_machine := animation_tree.get("parameters/HumanState/playback") as AnimationNodeStateMachinePlayback
@onready var interactionZone : InteractionZone = $"interaction zone"
signal start_intracting
@@ -56,9 +57,9 @@ func _physics_process(delta):
updateFacingDirectionInAnimationTree()
if wants_to_interact_with and wants_to_interact_with.get_parent().has_method("start_interaction"):
if wants_to_interact_with and wants_to_interact_with.has_method("start_interaction"):
if humanInteractionTarget == null:
humanInteractionTarget = wants_to_interact_with.get_parent() as Human
humanInteractionTarget = wants_to_interact_with as Human
humanInteractionTarget.start_interaction(self)
func _on_area_2d_body_entered(body: Node2D) -> void:
@@ -66,9 +67,25 @@ func _on_area_2d_body_entered(body: Node2D) -> void:
func start_interaction(askingForInteraction: Human):
emit_signal("start_intracting", askingForInteraction)
disable_interaction_clue()
func stop_interaction():
humanInteractionTarget = null
enable_interaction_clue()
func get_feet_global_position():
return global_position + Vector2(0, 43)
func enable_interaction_clue():
if interactionZone:
var mat = $Sprite2D.get("material") as ShaderMaterial
if mat:
mat.set_shader_parameter("line_thickness", 1)
interactionZone.enable_interaction_clue()
func disable_interaction_clue():
if interactionZone:
var mat = $Sprite2D.get("material") as ShaderMaterial
if mat:
mat.set_shader_parameter("line_thickness", 0)
interactionZone.disable_interaction_clue()

View File

@@ -5,7 +5,7 @@ var toFollow: Array[Vector2i]
@onready var world: TileMapLayer = get_parent().get_parent();
@onready var obstacles: TileMapLayer = world.get_children()[2]
@export var controled:Human
@onready var controled:Human = get_parent()
var destination:Node2D
var HumanLayer = 0
@@ -67,7 +67,6 @@ func _process(delta: float) -> void:
func _on_character_body_2d_start_intracting(interactingWith: Human) -> void:
controled.face(interactingWith.global_position)
print("pouet")
# ouvre un dialogue
var resource = load("res://caracters/bob/bob.dialogue")
DialogueManager.show_dialogue_balloon(resource, "start")

View File

@@ -0,0 +1,11 @@
[gd_scene load_steps=2 format=3 uid="uid://07byq4mh8uwv"]
[ext_resource type="Script" path="res://caracters/npc.gd" id="1_x4w66"]
[node name="npcControler" type="Node2D"]
script = ExtResource("1_x4w66")
[node name="Label" type="Label" parent="."]
visible = false
offset_right = 40.0
offset_bottom = 23.0

View File

@@ -2,23 +2,20 @@ extends Node
@export var human: Human
@export var ray : ShapeCast2D
var interactable : Node2D
var can_interact_with : Node2D
var possible_interactables : Array[Node2D]
func _unhandled_input(event: InputEvent) -> void:
human.stop_interaction()
human.velocityVector = Vector2(0, 0)
human.wants_to_grab = false
human.wants_to_interact_with = null
if (
event.is_action("move_left") or
event.is_action("move_right") or
event.is_action("move_up") or
event.is_action("move_down")
):
human.velocityVector = Input.get_vector("move_left", "move_right", "move_up", "move_down")
human.velocityVector = Input.get_vector("move_left", "move_right", "move_up", "move_down")
if event.is_action_pressed("grab"):
if interactable:
human.wants_to_interact_with = interactable
if can_interact_with:
human.wants_to_interact_with = can_interact_with
else:
human.wants_to_grab = true
@@ -38,10 +35,40 @@ func _process(delta) -> void:
ray.target_position = Vector2(-48, 0)
(ray.shape as RectangleShape2D).size = Vector2(20, 50)
interactable = null
# find all the possible interactables
possible_interactables = []
if ray.is_colliding():
var nbCollisions = ray.get_collision_count()
for n in range(nbCollisions):
var colider = ray.get_collider(n) as Node2D
if colider != null and colider != get_parent():
interactable = colider
if (
colider and colider.get_parent().has_method("start_interaction") and
colider.get_parent().has_method("enable_interaction_clue") and
colider.get_parent().has_method("disable_interaction_clue")
):
possible_interactables.append(colider.get_parent())
# find the closest interactable
var distance_to_closest = Vector2(0, 0)
var closest: Node2D = null
for potential_closest in possible_interactables:
var distance_to_human = abs(potential_closest.global_position - human.global_position)
if distance_to_closest == Vector2(0, 0):
distance_to_closest = distance_to_human
closest = potential_closest
if distance_to_human < distance_to_closest:
closest = potential_closest
distance_to_closest = distance_to_human
# if the new closest is different from the one we had before, notify the one we had before that it shouldn't keep its bubble visible
if can_interact_with != null:
if can_interact_with != closest:
can_interact_with.get_children()
can_interact_with.disable_interaction_clue()
# don't retrigger enabling the clue if it was already enabled
if can_interact_with != closest:
can_interact_with = closest
if can_interact_with:
can_interact_with.enable_interaction_clue()

View File

@@ -0,0 +1,12 @@
extends Area2D
class_name InteractionZone
@export var clue: Clue
func enable_interaction_clue():
if clue:
clue.setVisible(true)
func disable_interaction_clue():
if clue:
clue.setVisible(false)

View File

@@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://x2asns3kiqwg"]
[ext_resource type="Script" path="res://interactable/interaction_zone.gd" id="1_gljn5"]
[node name="interaction zone" type="Area2D"]
collision_layer = 8
collision_mask = 8
script = ExtResource("1_gljn5")

View File

@@ -28,7 +28,7 @@ position = Vector2(-333, -262)
[node name="movibles" type="Node2D" parent="."]
[node name="player" parent="movibles" instance=ExtResource("2_5x6b5")]
position = Vector2(-3964, -20)
position = Vector2(-107, -161)
[node name="cars" type="Node" parent="movibles"]

View File

@@ -6,5 +6,6 @@
script = ExtResource("1_fn0ft")
[node name="debugLabel" type="Label" parent="."]
visible = false
offset_right = 40.0
offset_bottom = 23.0