更新c01s05院长书房;更新prop hud选中与交互效果

This commit is contained in:
cakipaul 2025-01-12 19:36:41 +08:00
parent e0a746d2fa
commit a982c3a2e2
48 changed files with 527 additions and 238 deletions

View File

@ -4,7 +4,6 @@
## A collection of dialogue lines for use with [code]DialogueManager[/code]. ## A collection of dialogue lines for use with [code]DialogueManager[/code].
class_name DialogueResource extends Resource class_name DialogueResource extends Resource
const _DialogueManager = preload("./dialogue_manager.gd") const _DialogueManager = preload("./dialogue_manager.gd")
const DialogueLine = preload("./dialogue_line.gd") const DialogueLine = preload("./dialogue_line.gd")
@ -30,14 +29,38 @@ const DialogueLine = preload("./dialogue_line.gd")
## Get the next printable line of dialogue, starting from a referenced line ([code]title[/code] can ## Get the next printable line of dialogue, starting from a referenced line ([code]title[/code] can
## be a title string or a stringified line number). Runs any mutations along the way and then returns ## be a title string or a stringified line number). Runs any mutations along the way and then returns
## the first dialogue line encountered. ## the first dialogue line encountered.
func get_next_dialogue_line(title: String, extra_game_states: Array = [], mutation_behaviour: _DialogueManager.MutationBehaviour = _DialogueManager.MutationBehaviour.Wait) -> DialogueLine: func get_next_dialogue_line(
return await Engine.get_singleton("DialogueManager").get_next_dialogue_line(self, title, extra_game_states, mutation_behaviour) title: String,
extra_game_states: Array = [],
mutation_behaviour: _DialogueManager.MutationBehaviour = _DialogueManager.MutationBehaviour.Wait
) -> DialogueLine:
return await Engine.get_singleton("DialogueManager").get_next_dialogue_line(
self, title, extra_game_states, mutation_behaviour
)
## Get the list of any titles found in the file. ## Get the list of any titles found in the file.
func get_titles() -> PackedStringArray: func get_titles() -> Array:
return titles.keys() return titles.keys()
func get_ordered_titles() -> Array:
var splitted = raw_text.split("\n")
var ordered_titles = []
for line in splitted:
if line.begins_with("~ "):
ordered_titles.append(line.substr(2).strip_edges())
# # check ordered_titles consistency to titles
# for title in ordered_titles:
# if not titles.has(title):
# printerr("Title %s not found in titles" % title)
# ordered_titles.remove(title)
# for title in titles.keys():
# if not ordered_titles.has(title):
# printerr("Title %s not found in ordered_titles" % title)
# ordered_titles.append(title)
return ordered_titles
func _to_string() -> String: func _to_string() -> String:
return "<DialogueResource titles=\"%s\">" % [",".join(titles.keys())] return '<DialogueResource titles="%s">' % [",".join(titles.keys())]

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 KiB

After

Width:  |  Height:  |  Size: 141 KiB

View File

@ -1,4 +1,6 @@
keys,zh_Hans,_character,_notes,_tags,en keys,zh_Hans,_character,_notes,_tags,en
t89c0f4a8de,x年,,,,
t356af5308e,下午一点,,,,
t344c97cf2c,据闻奉贤县分水墩又有七人染受鼠疫,病状可怖,闻医官药治无用,免职。,,,, t344c97cf2c,据闻奉贤县分水墩又有七人染受鼠疫,病状可怖,闻医官药治无用,免职。,,,,
tdb119a3714,有地方人称鼠疫为妖邪作祟,甚为惊骇,一时人心惶惶,竟有聚众滋闹之事,政府以防疫事宜关系紧要,拟赴分水墩一带调查防疫事宜云。,,,, tdb119a3714,有地方人称鼠疫为妖邪作祟,甚为惊骇,一时人心惶惶,竟有聚众滋闹之事,政府以防疫事宜关系紧要,拟赴分水墩一带调查防疫事宜云。,,,,
ta750647b12,《申报》,,,, ta750647b12,《申报》,,,,

1 keys zh_Hans _character _notes _tags en
2 t89c0f4a8de x年
3 t356af5308e 下午一点
4 t344c97cf2c 据闻奉贤县分水墩又有七人染受鼠疫,病状可怖,闻医官药治无用,免职。
5 tdb119a3714 有地方人称鼠疫为妖邪作祟,甚为惊骇,一时人心惶惶,竟有聚众滋闹之事,政府以防疫事宜关系紧要,拟赴分水墩一带调查防疫事宜云。
6 ta750647b12 《申报》

View File

@ -1,3 +1,8 @@
~ c01_院长座钟
x年 [ID:t89c0f4a8de]
下午一点 [ID:t356af5308e]
=> END
~ c02_鼠疫海报 ~ c02_鼠疫海报
据闻奉贤县分水墩又有七人染受鼠疫,病状可怖,闻医官药治无用,免职。 [ID:t344c97cf2c] 据闻奉贤县分水墩又有七人染受鼠疫,病状可怖,闻医官药治无用,免职。 [ID:t344c97cf2c]
有地方人称鼠疫为妖邪作祟,甚为惊骇,一时人心惶惶,竟有聚众滋闹之事,政府以防疫事宜关系紧要,拟赴分水墩一带调查防疫事宜云。 [ID:tdb119a3714] 有地方人称鼠疫为妖邪作祟,甚为惊骇,一时人心惶惶,竟有聚众滋闹之事,政府以防疫事宜关系紧要,拟赴分水墩一带调查防疫事宜云。 [ID:tdb119a3714]

View File

@ -1,4 +1,5 @@
keys,zh_Hans,en,_character,_notes,_tags keys,zh_Hans,en,_character,_notes,_tags
c01_纸包钥匙,一张纸条包着钥匙,,,,
ui_退出,退出,Exit,,, ui_退出,退出,Exit,,,
ui_阅读,阅读,Read,,, ui_阅读,阅读,Read,,,
ui_收起,收起,Hold,,, ui_收起,收起,Hold,,,
@ -19,7 +20,9 @@ notes_无法触碰,无法触碰,,,,
notes_挂画,挂画,,,, notes_挂画,挂画,,,,
notes_相框,相框,,,, notes_相框,相框,,,,
notes_寻人启事,寻人启事,,,, notes_寻人启事,寻人启事,,,,
c01_纸包钥匙,一张纸条包着钥匙,,,, c01_鸡毛掸子,这是鸡毛掸子吗?,,,,
c01_院长书桌,书桌上好像有本书,,,,
c01_院长座钟,唔...下午一点了,,,,
c02_绳子剪刀,绳子和剪刀,,,, c02_绳子剪刀,绳子和剪刀,,,,
c02_寻人启事1,似乎是一张寻人启事,,,, c02_寻人启事1,似乎是一张寻人启事,,,,
c02_寻人启事2,脸的部分被撕掉了,看不清,,,, c02_寻人启事2,脸的部分被撕掉了,看不清,,,,

1 keys zh_Hans en _character _notes _tags
2 c01_纸包钥匙 一张纸条包着钥匙
3 ui_退出 退出 Exit
4 ui_阅读 阅读 Read
5 ui_收起 收起 Hold
20 notes_挂画 挂画
21 notes_相框 相框
22 notes_寻人启事 寻人启事
23 c01_纸包钥匙 c01_鸡毛掸子 一张纸条包着钥匙 这是鸡毛掸子吗?
24 c01_院长书桌 书桌上好像有本书
25 c01_院长座钟 唔...下午一点了
26 c02_绳子剪刀 绳子和剪刀
27 c02_寻人启事1 似乎是一张寻人启事
28 c02_寻人启事2 脸的部分被撕掉了,看不清

View File

