/
PGStudio
/
DiplomaProject
Обзор
Документация
Войти
/
PGStudio
/
DiplomaProject
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
scripts/VisualNovel.gd
226 строк
10 KB
PGStudio
-
21 июн 2026, 23:04
21 июн 2026, 23:04
c8a06fe
Код
Авторство
О чём код?
extends Node2D # INITIALIZATION @export var background: PackedScene @export var textbox: PackedScene @export var textbox_max_height: float @export var textbox_timer_character: float @export var selection_screen: PackedScene @export var selection_screen_max_size: float @export var selection_screen_count_buttons: int @export var display_characters_aspect: float @onready var DisplayBackgrounds: Node2D = $DisplayBackgrounds @onready var DisplayCharacters: Node2D = $DisplayCharacters @onready var Textbox: Node2D = $Textbox @onready var SelectionScreen: Node2D = $SelectionScreen static var AUTOLOAD_ORDER: int = -1 static var AUTOLOAD_SCENE: String = "" var Order: int = 0 var Procedure: Array var Sleep: Timer var AutoPlay: bool = false var Labels: Dictionary[String, int] # BASE FUNCTIONS func _ready() -> void: get_viewport().size_changed.connect(adaptive_ui) DisplayCharacters.set_aspect(display_characters_aspect) Textbox.set_textbox(textbox) Textbox.set_timer_character(textbox_timer_character) SelectionScreen.set_selection_screen(selection_screen, selection_screen_count_buttons) SelectionScreen.set_active(false) Sleep = Timer.new() add_child(Sleep) Sleep.wait_time = 1.175494E-38 Sleep.timeout.connect(func(): adaptive_ui() Sleep.timeout.disconnect(Sleep.timeout.get_connections()[0]["callable"]) Sleep.timeout.connect(execute_procedure) Sleep.start() ) Sleep.start() func _process(_delta: float) -> void: DisplayServer.window_set_title("FPS: " + str(Engine.get_frames_per_second())) if Input.is_action_just_pressed("next_action") && !SelectionScreen.is_active(): execute_procedure() if Input.is_action_just_pressed("scroll_up"): Textbox.scroll_up() if Input.is_action_just_pressed("scroll_down"): Textbox.scroll_down() #if Input.is_action_just_pressed("exit"): # get_parent().queue_free() # get_tree().change_scene_to_file("res://scenes/UI/StartMenu.tscn") func execute_procedure() -> void: if AUTOLOAD_ORDER != -1: while AUTOLOAD_ORDER - 1 > Order: Procedure[Order][0][1].callv(Procedure[Order][1]) SelectionScreen.set_active(false) Order = Order + 1 DisplayBackgrounds.skip_animation() DisplayCharacters.skip_animation() AUTOLOAD_ORDER = -1 AUTOLOAD_SCENE = "" return if Textbox.is_finish_message() == false: Textbox.skip_animation_message(); return if Order >= Procedure.size(): get_parent().queue_free(); get_tree().change_scene_to_file("res://scenes/UI/StartMenu.tscn"); return print(str(Order) + "/" + str(Procedure.size() - 1) + ": [", Procedure[Order][0][0], " , ", Procedure[Order][1], " , ", Procedure[Order][2].wait_sec, " sec]") Sleep.wait_time = Procedure[Order][2].wait_sec + 1.175494E-38 Sleep.start() Procedure[Order][0][1].callv(Procedure[Order][1]) if Procedure[Order][0][0] == "selections": Textbox.modulate = Textbox.modulate.darkened(0.5) DisplayBackgrounds.modulate = DisplayBackgrounds.modulate.darkened(0.5) DisplayCharacters.modulate = DisplayCharacters.modulate.darkened(0.5) Order = Order + 1 func adaptive_ui() -> void: var scale_background: float if get_viewport_rect().size.aspect() / DisplayBackgrounds.get_aspect() > 1.0: scale_background = get_viewport_rect().size.x / DisplayBackgrounds.get_size().x else: scale_background = get_viewport_rect().size.y / DisplayBackgrounds.get_size().y DisplayBackgrounds.scale = Vector2(scale_background, scale_background) DisplayBackgrounds.position = (get_viewport_rect().size - DisplayBackgrounds.get_size() * scale_background) / 2.0 var scale_display_characters: float scale_display_characters = get_viewport_rect().size.y / DisplayCharacters.CurrentSubViewport.size.y DisplayCharacters.scale = Vector2(scale_display_characters, scale_display_characters) DisplayCharacters.position = (get_viewport_rect().size - DisplayCharacters.get_size() * scale_display_characters) / 2.0 var scale_textbox: float = get_viewport_rect().size.y / Textbox.get_size().y scale_textbox = min(scale_textbox, scale_textbox * textbox_max_height) scale_textbox = min(scale_textbox, get_viewport_rect().size.x / Textbox.get_size().x) Textbox.scale = Vector2(scale_textbox, scale_textbox) Textbox.position = get_viewport_rect().size - Textbox.get_size() * scale_textbox Textbox.position.x /= 2.0 var scale_selection_screen: float = get_viewport_rect().size.y / SelectionScreen.get_size().y scale_selection_screen = min(scale_selection_screen, scale_selection_screen * selection_screen_max_size) scale_selection_screen = min(scale_selection_screen, Textbox.get_size().x * Textbox.scale.x / SelectionScreen.get_size().x) SelectionScreen.scale = Vector2(scale_selection_screen, scale_selection_screen) SelectionScreen.position = get_viewport_rect().size - SelectionScreen.get_size() * scale_selection_screen SelectionScreen.position.x /= 2.0 SelectionScreen.position.y /= 2.0 # INITIALIZATION API FUNCTIONS func add_backgrounds(backgrounds: Dictionary[String, PackedScene]) -> void: for current_background in backgrounds: if backgrounds[current_background]: DisplayBackgrounds.add_background(backgrounds[current_background], current_background) elif current_background: var empty_scene: PackedScene = PackedScene.new() var new_node: Node2D = Node2D.new() var new_sprite: Sprite2D = Sprite2D.new() new_sprite.name = "Sprite2D" new_node.add_child(new_sprite) new_sprite.owner = new_node empty_scene.pack(new_node) DisplayBackgrounds.add_background(empty_scene, current_background) func add_characters(characters: Dictionary[String, PackedScene]) -> void: for character in characters: if characters[character]: DisplayCharacters.add_character(characters[character], character) elif character: var empty_scene: PackedScene = PackedScene.new() var new_node: Node2D = Node2D.new() var new_sprite: Sprite2D = Sprite2D.new() new_sprite.name = "Sprite2D" new_node.add_child(new_sprite) new_sprite.owner = new_node empty_scene.pack(new_node) DisplayCharacters.add_character(empty_scene, character) func add_textbox_themes(textbox_themes: Dictionary[String, PackedScene]) -> void: for textbox_theme in textbox_themes: if textbox_themes[textbox_theme]: pass elif textbox_theme: pass func add_selection_screen_themes(selection_screen_themes: Dictionary[String, PackedScene]) -> void: for selection_screen_theme in selection_screen_themes: if selection_screen_themes[selection_screen_theme]: pass elif selection_screen_theme: pass func set_autoplay(value: bool) -> void: AutoPlay = value if value == true: Sleep.wait_time = 1.175494E-38 Sleep.start() func save_procedure() -> void: var config_file: ConfigFile = ConfigFile.new() config_file.set_value("GameSave", "order", Order) config_file.set_value("GameSave", "chapter", get_tree().current_scene.scene_file_path) config_file.save("user://game_save.cfg") func load_procedure() -> void: var config_file: ConfigFile = ConfigFile.new() config_file.load("user://game_save.cfg") AUTOLOAD_ORDER = config_file.get_value("GameSave", "order", -1) AUTOLOAD_SCENE = config_file.get_value("GameSave", "chapter", "") if AUTOLOAD_SCENE != "": get_tree().change_scene_to_file(AUTOLOAD_SCENE) # API FUNCTIONS class Data: var wait_sec: float = NAN func time(second: float) -> Data: wait_sec = second return self func set_background(background_name: String) -> Data: var data: Data = Data.new().time(DisplayBackgrounds.time_animation) Procedure.append([["set_background", DisplayBackgrounds.set_background], [background_name], data]) return data func show_character(character_name: String, where: String, character_position: Vector2 = Vector2.ZERO, character_scale: Vector2 = Vector2.ONE) -> Data: var data: Data = Data.new().time(DisplayCharacters.time_animation) Procedure.append([["show_character", DisplayCharacters.show_character], [character_name, where, character_position, character_scale], data]) return data func send_message(message: String = "", name_character: String = "", timer_character: float = Textbox.timer_character) -> Data: var data: Data = Data.new() if message == "": data.time(0.0) Procedure.append([["send_message", Textbox.send_message], [message, name_character, timer_character], data]) return data func set_focus_mode(value: bool) -> Data: var data: Data = Data.new().time(0.0) Procedure.append([["set_focus_mode", DisplayCharacters.set_focus_mode], [value], data]) return data func focus_character(character_names: Array) -> Data: var data: Data = Data.new().time(DisplayCharacters.time_animation / 2.0) Procedure.append([["focus_character", DisplayCharacters.focus_character], [character_names], data]) return data func wait() -> Data: var data: Data = Data.new().time(1.0) Procedure.append([["wait", func(): pass], [], data]) return data func jump(name_label: String) -> Data: var data: Data = Data.new().time(0.0) Procedure.append([["jump", func(): if Labels.has(name_label): Order = Labels[name_label] - 1], [], data]) return data func label(name_label: String) -> void: if Labels.has(name_label): printerr("Duplicated label: " + name_label) else: Labels[name_label] = Procedure.size() func selections(texts: Array, labels: Array) -> void: if len(texts) != len(labels): printerr("Wrong selection!") var functions: Array var data: Data = Data.new() for current_label in labels: functions.append(func(): if Labels.has(current_label): Order = Labels[current_label] SelectionScreen.set_active(false) Textbox.modulate = Textbox.modulate.darkened(-1.0) DisplayBackgrounds.modulate = DisplayBackgrounds.modulate.darkened(-1.0) DisplayCharacters.modulate = DisplayCharacters.modulate.darkened(-1.0) execute_procedure() ) Procedure.append([["selections", SelectionScreen.set_function_buttons], [texts, functions], data])