Add cinematic title artwork
This commit is contained in:
@@ -111,7 +111,7 @@ Godot 4 tactical RPG prototype inspired by classic turn-based Romance of the Thr
|
||||
- Campaign completion screen.
|
||||
- New campaign save reset.
|
||||
- Manual campaign checkpoint save/load.
|
||||
- Title screen offers start, load, and settings; BGM/SFX volume, sound toggles, and edge-scroll preference persist in `user://heros_settings.json`.
|
||||
- Cinematic title screen uses the battlefield backdrop and Cao Cao portrait art, offers start/load/settings, and persists BGM/SFX volume, sound toggles, and edge-scroll preference in `user://heros_settings.json`.
|
||||
- Victory and defeat result overlay.
|
||||
- Dialogue portrait slot with officer default image paths, optional per-line overrides, and speaker-initial fallback.
|
||||
- Initial AI-generated photorealistic officer portraits for Cao Cao, Xiahou Dun, Xiahou Yuan, Cao Ren, Dian Wei, Guo Jia, and Zhang He.
|
||||
|
||||
@@ -26,6 +26,8 @@ const THREAT_OVERLAY_COLOR := Color(0.76, 0.060, 0.035, 0.20)
|
||||
const THREAT_BORDER_COLOR := Color(0.86, 0.18, 0.10, 0.48)
|
||||
const BGM_MENU_PATH := "res://audio/bgm/menu_theme_placeholder.wav"
|
||||
const BGM_BATTLE_PATH := "res://audio/bgm/battle_loop_placeholder.wav"
|
||||
const TITLE_BACKGROUND_PATH := "res://art/backgrounds/battlefield_frontier.png"
|
||||
const TITLE_PORTRAIT_PATH := "res://art/portraits/cao_cao.png"
|
||||
const SETTINGS_PATH := "user://heros_settings.json"
|
||||
const SETTINGS_SAVE_VERSION := 1
|
||||
const SFX_BOW_RELEASE_PATH := "res://audio/sfx/bow_release_01.wav"
|
||||
@@ -465,7 +467,11 @@ var top_load_button: Button
|
||||
var restart_button: Button
|
||||
var new_campaign_button: Button
|
||||
var title_screen_root: Control
|
||||
var title_background_texture_rect: TextureRect
|
||||
var title_portrait_texture_rect: TextureRect
|
||||
var title_panel: PanelContainer
|
||||
var title_caption_label: Label
|
||||
var title_subtitle_label: Label
|
||||
var title_start_button: Button
|
||||
var title_load_button: Button
|
||||
var title_settings_button: Button
|
||||
@@ -2997,15 +3003,63 @@ func _create_hud() -> void:
|
||||
title_screen_root.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
root.add_child(title_screen_root)
|
||||
|
||||
title_background_texture_rect = TextureRect.new()
|
||||
title_background_texture_rect.name = "TitleBattlefieldBackdrop"
|
||||
title_background_texture_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
title_background_texture_rect.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
title_background_texture_rect.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
||||
title_background_texture_rect.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_COVERED
|
||||
title_background_texture_rect.texture = _load_art_texture(TITLE_BACKGROUND_PATH)
|
||||
title_screen_root.add_child(title_background_texture_rect)
|
||||
|
||||
var title_dim := ColorRect.new()
|
||||
title_dim.name = "TitleInkWash"
|
||||
title_dim.color = Color(0.025, 0.016, 0.010, 0.92)
|
||||
title_dim.color = Color(0.025, 0.016, 0.010, 0.48)
|
||||
title_dim.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
title_dim.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
title_screen_root.add_child(title_dim)
|
||||
|
||||
var title_menu_shadow := ColorRect.new()
|
||||
title_menu_shadow.name = "TitleMenuInkPanel"
|
||||
title_menu_shadow.position = Vector2(0, 0)
|
||||
title_menu_shadow.size = Vector2(790, 720)
|
||||
title_menu_shadow.color = Color(0.030, 0.018, 0.010, 0.58)
|
||||
title_menu_shadow.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
title_screen_root.add_child(title_menu_shadow)
|
||||
|
||||
var title_portrait_shadow := ColorRect.new()
|
||||
title_portrait_shadow.name = "TitlePortraitLacquerField"
|
||||
title_portrait_shadow.position = Vector2(770, 36)
|
||||
title_portrait_shadow.size = Vector2(430, 628)
|
||||
title_portrait_shadow.color = Color(0.045, 0.018, 0.010, 0.56)
|
||||
title_portrait_shadow.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
title_screen_root.add_child(title_portrait_shadow)
|
||||
|
||||
title_portrait_texture_rect = TextureRect.new()
|
||||
title_portrait_texture_rect.name = "TitleCaoCaoPortrait"
|
||||
title_portrait_texture_rect.position = Vector2(804, 48)
|
||||
title_portrait_texture_rect.size = Vector2(388, 606)
|
||||
title_portrait_texture_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
title_portrait_texture_rect.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
||||
title_portrait_texture_rect.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_COVERED
|
||||
title_portrait_texture_rect.texture = _load_art_texture(TITLE_PORTRAIT_PATH)
|
||||
title_portrait_texture_rect.modulate = Color(1.0, 0.95, 0.86, 0.94)
|
||||
title_screen_root.add_child(title_portrait_texture_rect)
|
||||
|
||||
var title_portrait_caption := Label.new()
|
||||
title_portrait_caption.name = "TitlePortraitCaption"
|
||||
title_portrait_caption.text = "조조"
|
||||
title_portrait_caption.position = Vector2(818, 604)
|
||||
title_portrait_caption.size = Vector2(350, 34)
|
||||
title_portrait_caption.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
|
||||
title_portrait_caption.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
title_portrait_caption.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
_apply_label_style(title_portrait_caption, UI_OLD_BRONZE, 18)
|
||||
title_screen_root.add_child(title_portrait_caption)
|
||||
|
||||
title_panel = PanelContainer.new()
|
||||
title_panel.name = "TitleMenuPanel"
|
||||
title_panel.position = Vector2(286, 76)
|
||||
title_panel.position = Vector2(58, 76)
|
||||
title_panel.size = Vector2(708, 568)
|
||||
title_panel.custom_minimum_size = Vector2(708, 568)
|
||||
_apply_panel_style(title_panel, "paper")
|
||||
@@ -3018,21 +3072,21 @@ func _create_hud() -> void:
|
||||
title_column.add_child(_make_scroll_rod(616, 5))
|
||||
title_column.add_child(_make_seal_ribbon(616, 18))
|
||||
|
||||
var title_caption := Label.new()
|
||||
title_caption.text = "영웅전"
|
||||
title_caption.custom_minimum_size = Vector2(616, 58)
|
||||
title_caption.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
title_caption.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
_apply_label_style(title_caption, UI_PARCHMENT_TEXT, 34)
|
||||
title_column.add_child(title_caption)
|
||||
title_caption_label = Label.new()
|
||||
title_caption_label.text = "조조전"
|
||||
title_caption_label.custom_minimum_size = Vector2(616, 58)
|
||||
title_caption_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
title_caption_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
_apply_label_style(title_caption_label, UI_PARCHMENT_TEXT, 34)
|
||||
title_column.add_child(title_caption_label)
|
||||
|
||||
var title_subtitle := Label.new()
|
||||
title_subtitle.text = "난세의 첫 군령"
|
||||
title_subtitle.custom_minimum_size = Vector2(616, 34)
|
||||
title_subtitle.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
title_subtitle.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
_apply_label_style(title_subtitle, UI_OLD_BRONZE, 17)
|
||||
title_column.add_child(title_subtitle)
|
||||
title_subtitle_label = Label.new()
|
||||
title_subtitle_label.text = "난세를 여는 첫 군령"
|
||||
title_subtitle_label.custom_minimum_size = Vector2(616, 34)
|
||||
title_subtitle_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
title_subtitle_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
_apply_label_style(title_subtitle_label, UI_OLD_BRONZE, 17)
|
||||
title_column.add_child(title_subtitle_label)
|
||||
|
||||
var title_body_panel := PanelContainer.new()
|
||||
title_body_panel.custom_minimum_size = Vector2(616, 314)
|
||||
|
||||
@@ -41,6 +41,14 @@ func _check_title_menu_start_load_and_settings(failures: Array[String]) -> void:
|
||||
|
||||
if scene.title_screen_root == null or not scene.title_screen_root.visible:
|
||||
failures.append("title screen should be visible on startup")
|
||||
if scene.title_background_texture_rect == null or scene.title_background_texture_rect.texture == null:
|
||||
failures.append("title screen should show a high-resolution battlefield backdrop")
|
||||
if scene.title_portrait_texture_rect == null or scene.title_portrait_texture_rect.texture == null:
|
||||
failures.append("title screen should show Cao Cao portrait art")
|
||||
if scene.title_panel == null or scene.title_panel.position.x > 100.0:
|
||||
failures.append("title menu panel should sit on the left side of the cinematic title screen")
|
||||
if scene.title_caption_label == null or scene.title_caption_label.text != "조조전":
|
||||
failures.append("title screen should present the campaign title in Korean")
|
||||
if scene.briefing_panel == null or scene.briefing_panel.visible:
|
||||
failures.append("briefing should stay hidden behind the title screen")
|
||||
if scene.title_start_button == null or scene.title_start_button.text != "처음부터 시작":
|
||||
@@ -55,6 +63,8 @@ func _check_title_menu_start_load_and_settings(failures: Array[String]) -> void:
|
||||
scene._on_title_settings_pressed()
|
||||
if scene.title_settings_panel == null or not scene.title_settings_panel.visible:
|
||||
failures.append("title settings panel should open from the title screen")
|
||||
if scene.title_start_button != null and scene.title_start_button.visible:
|
||||
failures.append("title settings should replace the main title commands while open")
|
||||
if scene.title_bgm_toggle == null or scene.title_sfx_toggle == null or scene.title_edge_scroll_toggle == null:
|
||||
failures.append("title settings should expose BGM, SFX, and edge-scroll toggles")
|
||||
if scene.title_bgm_volume_slider == null or scene.title_sfx_volume_slider == null:
|
||||
|
||||
Reference in New Issue
Block a user