@ -8,15 +8,15 @@
~ PropItems ~ PropItems
# texture 路径从 "res://asset/art/prop/" 之后算起 # texture 路径从 "res://asset/art/prop/" 之后算起
# c01 # c01
令牌[#texture=c01/令牌物品.png] [ID:prop_令牌] 令牌 [#texture=c01/令牌物品.png] [ID:prop_令牌]
装有灵魂的令牌[#texture=c01/装有灵魂的令牌物品.png] [ID:prop_装有灵魂的令牌] 装有灵魂的令牌 [#texture=c01/装有灵魂的令牌物品.png] [ID:prop_装有灵魂的令牌]
# c02 # c02
小猫玩具的脑袋[#texture=c02/小猫玩具脑袋物品.png] [ID:prop_小猫玩具的脑袋] 小猫玩具的脑袋 [#texture=c02/小猫玩具脑袋物品.png] [ID:prop_小猫玩具的脑袋]
绳子[#texture=c02/绳子物品.png] [ID:prop_绳子] 绳子 [#texture=c02/绳子物品.png] [ID:prop_绳子]
1012钥匙[#texture=c02/1012钥匙物品.png] [ID:prop_1012钥匙] 1012钥匙 [#texture=c02/1012钥匙物品.png] [ID:prop_1012钥匙]
老虎钳[#texture=c02/老虎钳物品.png] [ID:prop_老虎钳] 老虎钳 [#texture=c02/老虎钳物品.png] [ID:prop_老虎钳]
3014旋转锁钥匙[#texture=c02/3014旋转锁钥匙物品.png] [ID:prop_3014旋转锁钥匙] 3014旋转锁钥匙 [#texture=c02/3014旋转锁钥匙物品.png] [ID:prop_3014旋转锁钥匙]
小猫玩具[#texture=c02/小猫玩具完整物品.png] [ID:prop_小猫玩具完整] 小猫玩具 [#texture=c02/小猫玩具完整物品.png] [ID:prop_小猫玩具完整]
=> END! => END!
# notes 通用 # notes 通用
@ -25,11 +25,11 @@
=> END => END
~ notes_锁住了 ~ notes_锁住了
锁住了[ID:notes_锁住了] 锁住了 [ID:notes_锁住了]
=> END => END
~ notes_打不开 ~ notes_打不开
打不开[ID:notes_打不开] 打不开 [ID:notes_打不开]
=> END => END
~ notes_干掉的血迹 ~ notes_干掉的血迹
@ -57,8 +57,16 @@
=> END => END
# c01 # c01
~ c01_纸包钥匙 ~ c01_鸡毛掸子
一张纸条包着钥匙 [ID:c01_纸包钥匙] 这是鸡毛掸子吗? [ID:c01_鸡毛掸子]
=> END
~ c01_院长书桌
书桌上好像有本书 [ID:c01_院长书桌]
=> END
~ c01_院长座钟
唔...下午一点了 [ID:c01_院长座钟]
=> END => END
# c02 # c02
@ -80,7 +88,7 @@
=> END => END
~ c02_老鼠洞 ~ c02_老鼠洞
一个老鼠洞[ID:c02_老鼠洞1] 一个老鼠洞 [ID:c02_老鼠洞1]
在这种楼里挺常见的 [ID:c02_老鼠洞2] 在这种楼里挺常见的 [ID:c02_老鼠洞2]
=> END => END

File diff suppressed because one or more lines are too long

View File

@ -83,7 +83,8 @@ func reload_frames():
func _on_mapping_submitted(new_text: String): func _on_mapping_submitted(new_text: String):
# clear the old mapping # clear the old mapping
var sprite_frames = animated_sprite.sprite_frames as SpriteFrames var sprite_frames = animated_sprite.sprite_frames as SpriteFrames
sprite_frames.remove_animation(mapping_name) if sprite_frames.has_animation(mapping_name):
sprite_frames.remove_animation(mapping_name)
mapping_name = new_text mapping_name = new_text
frames_config.data.mapping[frame_dir_name] = mapping_name frames_config.data.mapping[frame_dir_name] = mapping_name
reload_frames() reload_frames()

View File

@ -21,7 +21,7 @@ size_flags_vertical = 4
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="PanelContainer/CenterContainer"] [node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="PanelContainer/CenterContainer"]
unique_name_in_owner = true unique_name_in_owner = true
sprite_frames = ExtResource("2_4hiuy") sprite_frames = ExtResource("2_4hiuy")
animation = &"climbing_down" animation = &"c00_吕萍_记笔记_right"
[node name="HBoxContainer" type="HBoxContainer" parent="."] [node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 2 layout_mode = 2

View File

@ -16,8 +16,11 @@ func get_player() -> MainPlayer:
return get_node_or_null("/root/Main/MainPlayer") as MainPlayer return get_node_or_null("/root/Main/MainPlayer") as MainPlayer
func get_prop_hud() -> PropHud: func get_current_selected_prop() -> String:
return get_node_or_null("/root/Main/UILayer/PropHUD") as PropHud var prop_hud = get_node_or_null("/root/Main/UILayer/PropHUD") as PropHud
if prop_hud and prop_hud.selected:
return prop_hud.inventory.current_item_key()
return ""
func pop_os(lines := []): func pop_os(lines := []):

View File

@ -37,6 +37,7 @@ buses/default_bus_layout="res://config/default_bus_layout.tres"
[autoload] [autoload]
DebugMenu="*res://addons/debug_menu/debug_menu.tscn" DebugMenu="*res://addons/debug_menu/debug_menu.tscn"
DialogueManager="*res://addons/dialogue_manager/dialogue_manager.gd"
GlobalConfigManager="*res://manager/config_manager/global_config_manager.gd" GlobalConfigManager="*res://manager/config_manager/global_config_manager.gd"
ArchiveManager="*res://manager/archive_manager/archive_manager.gd" ArchiveManager="*res://manager/archive_manager/archive_manager.gd"
CameraFocusMarker="*res://scene/camera/camera_focus_marker.tscn" CameraFocusMarker="*res://scene/camera/camera_focus_marker.tscn"
@ -46,7 +47,6 @@ AudioManager="*res://manager/audio_manager/audio_manager.gd"
EventManager="*res://manager/event_manager/event_manager.gd" EventManager="*res://manager/event_manager/event_manager.gd"
CgManager="*res://manager/cg_manager/cg_manager.gd" CgManager="*res://manager/cg_manager/cg_manager.gd"
InputManager="res://manager/input/input_manager.gd" InputManager="res://manager/input/input_manager.gd"
DialogueManager="*res://addons/dialogue_manager/dialogue_manager.gd"
[dialogue_manager] [dialogue_manager]
@ -137,6 +137,11 @@ prop_right={
, Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":16,"position":Vector2(427, 48),"global_position":Vector2(446, 139),"factor":0.0300018,"button_index":5,"canceled":false,"pressed":true,"double_click":false,"script":null) , Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":16,"position":Vector2(427, 48),"global_position":Vector2(446, 139),"factor":0.0300018,"button_index":5,"canceled":false,"pressed":true,"double_click":false,"script":null)
] ]
} }
prop_select={
"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":88,"key_label":0,"unicode":120,"location":0,"echo":false,"script":null)
]
}
toggle_journal={ toggle_journal={
"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":32,"key_label":0,"unicode":32,"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":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)

View File

@ -115,6 +115,6 @@ func _get_property_list() -> Array[Dictionary]:
"name": "hook_dialogue_title", "name": "hook_dialogue_title",
"type": TYPE_STRING, "type": TYPE_STRING,
"hint": PROPERTY_HINT_ENUM_SUGGESTION, "hint": PROPERTY_HINT_ENUM_SUGGESTION,
"hint_string": ",".join(dialogue_res.titles.keys()) "hint_string": ",".join(dialogue_res.get_ordered_titles())
} }
] ]

View File

@ -1,7 +1,8 @@
extends StaticBody2D extends Sprite2D
@export var entity_name: String = "" @export var entity_name: String = ""
@export var state: String = "" @export var prop_key := ""
@export var interacted := false
@export var texture_before: Texture2D @export var texture_before: Texture2D
@export var texture_after: Texture2D @export var texture_after: Texture2D
@ -25,4 +26,5 @@ func _on_cancel(_body = null) -> void:
func _on_interacted() -> void: func _on_interacted() -> void:
pass var key = SceneManager.get_current_selected_prop()
print("prop_key", key)

View File

@ -1,18 +1,14 @@
[gd_scene load_steps=6 format=3 uid="uid://cw3q5pvciumil"] [gd_scene load_steps=5 format=3 uid="uid://cw3q5pvciumil"]
[ext_resource type="Script" path="res://scene/entity/interactable.gd" id="1_6nrd3"] [ext_resource type="Script" path="res://scene/entity/interactable.gd" id="1_6nrd3"]
[ext_resource type="PackedScene" uid="uid://c85t6stvytvjn" path="res://scene/entity/ux/sfx.tscn" id="2_bvj74"] [ext_resource type="PackedScene" uid="uid://c85t6stvytvjn" path="res://scene/entity/ux/sfx.tscn" id="2_bvj74"]
[ext_resource type="PackedScene" uid="uid://c4tipnj1cr1j3" path="res://scene/entity/ux/sign.tscn" id="3_qsms8"] [ext_resource type="PackedScene" uid="uid://c4tipnj1cr1j3" path="res://scene/entity/ux/sign.tscn" id="3_qsms8"]
[ext_resource type="Texture2D" uid="uid://birl0unx22cmc" path="res://asset/art/scene/c02/s04_院子现实版/e_铁门.png" id="4_4pvt4"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_8d3b4"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_8d3b4"]
resource_local_to_scene = true resource_local_to_scene = true
size = Vector2(35, 70) size = Vector2(35, 70)
[node name="Interactable" type="StaticBody2D"] [node name="Interactable" type="Sprite2D"]
collision_layer = 4
collision_mask = 5
input_pickable = true
script = ExtResource("1_6nrd3") script = ExtResource("1_6nrd3")
[node name="Sfx" parent="." instance=ExtResource("2_bvj74")] [node name="Sfx" parent="." instance=ExtResource("2_bvj74")]
@ -27,9 +23,3 @@ collision_layer = 0
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] [node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
unique_name_in_owner = true unique_name_in_owner = true
shape = SubResource("RectangleShape2D_8d3b4") shape = SubResource("RectangleShape2D_8d3b4")
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="."]
polygon = PackedVector2Array(-13.5, -86.5, -13.5, 51, -11.5, 52.5, -11.5, 55.1, -5.8, 53.5, 2.3, 69.5, 3.1, 69.5, 5.8, 76.7, 5.1, 78.5, 3.1, 78.5, 4.4, 86.5, 13.5, 86.5, 13.5, -72.5, 5.4, -72.5, -2.5, -82.2, -2.5, -86.5)
[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource("4_4pvt4")

View File

@ -21,6 +21,7 @@ var content_key: String = ""
@onready var area2d = %Area2D as Area2D @onready var area2d = %Area2D as Area2D
@onready var sfx = %Sfx @onready var sfx = %Sfx
@onready var container = %Container
@onready var cover_rect = %Cover as TextureRect @onready var cover_rect = %Cover as TextureRect
@onready var content_label = %ContentLabel as Label @onready var content_label = %ContentLabel as Label
@onready var tip_label = %TipLabel as Label @onready var tip_label = %TipLabel as Label
@ -31,13 +32,6 @@ var tip_notes = "Q: " + tr("ui_退出") + " " + "E: " + tr("ui_收起")
static var content_dialogue = ( static var content_dialogue = (
preload("res://asset/dialogue/inspect_content.dialogue") as DialogueResource preload("res://asset/dialogue/inspect_content.dialogue") as DialogueResource
) )
static var content_titles = ""
static func _static_init() -> void:
# preload all titles from content_dialogue
content_titles = ",".join(content_dialogue.titles.keys())
var status := STATUS_NORAML var status := STATUS_NORAML
var blinking_tween: Tween var blinking_tween: Tween
@ -46,17 +40,15 @@ var inspected_time = 0.0
func _ready() -> void: func _ready() -> void:
$InspectLayer.layer = GlobalConfig.CANVAS_LAYER_PROP_INSPECTOR
sign_mark.interacted.connect(_on_interacted) sign_mark.interacted.connect(_on_interacted)
sign_mark.cancel.connect(_on_cancel) sign_mark.cancel.connect(_on_cancel)
container.modulate.a = 0.0
content_label.text = _get_tr_content() content_label.text = _get_tr_content()
content_label.modulate.a = 0.0
tip_label.text = tip_cover tip_label.text = tip_cover
tip_label.modulate.a = 0.0
cover_rect.modulate.a = 0.0
cover_rect.texture = texture_cover cover_rect.texture = texture_cover
func _get_tr_content(): func _get_tr_content():
if content_key == "": if content_key == "":
return "" return ""
@ -83,20 +75,19 @@ func _on_interacted() -> void:
status = STATUS_INSPECTING_COVER status = STATUS_INSPECTING_COVER
sign_mark.show_sign = false sign_mark.show_sign = false
SceneManager.freeze_player(0) SceneManager.freeze_player(0)
cover_rect.texture = texture_cover
tip_label.text = tip_cover tip_label.text = tip_cover
_blink_label(true) _blink_label(true)
elif status == STATUS_INSPECTING_COVER: elif status == STATUS_INSPECTING_COVER:
sfx.play() sfx.play()
status = STATUS_INSPECTING_NOTES status = STATUS_INSPECTING_NOTES
tip_label.text = tip_notes tip_label.text = tip_notes
create_tween().tween_property(content_label, "modulate:a", 1.0, 0.2) create_tween().tween_property(container, "modulate:a", 1.0, 0.15)
create_tween().tween_property(cover_rect, "modulate:a", 1.0, 0.15)
elif status == STATUS_INSPECTING_NOTES: elif status == STATUS_INSPECTING_NOTES:
sfx.play() sfx.play()
status = STATUS_INSPECTING_COVER status = STATUS_INSPECTING_COVER
tip_label.text = tip_cover tip_label.text = tip_cover
create_tween().tween_property(content_label, "modulate:a", 0.0, 0.15) create_tween().tween_property(container, "modulate:a", 0.0, 0.15)
create_tween().tween_property(cover_rect, "modulate:a", 0.0, 0.2)
func _blink_label(init := true): func _blink_label(init := true):
@ -114,9 +105,8 @@ func _blink_label(init := true):
func _on_cancel(_body = null): func _on_cancel(_body = null):
# inspected_time = Time.get_ticks_msec() # inspected_time = Time.get_ticks_msec()
status = STATUS_NORAML status = STATUS_NORAML
cover_rect.modulate.a = 0.0
var tween = create_tween() var tween = create_tween()
tween.tween_property(content_label, "modulate:a", 0.0, 0.15) tween.tween_property(container, "modulate:a", 0.0, 0.15)
if blinking_tween and blinking_tween.is_running(): if blinking_tween and blinking_tween.is_running():
blinking_tween.kill() blinking_tween.kill()
tween.parallel().tween_property(tip_label, "modulate:a", 0.0, 0.15) tween.parallel().tween_property(tip_label, "modulate:a", 0.0, 0.15)
@ -139,12 +129,12 @@ func _get(property: StringName) -> Variant:
return null return null
func _get_property_list() -> Array[Dictionary]: # only show notes_ properties in editor func _get_property_list() -> Array[Dictionary]: # only show notes_ properties in editor
if Engine.is_editor_hint() and editor_filter and editor_filter != "none": if Engine.is_editor_hint() and editor_filter and editor_filter != "none":
var filted_titles = content_dialogue.titles.keys().filter(_filter_property) var filted_titles = content_dialogue.get_ordered_titles().filter(_filter_property)
return [ return [
{ {
"name": "note_key", "name": "content_key",
"type": TYPE_STRING, "type": TYPE_STRING,
"hint": PROPERTY_HINT_ENUM_SUGGESTION, "hint": PROPERTY_HINT_ENUM_SUGGESTION,
"hint_string": ",".join(filted_titles) "hint_string": ",".join(filted_titles)
@ -155,9 +145,10 @@ func _get_property_list() -> Array[Dictionary]: # only show notes_ properties in
"name": "content_key", "name": "content_key",
"type": TYPE_STRING, "type": TYPE_STRING,
"hint": PROPERTY_HINT_ENUM_SUGGESTION, "hint": PROPERTY_HINT_ENUM_SUGGESTION,
"hint_string": content_titles "hint_string": ",".join(content_dialogue.get_ordered_titles())
} }
] ]
func _filter_property(property: StringName) -> bool: func _filter_property(property: StringName) -> bool:
return property.find(editor_filter) >= 0 return property.find(editor_filter) >= 0

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=10 format=3 uid="uid://ci5anaxsa1apl"] [gd_scene load_steps=11 format=3 uid="uid://ci5anaxsa1apl"]
[ext_resource type="Script" path="res://scene/entity/local_inspectable.gd" id="1_85el0"] [ext_resource type="Script" path="res://scene/entity/local_inspectable.gd" id="1_85el0"]
[ext_resource type="PackedScene" uid="uid://c85t6stvytvjn" path="res://scene/entity/ux/sfx.tscn" id="2_h0c2s"] [ext_resource type="PackedScene" uid="uid://c85t6stvytvjn" path="res://scene/entity/ux/sfx.tscn" id="2_h0c2s"]
@ -7,6 +7,7 @@
[ext_resource type="PackedScene" uid="uid://c4tipnj1cr1j3" path="res://scene/entity/ux/sign.tscn" id="4_do8tr"] [ext_resource type="PackedScene" uid="uid://c4tipnj1cr1j3" path="res://scene/entity/ux/sign.tscn" id="4_do8tr"]
[ext_resource type="SpriteFrames" uid="uid://c3s8u4ifaucpj" path="res://config/animation/entity_sprite_frames.tres" id="6_e77p4"] [ext_resource type="SpriteFrames" uid="uid://c3s8u4ifaucpj" path="res://config/animation/entity_sprite_frames.tres" id="6_e77p4"]
[ext_resource type="Script" path="res://scene/entity/ux/animated_sound_sprite_2d.gd" id="7_bhwlx"] [ext_resource type="Script" path="res://scene/entity/ux/animated_sound_sprite_2d.gd" id="7_bhwlx"]
[ext_resource type="Texture2D" uid="uid://cpht56skg054p" path="res://asset/art/scene/c01/s05_院长房间/e_座钟.png" id="8_53i12"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_4fuic"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_4fuic"]
resource_local_to_scene = true resource_local_to_scene = true
@ -18,6 +19,7 @@ font_size = 11
[node name="LocalInspectable" type="Sprite2D"] [node name="LocalInspectable" type="Sprite2D"]
script = ExtResource("1_85el0") script = ExtResource("1_85el0")
content_key = ""
[node name="Sfx" parent="." instance=ExtResource("2_h0c2s")] [node name="Sfx" parent="." instance=ExtResource("2_h0c2s")]
unique_name_in_owner = true unique_name_in_owner = true
@ -53,9 +55,20 @@ unique_name_in_owner = true
shape = SubResource("RectangleShape2D_4fuic") shape = SubResource("RectangleShape2D_4fuic")
[node name="InspectLayer" type="CanvasLayer" parent="."] [node name="InspectLayer" type="CanvasLayer" parent="."]
layer = 110 layer = 11
[node name="AspectRatioContainer" type="AspectRatioContainer" parent="InspectLayer"] [node name="Root" type="Control" parent="InspectLayer"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Container" type="PanelContainer" parent="InspectLayer/Root"]
unique_name_in_owner = true
modulate = Color(1, 1, 1, 0)
layout_mode = 1
anchors_preset = 15 anchors_preset = 15
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
@ -63,42 +76,40 @@ grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
mouse_filter = 2 mouse_filter = 2
[node name="Cover" type="TextureRect" parent="InspectLayer/AspectRatioContainer"] [node name="Cover" type="TextureRect" parent="InspectLayer/Root/Container"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 4 size_flags_horizontal = 4
size_flags_vertical = 4 size_flags_vertical = 4
mouse_filter = 2 mouse_filter = 2
texture = ExtResource("8_53i12")
[node name="ContentLabel" type="Label" parent="InspectLayer/AspectRatioContainer"] [node name="ContentLabel" type="Label" parent="InspectLayer/Root/Container"]
unique_name_in_owner = true unique_name_in_owner = true
modulate = Color(1, 1, 1, 0)
z_index = 100 z_index = 100
custom_minimum_size = Vector2(130, 0) custom_minimum_size = Vector2(130, 0)
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 4 size_flags_horizontal = 4
text = "据闻奉贤县分水墩又有七人染受鼠疫,病状可怖,闻医官药治无用,免职。
有地方人称鼠疫为妖邪作祟,甚为惊骇,一时人心惶惶,竟有聚众滋闹之事,政府以防疫事宜关系紧要,拟赴分水墩一带调查防疫事宜云。
《申报》
民国五年一月十三日"
label_settings = SubResource("LabelSettings_c3c2j") label_settings = SubResource("LabelSettings_c3c2j")
vertical_alignment = 1 vertical_alignment = 1
autowrap_mode = 3 autowrap_mode = 3
[node name="MarginContainer" type="MarginContainer" parent="InspectLayer/AspectRatioContainer"] [node name="MarginContainer" type="MarginContainer" parent="InspectLayer/Root"]
layout_mode = 2 layout_mode = 2
offset_top = 263.0
offset_right = 564.0
offset_bottom = 316.0
size_flags_vertical = 8 size_flags_vertical = 8
mouse_filter = 2 mouse_filter = 2
theme_override_constants/margin_bottom = 38 theme_override_constants/margin_bottom = 38
[node name="TipLabel" type="Label" parent="InspectLayer/AspectRatioContainer/MarginContainer"] [node name="TipLabel" type="Label" parent="InspectLayer/Root/MarginContainer"]
unique_name_in_owner = true unique_name_in_owner = true
modulate = Color(1, 1, 1, 0) modulate = Color(1, 1, 1, 0)
z_index = 100 z_index = 100
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 4 size_flags_horizontal = 4
size_flags_vertical = 8 size_flags_vertical = 8
text = "Q: 退出 E: 阅读" text = "Q: ui_退出 E: ui_阅读"
horizontal_alignment = 1 horizontal_alignment = 1
vertical_alignment = 1 vertical_alignment = 1

View File

@ -1,6 +1,7 @@
@tool @tool
extends Sprite2D extends Sprite2D
@export_enum("os", "ballon") var mode = "os"
@export_enum("items", "c01", "c02", "c03", "c04", "c05", "c06") var dialogue := "items": @export_enum("items", "c01", "c02", "c03", "c04", "c05", "c06") var dialogue := "items":
set(val): set(val):
dialogue = val dialogue = val
@ -14,7 +15,7 @@ extends Sprite2D
if is_node_ready(): if is_node_ready():
notify_property_list_changed() notify_property_list_changed()
var note_key := "" var note_key := ""
@export_enum("none", "notes", "c01", "c02", "c03", "c04", "c05", "c06") var editor_filter := "notes": @export_enum("none", "notes", "c01", "c02", "c03", "c04", "c05", "c06") var editor_filter := "none":
set(val): set(val):
editor_filter = val editor_filter = val
if is_node_ready(): if is_node_ready():
@ -34,6 +35,8 @@ var mutex = Mutex.new()
func _ready() -> void: func _ready() -> void:
if Engine.is_editor_hint():
return
area2d.body_entered.connect(_reset) area2d.body_entered.connect(_reset)
area2d.body_exited.connect(_on_cancel) area2d.body_exited.connect(_on_cancel)
sign_mark.interacted.connect(_on_interacted) sign_mark.interacted.connect(_on_interacted)
@ -47,15 +50,14 @@ func _on_interacted() -> void:
printerr("Note key is not set") printerr("Note key is not set")
return return
%Sfx.play() %Sfx.play()
# SceneManager.focus_node(self) match mode:
# CameraFocusMarker.tween_zoom(1.1, 1.5) "os":
# DialogueManager.show_dialogue_balloon(dialogue_res, note_key) _show_os()
# # TODO note viewing animation "ballon":
# SceneManager.freeze_player(0, "") _show_balloon()
# interacting = true
# DialogueManager.dialogue_ended.connect(_on_dialogue_ended, CONNECT_ONE_SHOT)
# var player = SceneManager.get_player() func _show_os():
# DialogueManager.show_dialogue_balloon_scene(player, dialogue_res, note_key)
var lines = [] var lines = []
var current_line = await dialogue_res.get_next_dialogue_line(note_key) var current_line = await dialogue_res.get_next_dialogue_line(note_key)
while current_line: while current_line:
@ -64,16 +66,28 @@ func _on_interacted() -> void:
current_line = await dialogue_res.get_next_dialogue_line(current_line.next_id) current_line = await dialogue_res.get_next_dialogue_line(current_line.next_id)
else: else:
break break
# if current_line.has("text"):
# lines.append(current_line)
# if current_line.has("next_id") and current_line.next_id != "end":
# current_line = dialogue_res.lines[current_line.next_id]
# else:
# break
SceneManager.pop_os(lines) SceneManager.pop_os(lines)
SceneManager.freeze_player(1.0, "") SceneManager.freeze_player(1.0, "")
func _show_balloon():
# SceneManager.focus_node(self)
# CameraFocusMarker.tween_zoom(1.1, 1.5)
DialogueManager.show_dialogue_balloon(dialogue_res, note_key)
# TODO note viewing animation
SceneManager.freeze_player(0, "")
interacting = true
DialogueManager.dialogue_ended.connect(_on_ballon_ended, CONNECT_ONE_SHOT)
# var player = SceneManager.get_player()
# DialogueManager.show_dialogue_balloon_scene(player, dialogue_res, note_key)
func _on_ballon_ended(_res):
interacting = false
SceneManager.release_player()
# SceneManager.focus_player_and_reset_zoom()
func _set(property: StringName, value: Variant) -> bool: func _set(property: StringName, value: Variant) -> bool:
if property == "note_key": if property == "note_key":
note_key = value note_key = value
@ -93,10 +107,10 @@ func _get_property_list() -> Array[Dictionary]:
# only show notes_ properties in editor # only show notes_ properties in editor
var titles = "" var titles = ""
if Engine.is_editor_hint() and editor_filter and editor_filter != "none": if Engine.is_editor_hint() and editor_filter and editor_filter != "none":
var filted_titles = dialogue_res.titles.keys().filter(_filter_property) var filted_titles = dialogue_res.get_ordered_titles().filter(_filter_property)
titles = ",".join(filted_titles) titles = ",".join(filted_titles)
else: else:
titles = ",".join(dialogue_res.titles.keys()) titles = ",".join(dialogue_res.get_ordered_titles())
return [ return [
{ {
"name": "note_key", "name": "note_key",
@ -111,12 +125,6 @@ func _filter_property(property: StringName) -> bool:
return property.find(editor_filter) >= 0 return property.find(editor_filter) >= 0
# func _on_dialogue_ended(_res):
# interacting = false
# SceneManager.release_player()
# SceneManager.focus_player_and_reset_zoom()
func _on_cancel(_body = null): func _on_cancel(_body = null):
interacting = false interacting = false

View File

@ -12,7 +12,6 @@ size = Vector2(40, 60)
[node name="Note" type="Sprite2D"] [node name="Note" type="Sprite2D"]
script = ExtResource("1_3igk8") script = ExtResource("1_3igk8")
editor_filter = "notes_"
note_key = "" note_key = ""
[node name="Sfx" parent="." instance=ExtResource("2_qocmg")] [node name="Sfx" parent="." instance=ExtResource("2_qocmg")]

View File

@ -77,6 +77,6 @@ func _get_property_list() -> Array[Dictionary]:
"name": "dialogue_title", "name": "dialogue_title",
"type": TYPE_STRING, "type": TYPE_STRING,
"hint": PROPERTY_HINT_ENUM_SUGGESTION, "hint": PROPERTY_HINT_ENUM_SUGGESTION,
"hint_string": ",".join(dialogue_res.titles.keys()) "hint_string": ",".join(dialogue_res.get_ordered_titles())
} }
] ]

View File

@ -1,5 +1,7 @@
# @tool
extends Sprite2D extends Sprite2D
@export var immediately := true
@export_enum("left", "right", "1", "2", "3", "4", "5", "6", "7", "8", "9") var portal_name := "left": @export_enum("left", "right", "1", "2", "3", "4", "5", "6", "7", "8", "9") var portal_name := "left":
set(value): set(value):
#if portal_name: #if portal_name:
@ -10,7 +12,13 @@ extends Sprite2D
@export var target_scene := "c02_s00" @export var target_scene := "c02_s00"
@export_enum("none", "left", "right", "1", "2", "3", "4", "5", "6", "7", "8", "9") @export_enum("none", "left", "right", "1", "2", "3", "4", "5", "6", "7", "8", "9")
var target_portal := "none" var target_portal := "none"
@export var default_texture: Texture2D
@export var opened_texture: Texture2D
@export var opened := false:
set(new_val):
opened = new_val
if is_node_ready():
_checkout_texture()
@onready var sign_mark = %Sign as Sign @onready var sign_mark = %Sign as Sign
@onready var area2d = %Area2D as Area2D @onready var area2d = %Area2D as Area2D
@ -22,6 +30,9 @@ var action_times := 0
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready() -> void: func _ready() -> void:
name = "portal_" + portal_name name = "portal_" + portal_name
_checkout_texture()
if Engine.is_editor_hint():
return
area2d.body_entered.connect(_reset) area2d.body_entered.connect(_reset)
area2d.body_exited.connect(_on_cancel) area2d.body_exited.connect(_on_cancel)
sign_mark.interacted.connect(_on_interacted) sign_mark.interacted.connect(_on_interacted)
@ -34,6 +45,11 @@ func _ready() -> void:
# label.name = "Label" # label.name = "Label"
# add_child(label) # add_child(label)
func _checkout_texture():
if opened:
texture = opened_texture
else:
texture = default_texture
func _on_interacted() -> void: func _on_interacted() -> void:
if target_portal == "none": if target_portal == "none":
@ -44,7 +60,7 @@ func _on_interacted() -> void:
print("传送前往", target_scene, target_portal) print("传送前往", target_scene, target_portal)
var ground_loader = SceneManager.get_ground_loader() as GroundLoader var ground_loader = SceneManager.get_ground_loader() as GroundLoader
if ground_loader: if ground_loader:
ground_loader.transition_to_scene(target_scene, target_portal) ground_loader.transition_to_scene(target_scene, target_portal, immediately)
func _on_cancel(_body = null): func _on_cancel(_body = null):
@ -54,7 +70,6 @@ func _on_cancel(_body = null):
func _reset(_body): func _reset(_body):
activated = true activated = true
# 暂时不启用自动传送 # 暂时不启用自动传送
# func _input(event: InputEvent) -> void: # func _input(event: InputEvent) -> void:
# # 长按自动传送 # # 长按自动传送

View File

@ -10,7 +10,7 @@
resource_local_to_scene = true resource_local_to_scene = true
size = Vector2(45, 130) size = Vector2(45, 130)
[node name="Portal" type="Sprite2D"] [node name="portal_left" type="Sprite2D"]
script = ExtResource("1_jyh6v") script = ExtResource("1_jyh6v")
[node name="Sfx" parent="." instance=ExtResource("3_6khux")] [node name="Sfx" parent="." instance=ExtResource("3_6khux")]

View File

@ -103,6 +103,14 @@ func _unhandled_input(event: InputEvent) -> void:
if activated: if activated:
if event.is_action_pressed("interact"): if event.is_action_pressed("interact"):
interacted.emit() interacted.emit()
if is_inside_tree():
# grab focus 放在 emit 后面,避免在 emit 时 prop hud 失去 focus
# 传送时会导致 is_inside_tree 为 false此时也无需与 prop hud 抢占 focus
focus_mode = FOCUS_ALL
grab_focus()
elif event.is_action_pressed("cancel"): elif event.is_action_pressed("cancel"):
cancel.emit() cancel.emit()
get_viewport().set_input_as_handled() release_focus()
var viewport = get_viewport()
if viewport:
viewport.set_input_as_handled()

View File

@ -24,6 +24,8 @@ func _ready() -> void:
script = ExtResource("1_0vrlo") script = ExtResource("1_0vrlo")
scene_config = SubResource("Resource_6ux50") scene_config = SubResource("Resource_6ux50")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
[node name="BGColorRect" type="ColorRect" parent="."] [node name="BGColorRect" type="ColorRect" parent="."]
custom_minimum_size = Vector2(664, 318) custom_minimum_size = Vector2(664, 318)
anchors_preset = 4 anchors_preset = 4
@ -45,10 +47,10 @@ offset = Vector2(0, -120)
[node name="DeployLayer" type="Node2D" parent="."] [node name="DeployLayer" type="Node2D" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
[node name="PortalLeft" parent="DeployLayer" instance=ExtResource("3_t73yw")] [node name="portal_left" parent="DeployLayer" instance=ExtResource("3_t73yw")]
position = Vector2(26, -1) position = Vector2(26, -1)
[node name="PortalRight" parent="DeployLayer" instance=ExtResource("3_t73yw")] [node name="portal_right" parent="DeployLayer" instance=ExtResource("3_t73yw")]
position = Vector2(530, 0) position = Vector2(530, 0)
portal_name = "right" portal_name = "right"

View File

@ -31,7 +31,7 @@ func _ready() -> void:
entrance_portal = archive_portal entrance_portal = archive_portal
if current_scene and entrance_portal: if current_scene and entrance_portal:
transition_to_scene(current_scene, entrance_portal, true) transition_to_scene(current_scene, entrance_portal, true)
elif ground: elif ground:
ground.queue_free() ground.queue_free()
ground = null ground = null
@ -124,7 +124,7 @@ func _set_camera_and_player_boundary():
var bg = ground.get_node("BGSprite2D") var bg = ground.get_node("BGSprite2D")
# set current_boarder by bg size # set current_boarder by bg size
if bg.texture and not Engine.is_editor_hint(): if bg.texture and not Engine.is_editor_hint():
var size = bg.texture.get_size() var size = bg.texture.get_size() * bg.scale
# camera rect # camera rect
var camera_size = Vector2(max(564.0, size.x), max(size.y, 316.0)) var camera_size = Vector2(max(564.0, size.x), max(size.y, 316.0))
var camera_upleft = Vector2(0, -camera_size.y / 2.0) var camera_upleft = Vector2(0, -camera_size.y / 2.0)

View File

@ -1,15 +1,22 @@
[gd_scene load_steps=12 format=3 uid="uid://dlx5xxbg53rb8"] [gd_scene load_steps=22 format=3 uid="uid://dlx5xxbg53rb8"]
[ext_resource type="PackedScene" uid="uid://dayyx4jerj7io" path="res://scene/ground/ground.tscn" id="1_ff4yb"] [ext_resource type="PackedScene" uid="uid://dayyx4jerj7io" path="res://scene/ground/ground.tscn" id="1_ff4yb"]
[ext_resource type="Script" path="res://config/deploy/scene_config.gd" id="2_ve5ly"] [ext_resource type="Script" path="res://config/deploy/scene_config.gd" id="2_ve5ly"]
[ext_resource type="Texture2D" uid="uid://bx5we5pgnlhl5" path="res://asset/art/scene/c01/s05_院长房间/bg_房间背景.png" id="3_3r1q2"]
[ext_resource type="Texture2D" uid="uid://dkufmwg07maun" path="res://asset/art/scene/c01/s05_院长房间/全局参考.png" id="3_7u4bh"] [ext_resource type="Texture2D" uid="uid://dkufmwg07maun" path="res://asset/art/scene/c01/s05_院长房间/全局参考.png" id="3_7u4bh"]
[ext_resource type="Texture2D" uid="uid://difymnwnet6lk" path="res://asset/art/scene/c01/s05_院长房间/bg_背景.png" id="3_f4ne6"]
[ext_resource type="Texture2D" uid="uid://bp2r4s6v6ag2f" path="res://asset/art/scene/c01/s05_院长房间/fg_前景.png" id="3_vmr0f"] [ext_resource type="Texture2D" uid="uid://bp2r4s6v6ag2f" path="res://asset/art/scene/c01/s05_院长房间/fg_前景.png" id="3_vmr0f"]
[ext_resource type="Texture2D" uid="uid://ch7ic6i6ewoi7" path="res://asset/art/scene/c01/s05_院长房间/e_门.png" id="4_gdhoy"]
[ext_resource type="Texture2D" uid="uid://bkbr5ubkif1e6" path="res://asset/art/scene/c01/s05_院长房间/e_打开的门.png" id="5_cddn7"] [ext_resource type="Texture2D" uid="uid://bkbr5ubkif1e6" path="res://asset/art/scene/c01/s05_院长房间/e_打开的门.png" id="5_cddn7"]
[ext_resource type="PackedScene" uid="uid://ci5anaxsa1apl" path="res://scene/entity/local_inspectable.tscn" id="6_v72k7"] [ext_resource type="PackedScene" uid="uid://ci5anaxsa1apl" path="res://scene/entity/local_inspectable.tscn" id="6_v72k7"]
[ext_resource type="Texture2D" uid="uid://cpht56skg054p" path="res://asset/art/scene/c01/s05_院长房间/e_座钟.png" id="7_3tetc"] [ext_resource type="Texture2D" uid="uid://cpht56skg054p" path="res://asset/art/scene/c01/s05_院长房间/e_座钟.png" id="7_3tetc"]
[ext_resource type="Texture2D" uid="uid://qw8jwid7j8qw" path="res://asset/art/scene/c01/s05_院长房间/e_床.png" id="7_xakd0"]
[ext_resource type="Texture2D" uid="uid://bt17wvt5nw6a7" path="res://asset/art/scene/c01/s05_院长房间/e_钢琴.png" id="8_mnduo"] [ext_resource type="Texture2D" uid="uid://bt17wvt5nw6a7" path="res://asset/art/scene/c01/s05_院长房间/e_钢琴.png" id="8_mnduo"]
[ext_resource type="Texture2D" uid="uid://iteaoon750bx" path="res://asset/art/scene/c01/s05_院长房间/e_桌椅.png" id="9_x837o"] [ext_resource type="Texture2D" uid="uid://iteaoon750bx" path="res://asset/art/scene/c01/s05_院长房间/e_桌椅.png" id="9_x837o"]
[ext_resource type="PackedScene" uid="uid://jr1yd46wm5je" path="res://scene/entity/note.tscn" id="10_18v0g"]
[ext_resource type="Texture2D" uid="uid://diw7l2qdwbyoc" path="res://asset/art/scene/c01/s05_院长房间/e_画框.png" id="11_6gq1s"]
[ext_resource type="Texture2D" uid="uid://dx3ym8inpuj5b" path="res://asset/art/scene/c01/s05_院长房间/e_鸡毛掸子.png" id="12_jtglg"]
[ext_resource type="PackedScene" uid="uid://cw3q5pvciumil" path="res://scene/entity/interactable.tscn" id="14_lq1ou"]
[ext_resource type="Texture2D" uid="uid://cyqnkcx3qx100" path="res://asset/art/scene/c01/s05_院长房间/l_房间背景.png" id="15_6p040"]
[sub_resource type="Resource" id="Resource_6jwab"] [sub_resource type="Resource" id="Resource_6jwab"]
resource_local_to_scene = true resource_local_to_scene = true
@ -19,43 +26,113 @@ player_y = 45
footstep_type = "concrete" footstep_type = "concrete"
bgm = "" bgm = ""
[sub_resource type="RectangleShape2D" id="RectangleShape2D_6i5gw"]
resource_local_to_scene = true
size = Vector2(40, 60)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_6bim4"]
resource_local_to_scene = true
size = Vector2(10, 60)
[sub_resource type="RectangleShape2D" id="RectangleShape2D_dq2na"]
resource_local_to_scene = true
size = Vector2(10, 60)
[node name="S05院长房间" type="Node2D"] [node name="S05院长房间" type="Node2D"]
[node name="Ground" parent="." instance=ExtResource("1_ff4yb")] [node name="Ground" parent="." instance=ExtResource("1_ff4yb")]
scene_config = SubResource("Resource_6jwab") scene_config = SubResource("Resource_6jwab")
[node name="BGSprite2D" parent="Ground" index="1"] [node name="BGSprite2D" parent="Ground" index="2"]
position = Vector2(45, -38) position = Vector2(23, -118)
texture = ExtResource("3_f4ne6") scale = Vector2(0.333, 0.333)
texture = ExtResource("3_3r1q2")
[node name="PortalLeft" parent="Ground/DeployLayer" index="0"] [node name="portal_right" parent="Ground/DeployLayer" index="1"]
position = Vector2(90, 11) position = Vector2(502, 9)
texture = ExtResource("4_gdhoy")
[node name="PortalRight" parent="Ground/DeployLayer" index="1"] target_scene = "c01_s05"
position = Vector2(473, 19) target_portal = "left"
texture = ExtResource("5_cddn7") default_texture = ExtResource("4_gdhoy")
opened_texture = ExtResource("5_cddn7")
[node name="座钟" parent="Ground/DeployLayer" index="2" instance=ExtResource("6_v72k7")] [node name="座钟" parent="Ground/DeployLayer" index="2" instance=ExtResource("6_v72k7")]
position = Vector2(316, 26) position = Vector2(334, 16)
texture = ExtResource("7_3tetc") texture = ExtResource("7_3tetc")
texture_cover = ExtResource("7_3tetc")
editor_filter = "c01"
content_key = "c01_院长座钟"
[node name="钢琴" parent="Ground/DeployLayer" index="3" instance=ExtResource("6_v72k7")] [node name="床" parent="Ground/DeployLayer" index="3" instance=ExtResource("6_v72k7")]
position = Vector2(232, 57) position = Vector2(84, 45)
texture = ExtResource("7_xakd0")
[node name="钢琴" parent="Ground/DeployLayer" index="4" instance=ExtResource("6_v72k7")]
position = Vector2(413, 47)
texture = ExtResource("8_mnduo") texture = ExtResource("8_mnduo")
[node name="桌椅" type="Sprite2D" parent="Ground/DeployLayer" index="4"] [node name="桌椅" parent="Ground/DeployLayer" index="5" instance=ExtResource("10_18v0g")]
position = Vector2(384, 52) position = Vector2(154, 42)
texture = ExtResource("9_x837o") texture = ExtResource("9_x837o")
editor_filter = "c01"
note_key = "c01_院长书桌"
[node name="Sign" parent="Ground/DeployLayer/桌椅" index="1"]
offset_top = -21.0
offset_bottom = 59.0
[node name="CollisionShape2D" parent="Ground/DeployLayer/桌椅/Area2D" index="0"]
shape = SubResource("RectangleShape2D_6i5gw")
[node name="画框" parent="Ground/DeployLayer" index="6" instance=ExtResource("10_18v0g")]
position = Vector2(277, -28)
texture = ExtResource("11_6gq1s")
editor_filter = "c01"
[node name="Sign" parent="Ground/DeployLayer/画框" index="1"]
offset_left = 6.0
offset_top = -1.0
offset_right = 89.0
offset_bottom = 79.0
[node name="CollisionShape2D" parent="Ground/DeployLayer/画框/Area2D" index="0"]
position = Vector2(11, -1)
shape = SubResource("RectangleShape2D_6bim4")
[node name="鸡毛掸子" parent="Ground/DeployLayer" index="7" instance=ExtResource("10_18v0g")]
position = Vector2(269, 20)
texture = ExtResource("12_jtglg")
editor_filter = "c01"
note_key = "c01_鸡毛掸子"
[node name="Area2D" parent="Ground/DeployLayer/鸡毛掸子" index="3"]
position = Vector2(-7, 0)
[node name="CollisionShape2D" parent="Ground/DeployLayer/鸡毛掸子/Area2D" index="0"]
shape = SubResource("RectangleShape2D_dq2na")
[node name="Interactable" parent="Ground/DeployLayer" index="8" instance=ExtResource("14_lq1ou")]
position = Vector2(210, 36)
[node name="PointLight2D" type="PointLight2D" parent="Ground/AmbientLayer" index="0"]
visible = false
position = Vector2(283, 0)
texture = ExtResource("15_6p040")
texture_scale = 0.33
height = 40.0
[node name="FGSprite2D" parent="Ground/ParallaxForeground/FGParallaxLayer" index="0"] [node name="FGSprite2D" parent="Ground/ParallaxForeground/FGParallaxLayer" index="0"]
position = Vector2(62, 35) position = Vector2(22, 49)
texture = ExtResource("3_vmr0f") texture = ExtResource("3_vmr0f")
[node name="参考" type="Sprite2D" parent="Ground"] [node name="参考" type="Sprite2D" parent="Ground"]
visible = false visible = false
modulate = Color(1, 1, 1, 0.219608) modulate = Color(1, 1, 1, 0.219608)
position = Vector2(276, 2) position = Vector2(281, -1)
scale = Vector2(0.26, 0.26) scale = Vector2(0.333, 0.333)
texture = ExtResource("3_7u4bh") texture = ExtResource("3_7u4bh")
[editable path="Ground"] [editable path="Ground"]
[editable path="Ground/DeployLayer/桌椅"]
[editable path="Ground/DeployLayer/画框"]
[editable path="Ground/DeployLayer/鸡毛掸子"]

View File

@ -22,24 +22,24 @@ scene_config = SubResource("Resource_p1xa1")
[node name="BGSprite2D" parent="Ground" index="1"] [node name="BGSprite2D" parent="Ground" index="1"]
texture = ExtResource("2_ni1a4") texture = ExtResource("2_ni1a4")
[node name="PortalLeft" parent="Ground/DeployLayer" index="0"] [node name="portal_left" parent="Ground/DeployLayer" index="0"]
position = Vector2(78, 27) position = Vector2(78, 27)
[node name="PortalRight" parent="Ground/DeployLayer" index="1"] [node name="portal_right" parent="Ground/DeployLayer" index="1"]
position = Vector2(392, 2) position = Vector2(392, 2)
portal_name = "right"
target_scene = "c02_s02" target_scene = "c02_s02"
target_portal = "left" target_portal = "left"
[node name="Note" parent="Ground/DeployLayer" index="2" instance=ExtResource("3_6lnxd")] [node name="Note" parent="Ground/DeployLayer" index="2" instance=ExtResource("3_6lnxd")]
position = Vector2(250, -22) position = Vector2(250, -22)
editor_filter = "c02"
note_key = "c02_寻人启事" note_key = "c02_寻人启事"
[node name="Note门口" parent="Ground/DeployLayer" index="3" instance=ExtResource("3_6lnxd")] [node name="Note门口" parent="Ground/DeployLayer" index="3" instance=ExtResource("3_6lnxd")]
position = Vector2(311, -27) position = Vector2(311, -27)
mode = "ballon"
dialogue = "c02" dialogue = "c02"
editor_filter = "c02" note_key = "c02_s01_门口"
note_key = "c02_s01_menpai"
[node name="Ambush" parent="Ground/DeployLayer" index="4" instance=ExtResource("6_vgxa0")] [node name="Ambush" parent="Ground/DeployLayer" index="4" instance=ExtResource("6_vgxa0")]
position = Vector2(135, 56) position = Vector2(135, 56)

View File

@ -11,15 +11,13 @@ class_name PropHud extends Control
@export_group("Inventory") @export_group("Inventory")
@export var inventory: PropInventory @export var inventory: PropInventory
@export_group("UI-UX") @export_group("UI-UX")
@export var display_time := 1.5 # 不包含渐入渐出(约 0.6s)的时长 @export var display_time := 2.5 # 不包含渐入渐出(约 0.6s)的时长
@export var locked := false @export var locked := false
@export var selected := false: @export var selected := false:
set(value): set(value):
selected = value selected = value
if value: if is_node_ready():
%Mark.visible = true %Mark.visible = value
else:
%Mark.visible = false
@onready var sfx = %Sfx as Sfx @onready var sfx = %Sfx as Sfx
@onready var left_btn = %LeftButton as TextureButton @onready var left_btn = %LeftButton as TextureButton
@ -31,6 +29,7 @@ class_name PropHud extends Control
@onready var title_label = %TitleLabel as Label @onready var title_label = %TitleLabel as Label
var items_dict := {} var items_dict := {}
# 从配置文件加载 prop items
var item_config_res = preload("res://asset/dialogue/item_description.dialogue") var item_config_res = preload("res://asset/dialogue/item_description.dialogue")
var item_config_title = "PropItems" var item_config_title = "PropItems"
var texture_path_prefix = "res://asset/art/prop/" var texture_path_prefix = "res://asset/art/prop/"
@ -48,25 +47,31 @@ func _ready() -> void:
_load_from_archive() _load_from_archive()
if Engine.is_editor_hint(): if Engine.is_editor_hint():
return return
focus_exited.connect(_on_focus_exited)
ArchiveManager.archive_loaded.connect(_load_from_archive) ArchiveManager.archive_loaded.connect(_load_from_archive)
# tween timer # tween timer
timer.wait_time = display_time timer.wait_time = display_time
timer.one_shot = true timer.one_shot = true
timer.autostart = false timer.autostart = false
timer.timeout.connect(toggle_details.bind(false)) timer.timeout.connect(_on_timer_timeout)
add_child(timer) add_child(timer)
# connect signals # connect signals
left_btn.pressed.connect(on_left_pressed) left_btn.pressed.connect(on_left_pressed)
right_btn.pressed.connect(on_right_pressed) right_btn.pressed.connect(on_right_pressed)
panel.pressed.connect(_on_panel_pressed) panel.pressed.connect(_on_panel_pressed)
mark.modulate.a = 0.0 %Mark.visible = selected
mark.modulate.a = 0.8
title_label.modulate.a = 0.0 title_label.modulate.a = 0.0
# _toggle_btn_ability(false) # _toggle_btn_ability(false)
left_btn.modulate.a = 0.5 left_btn.modulate.a = 0.5
right_btn.modulate.a = 0.5 right_btn.modulate.a = 0.5
mouse_entered.connect(_on_mouse_entered) mouse_entered.connect(_on_mouse_entered)
mouse_exited.connect(_on_mouse_exited) mouse_exited.connect(_on_mouse_exited)
selected = selected
func _on_focus_exited() -> void:
if selected:
selected = false
func _load_items(): func _load_items():
@ -127,7 +132,8 @@ func _update_prop_display_with_texture():
func on_left_pressed() -> void: func on_left_pressed() -> void:
sfx.play() sfx.play()
_mouse_moved_on_listening() _mouse_moved_on_listening()
inventory.index_wrap_add(-1) if inventory.index_wrap_add(-1):
selected = false
_update_prop_display_with_texture() _update_prop_display_with_texture()
_tween_container(true) _tween_container(true)
@ -135,7 +141,8 @@ func on_left_pressed() -> void:
func on_right_pressed() -> void: func on_right_pressed() -> void:
sfx.play() sfx.play()
_mouse_moved_on_listening() _mouse_moved_on_listening()
inventory.index_wrap_add(1) if inventory.index_wrap_add(1):
selected = false
_update_prop_display_with_texture() _update_prop_display_with_texture()
_tween_container(false) _tween_container(false)
@ -154,6 +161,10 @@ func _tween_container(left_to_right := true) -> void:
func _on_panel_pressed() -> void: func _on_panel_pressed() -> void:
sfx.play() sfx.play()
if not selected:
focus_mode = FOCUS_ALL
grab_focus()
selected = true
_mouse_moved_on_listening() _mouse_moved_on_listening()
print("panel") print("panel")
@ -174,6 +185,10 @@ func _mouse_moved_on_listening() -> void:
timer.start(display_time) timer.start(display_time)
func _on_timer_timeout() -> void:
toggle_details(false)
func _unhandled_input(event: InputEvent) -> void: func _unhandled_input(event: InputEvent) -> void:
if locked: if locked:
return return
@ -183,6 +198,9 @@ func _unhandled_input(event: InputEvent) -> void:
elif event.is_action_pressed("prop_right"): elif event.is_action_pressed("prop_right"):
on_right_pressed() on_right_pressed()
get_viewport().set_input_as_handled() get_viewport().set_input_as_handled()
elif event.is_action_pressed("prop_select"):
_on_panel_pressed()
get_viewport().set_input_as_handled()
func _input(event: InputEvent) -> void: func _input(event: InputEvent) -> void:
@ -199,19 +217,18 @@ func toggle_details(display := true) -> void:
if display: if display:
displaying = true displaying = true
_toggle_btn_ability(true) _toggle_btn_ability(true)
display_tween.tween_property(mark, "modulate:a", 0.5, 0.2) display_tween.parallel().tween_property(title_label, "modulate:a", 1.0, 0.3)
display_tween.parallel().tween_property(title_label, "modulate:a", 1.0, 0.2) display_tween.parallel().tween_property(left_btn, "modulate:a", 1.0, 0.3)
display_tween.parallel().tween_property(left_btn, "modulate:a", 1.0, 0.5) display_tween.parallel().tween_property(right_btn, "modulate:a", 1.0, 0.3)
display_tween.parallel().tween_property(right_btn, "modulate:a", 1.0, 0.5) display_tween.parallel().tween_property(mark, "modulate:a", 1.0, 0.3)
display_tween.tween_property(mark, "modulate:a", 1.0, 0.2)
display_tween.parallel().tween_property(mark, "scale", Vector2(1.1, 1.1), 0.3).set_trans( display_tween.parallel().tween_property(mark, "scale", Vector2(1.1, 1.1), 0.3).set_trans(
Tween.TRANS_CUBIC Tween.TRANS_CUBIC
) )
display_tween.tween_property(mark, "scale", Vector2.ONE, 0.3).set_trans(Tween.TRANS_CUBIC) display_tween.tween_property(mark, "scale", Vector2.ONE, 0.2).set_trans(Tween.TRANS_CUBIC)
timer.start(display_time) timer.start(display_time)
else: else:
displaying = false displaying = false
display_tween.tween_property(mark, "modulate:a", 0.0, 0.6) display_tween.tween_property(mark, "modulate:a", 0.8, 0.6)
display_tween.parallel().tween_property(title_label, "modulate:a", 0.0, 0.6) display_tween.parallel().tween_property(title_label, "modulate:a", 0.0, 0.6)
display_tween.parallel().tween_property(left_btn, "modulate:a", 0.5, 0.5) display_tween.parallel().tween_property(left_btn, "modulate:a", 0.5, 0.5)
display_tween.parallel().tween_property(right_btn, "modulate:a", 0.5, 0.5) display_tween.parallel().tween_property(right_btn, "modulate:a", 0.5, 0.5)
@ -233,3 +250,15 @@ func enable_prop_item(prop_key: String) -> void:
inventory.enable_item(prop_key) inventory.enable_item(prop_key)
_load_texture_cache() _load_texture_cache()
_update_prop_display_with_texture() _update_prop_display_with_texture()
# save to archive immediately
ArchiveManager.save_all()
func disable_prop_item(prop_key: String) -> void:
if not inventory or not prop_key:
return
inventory.disable_item(prop_key)
_load_texture_cache()
_update_prop_display_with_texture()
# save to archive immediately
ArchiveManager.save_all()

View File

@ -21,7 +21,6 @@ offset_bottom = 504.0
scale = Vector2(0.3, 0.3) scale = Vector2(0.3, 0.3)
mouse_filter = 1 mouse_filter = 1
script = ExtResource("1_bbv0a") script = ExtResource("1_bbv0a")
enable_item = false
[node name="VBoxContainer" type="VBoxContainer" parent="."] [node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 0 layout_mode = 0
@ -70,6 +69,7 @@ offset_right = 65.0
offset_bottom = 65.0 offset_bottom = 65.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
mouse_filter = 1
[node name="PropContainer" type="CenterContainer" parent="VBoxContainer/HBoxContainer/HudPanel/Container"] [node name="PropContainer" type="CenterContainer" parent="VBoxContainer/HBoxContainer/HudPanel/Container"]
unique_name_in_owner = true unique_name_in_owner = true
@ -93,6 +93,7 @@ texture = ExtResource("8_l2cwd")
[node name="Mark" type="TextureRect" parent="VBoxContainer/HBoxContainer/HudPanel"] [node name="Mark" type="TextureRect" parent="VBoxContainer/HBoxContainer/HudPanel"]
unique_name_in_owner = true unique_name_in_owner = true
visible = false
layout_mode = 1 layout_mode = 1
anchors_preset = 3 anchors_preset = 3
anchor_left = 1.0 anchor_left = 1.0

View File

@ -16,7 +16,16 @@ func enable_item(prop_key: String) -> void:
# emit_changed() # emit_changed()
func index_wrap_add(delta: int) -> void: func disable_item(prop_key: String) -> void:
if enabled_items.has(prop_key):
enabled_items.erase(prop_key)
# wrap index
current_index = wrapi(current_index, 0, enabled_items.size())
# return true if the index changed
func index_wrap_add(delta: int) -> bool:
current_index += delta current_index += delta
current_index = wrapi(current_index, 0, enabled_items.size()) current_index = wrapi(current_index, 0, enabled_items.size())
# emit_changed() # emit_changed()
return not enabled_items.is_empty()

View File

@ -19,6 +19,7 @@ environment = ExtResource("9_jsof5")
[node name="GroundLoader" parent="." instance=ExtResource("10_8rc5n")] [node name="GroundLoader" parent="." instance=ExtResource("10_8rc5n")]
position = Vector2(1, 0) position = Vector2(1, 0)
current_scene = "c01_s05"
[node name="MainPlayer" parent="." instance=ExtResource("6_6geb0")] [node name="MainPlayer" parent="." instance=ExtResource("6_6geb0")]
unique_name_in_owner = true unique_name_in_owner = true
@ -29,7 +30,6 @@ scale = Vector2(0.6, 0.6)
[node name="PropInspector" parent="." instance=ExtResource("5_ux0rw")] [node name="PropInspector" parent="." instance=ExtResource("5_ux0rw")]
unique_name_in_owner = true unique_name_in_owner = true
visible = false
[node name="UILayer" type="CanvasLayer" parent="."] [node name="UILayer" type="CanvasLayer" parent="."]
layer = 12 layer = 12
@ -74,7 +74,7 @@ metadata/_edit_use_anchors_ = true
[node name="PropHUD" parent="UILayer" instance=ExtResource("4_t7gb2")] [node name="PropHUD" parent="UILayer" instance=ExtResource("4_t7gb2")]
scale = Vector2(0.24, 0.24) scale = Vector2(0.24, 0.24)
enable_item = null display_time = 1.5
metadata/_edit_use_anchors_ = true metadata/_edit_use_anchors_ = true
[node name="Journal" parent="." instance=ExtResource("10_durpa")] [node name="Journal" parent="." instance=ExtResource("10_durpa")]

View File

@ -12,6 +12,8 @@ enum MOVEMENT_STATUS {
CLIMBING, CLIMBING,
} }
@export var shadow_color := Color(0.1, 0.1, 0.1, 0.7)
var shadow_y := 0.0
@export var player_movement_rect := Rect2(50, -500, 1400, 1000) @export var player_movement_rect := Rect2(50, -500, 1400, 1000)
@export var velocity_ratio := 1.0 @export var velocity_ratio := 1.0
@export var action_locked := false: @export var action_locked := false:
@ -44,15 +46,20 @@ enum MOVEMENT_STATUS {
@onready var footstep_timer = %FootstepTimer as Timer @onready var footstep_timer = %FootstepTimer as Timer
@onready var sprite = %AnimatedSprite2D as AnimatedSprite2D @onready var sprite = %AnimatedSprite2D as AnimatedSprite2D
@onready var os_pivot = %OSPivot as Control @onready var os_pivot = %OSPivot as Control
@onready var os_contaner = %PanelContainer as PanelContainer
@onready var os_label = %OSLabel as DialogueLabel @onready var os_label = %OSLabel as DialogueLabel
# animation -> {frame -> {shadow polygon}}
var animation_shadow_polygons = {}
func _ready() -> void: func _ready() -> void:
# _reset_face_direction() # _reset_face_direction()
footstep_timer.timeout.connect(_on_footstep_timer_timeout) footstep_timer.timeout.connect(_on_footstep_timer_timeout)
footstep_timer.stop() footstep_timer.stop()
SceneManager.focus_player() SceneManager.focus_player()
os_label.modulate.a = 0.0 os_contaner.modulate.a = 0.0
sprite.frame_changed.connect(queue_redraw)
func _on_footstep_timer_timeout(): func _on_footstep_timer_timeout():
@ -118,7 +125,7 @@ func set_facing_direction(direction: Vector2) -> void:
func _play_animation() -> void: func _play_animation() -> void:
# reset the os label position on animation changed. # reset the os label position on animation changed.
_reset_os_position() _reset_os_and_shadow_position()
match current_status: match current_status:
MOVEMENT_STATUS.IDLE: MOVEMENT_STATUS.IDLE:
if facing_direction.x > 0.0: if facing_direction.x > 0.0:
@ -153,16 +160,16 @@ func _play_animation() -> void:
sprite.play(&"laying_moving_l") sprite.play(&"laying_moving_l")
footstep_timer.wait_time = 2.0 / 3.0 footstep_timer.wait_time = 2.0 / 3.0
footstep_timer.start() footstep_timer.start()
MOVEMENT_STATUS.CLIMBING_STAY: # MOVEMENT_STATUS.CLIMBING_STAY:
sprite.play(&"climbing_stay") # sprite.play(&"climbing_stay")
footstep_timer.stop() # footstep_timer.stop()
MOVEMENT_STATUS.CLIMBING: # MOVEMENT_STATUS.CLIMBING:
if facing_direction.y > 0.0: # if facing_direction.y > 0.0:
sprite.play(&"climbing_down") # sprite.play(&"climbing_down")
else: # else:
sprite.play(&"climbing_up") # sprite.play(&"climbing_up")
footstep_timer.wait_time = 2.0 / 3.0 # footstep_timer.wait_time = 2.0 / 3.0
footstep_timer.start() # footstep_timer.start()
func _get_speed(direction: Vector2) -> Vector2: func _get_speed(direction: Vector2) -> Vector2:
@ -239,10 +246,61 @@ func release_player():
_play_animation() _play_animation()
func _reset_os_position(): func _draw() -> void:
var animation = sprite.animation
if not animation:
return
if not animation_shadow_polygons.has(animation):
_build_shadow_polygons(animation)
var animation_polygons = animation_shadow_polygons[animation]
if animation_polygons.has(sprite.frame):
draw_polygon(animation_polygons[sprite.frame], [shadow_color])
else:
printerr("No shadow polygon found for frame %d" % sprite.frame)
func _build_shadow_polygons(animation):
var frames = sprite.sprite_frames
var coords_dict = {}
for i in frames.get_frame_count(animation):
var texture = frames.get_frame_texture(animation, i) as Texture2D
if not texture:
continue
var image = texture.get_image()
var x_min = 10000
var x_max = -1
for y in range(texture.get_height()):
for x in range(texture.get_width()):
var color = image.get_pixel(x, y)
if color.a > 0.0:
x_min = min(x_min, x)
x_max = max(x_max, x)
if x_min >= x_max:
continue
var oval_ab: Vector2
oval_ab.x = (x_max - x_min) * 0.5
oval_ab.y = max(3.0, oval_ab.x * 0.12)
var x_offset = (x_max - x_min) * 0.5 + x_min - texture.get_width() * 0.5
var coords: PackedVector2Array
# build shadow oval shape with segments.
var segments = 16
for j in range(segments):
var angle = PI * 2 / segments * j
var x = cos(angle) * oval_ab.x + x_offset
var y = sin(angle) * oval_ab.y + shadow_y
coords.append(Vector2(x, y))
coords_dict[i] = coords
animation_shadow_polygons[animation] = coords_dict
func _reset_os_and_shadow_position():
if sprite.animation: if sprite.animation:
var size = sprite.sprite_frames.get_frame_texture(sprite.animation, 0).get_size() var texture = sprite.sprite_frames.get_frame_texture(sprite.animation, 0) as Texture2D
var size = texture.get_size()
# reset the os label position
os_pivot.position.y = -size.y * 0.5 - 4.0 os_pivot.position.y = -size.y * 0.5 - 4.0
# reset the shadow position
shadow_y = size.y * 0.5
var os_tween: Tween var os_tween: Tween
@ -253,13 +311,13 @@ func pop_os(lines := []):
os_tween.kill() os_tween.kill()
os_tween = create_tween() os_tween = create_tween()
os_label.text = "" os_label.text = ""
os_tween.tween_property(os_label, "modulate:a", 1.0, 0.1) os_tween.tween_property(os_contaner, "modulate:a", 1.0, 0.2)
for line in lines: for line in lines:
var duration = max(min(4.0, line.text.length() * 0.2), 2.0) var duration = max(min(4.0, line.text.length() * 0.2), 2.0) - 0.4
os_tween.tween_callback(_os_load_line.bind(line)) os_tween.tween_callback(_os_load_line.bind(line))
os_tween.tween_callback(os_label.type_out) os_tween.tween_callback(os_label.type_out)
os_tween.tween_interval(duration) os_tween.tween_interval(duration)
os_tween.tween_property(os_label, "modulate:a", 0.0, 0.1) os_tween.tween_property(os_contaner, "modulate:a", 0.0, 0.2)
func _os_load_line(line): func _os_load_line(line):

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=7 format=3 uid="uid://cjhw5ecygrqty"] [gd_scene load_steps=8 format=3 uid="uid://cjhw5ecygrqty"]
[ext_resource type="Script" path="res://scene/player/main_player.gd" id="1_3a78y"] [ext_resource type="Script" path="res://scene/player/main_player.gd" id="1_3a78y"]
[ext_resource type="SpriteFrames" uid="uid://c3s8u4ifaucpj" path="res://config/animation/entity_sprite_frames.tres" id="2_3w63u"] [ext_resource type="SpriteFrames" uid="uid://c3s8u4ifaucpj" path="res://config/animation/entity_sprite_frames.tres" id="2_3w63u"]
@ -9,6 +9,18 @@
[sub_resource type="RectangleShape2D" id="RectangleShape2D_fno82"] [sub_resource type="RectangleShape2D" id="RectangleShape2D_fno82"]
size = Vector2(78.25, 205.062) size = Vector2(78.25, 205.062)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_lq4rc"]
bg_color = Color(0.0313726, 0.0313726, 0.0313726, 0.729412)
border_color = Color(0.8, 0.8, 0.8, 0.160784)
corner_radius_top_left = 6
corner_radius_top_right = 6
corner_radius_bottom_right = 6
corner_radius_bottom_left = 6
expand_margin_left = 6.0
expand_margin_top = 6.0
expand_margin_right = 6.0
expand_margin_bottom = 6.0
[node name="MainPlayer" type="CharacterBody2D"] [node name="MainPlayer" type="CharacterBody2D"]
collision_mask = 2 collision_mask = 2
script = ExtResource("1_3a78y") script = ExtResource("1_3a78y")
@ -38,26 +50,39 @@ layout_mode = 3
anchors_preset = 0 anchors_preset = 0
offset_top = -20.0 offset_top = -20.0
offset_bottom = -20.0 offset_bottom = -20.0
mouse_filter = 2
[node name="MarginContainer" type="MarginContainer" parent="OSPivot"] [node name="MarginContainer" type="MarginContainer" parent="OSPivot"]
custom_minimum_size = Vector2(100, 0) custom_minimum_size = Vector2(120, 0)
layout_mode = 1 layout_mode = 1
anchors_preset = 8 anchors_preset = 7
anchor_left = 0.5 anchor_left = 0.5
anchor_top = 0.5 anchor_top = 1.0
anchor_right = 0.5 anchor_right = 0.5
anchor_bottom = 0.5 anchor_bottom = 1.0
offset_left = -25.0 offset_left = -60.0
offset_top = -6.0 offset_top = -12.0
offset_right = 25.0 offset_right = 60.0
offset_bottom = 6.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 0
size_flags_horizontal = 4
size_flags_vertical = 8
mouse_filter = 2
[node name="OSLabel" type="RichTextLabel" parent="OSPivot/MarginContainer"] [node name="PanelContainer" type="PanelContainer" parent="OSPivot/MarginContainer"]
unique_name_in_owner = true unique_name_in_owner = true
custom_minimum_size = Vector2(50, 0) custom_minimum_size = Vector2(100, 0)
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
mouse_filter = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_lq4rc")
[node name="OSLabel" type="RichTextLabel" parent="OSPivot/MarginContainer/PanelContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(120, 0)
layout_mode = 2
size_flags_vertical = 8
mouse_filter = 2 mouse_filter = 2
theme_override_fonts/normal_font = ExtResource("4_4jk1c") theme_override_fonts/normal_font = ExtResource("4_4jk1c")
bbcode_enabled = true bbcode_enabled = true

View File

@ -9,6 +9,7 @@ font_size = 11
[node name="PropInspector" type="CanvasLayer"] [node name="PropInspector" type="CanvasLayer"]
layer = 11 layer = 11
visible = false
script = ExtResource("1_2wpwe") script = ExtResource("1_2wpwe")
[node name="TextureRect" type="TextureRect" parent="."] [node name="TextureRect" type="TextureRect" parent="."]