Add title story preview strip
This commit is contained in:
@@ -126,7 +126,7 @@ Godot 4 tactical RPG prototype inspired by classic turn-based Romance of the Thr
|
|||||||
- Campaign completion screen.
|
- Campaign completion screen.
|
||||||
- New campaign save reset.
|
- New campaign save reset.
|
||||||
- Manual campaign checkpoint save/load.
|
- Manual campaign checkpoint save/load.
|
||||||
- Cinematic title screen uses a dedicated ancient-war-camp dawn backdrop and Cao Cao portrait art, offers start/load/settings, leads new campaigns through a generated four-panel Yellow Turban rebellion, Cao Cao resolve, Xiahou Dun meeting, and Yingchuan contact prologue with full-screen story artwork, a chapter seal, and a bottom scroll caption panel, exposes the same audio/edge-scroll settings from the top in-game toolbar, includes a one-click audio recovery control, and persists BGM/SFX volume, sound toggles, and edge-scroll preference in `user://heros_settings.json`.
|
- Cinematic title screen uses a dedicated ancient-war-camp dawn backdrop and Cao Cao portrait art, offers start/load/settings, previews the four generated opening story panels on the title menu, leads new campaigns through a generated four-panel Yellow Turban rebellion, Cao Cao resolve, Xiahou Dun meeting, and Yingchuan contact prologue with full-screen story artwork, a chapter seal, and a bottom scroll caption panel, exposes the same audio/edge-scroll settings from the top in-game toolbar, includes a one-click audio recovery control, and persists BGM/SFX volume, sound toggles, and edge-scroll preference in `user://heros_settings.json`.
|
||||||
- Victory and defeat result overlay.
|
- Victory and defeat result overlay.
|
||||||
- Dialogue portrait slot stays fixed across speaker and narration lines, with officer default image paths, optional per-line overrides, and speaker-initial or record fallback.
|
- Dialogue portrait slot stays fixed across speaker and narration lines, with officer default image paths, optional per-line overrides, and speaker-initial or record fallback.
|
||||||
- Initial AI-generated photorealistic officer portraits for Cao Cao, Xiahou Dun, Xiahou Yuan, Cao Ren, Dian Wei, Guo Jia, and Zhang He.
|
- Initial AI-generated photorealistic officer portraits for Cao Cao, Xiahou Dun, Xiahou Yuan, Cao Ren, Dian Wei, Guo Jia, and Zhang He.
|
||||||
|
|||||||
@@ -1954,6 +1954,52 @@ func _make_seal_cluster(height: float) -> HBoxContainer:
|
|||||||
return cluster
|
return cluster
|
||||||
|
|
||||||
|
|
||||||
|
func _make_title_story_preview_strip() -> PanelContainer:
|
||||||
|
var panel := PanelContainer.new()
|
||||||
|
panel.name = "TitleStoryPreviewStrip"
|
||||||
|
panel.custom_minimum_size = Vector2(616, 88)
|
||||||
|
_apply_panel_style(panel, "hud_info")
|
||||||
|
|
||||||
|
var row := HBoxContainer.new()
|
||||||
|
row.custom_minimum_size = Vector2(584, 68)
|
||||||
|
row.add_theme_constant_override("separation", 8)
|
||||||
|
panel.add_child(row)
|
||||||
|
|
||||||
|
for index in range(OPENING_PROLOGUE_PAGES.size()):
|
||||||
|
var page: Dictionary = OPENING_PROLOGUE_PAGES[index]
|
||||||
|
row.add_child(_make_title_story_preview_card(str(page.get("title", "")), str(page.get("image", "")), index + 1))
|
||||||
|
return panel
|
||||||
|
|
||||||
|
|
||||||
|
func _make_title_story_preview_card(title: String, image_path: String, index: int) -> VBoxContainer:
|
||||||
|
var card := VBoxContainer.new()
|
||||||
|
card.name = "TitleStoryPreviewCard%d" % index
|
||||||
|
card.custom_minimum_size = Vector2(140, 68)
|
||||||
|
card.add_theme_constant_override("separation", 3)
|
||||||
|
card.tooltip_text = "%d. %s" % [index, title]
|
||||||
|
|
||||||
|
var texture_rect := TextureRect.new()
|
||||||
|
texture_rect.name = "TitleStoryPreviewImage"
|
||||||
|
texture_rect.custom_minimum_size = Vector2(140, 48)
|
||||||
|
texture_rect.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
||||||
|
texture_rect.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_COVERED
|
||||||
|
texture_rect.texture = _load_art_texture(image_path)
|
||||||
|
texture_rect.modulate = Color(0.96, 0.94, 0.88, 0.94)
|
||||||
|
texture_rect.tooltip_text = card.tooltip_text
|
||||||
|
card.add_child(texture_rect)
|
||||||
|
|
||||||
|
var label := Label.new()
|
||||||
|
label.name = "TitleStoryPreviewLabel"
|
||||||
|
label.text = title
|
||||||
|
label.custom_minimum_size = Vector2(140, 17)
|
||||||
|
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||||
|
label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||||
|
label.tooltip_text = card.tooltip_text
|
||||||
|
_apply_label_style(label, UI_OLD_BRONZE, 10)
|
||||||
|
card.add_child(label)
|
||||||
|
return card
|
||||||
|
|
||||||
|
|
||||||
func _make_map_lattice_overlay(size: Vector2) -> Control:
|
func _make_map_lattice_overlay(size: Vector2) -> Control:
|
||||||
var overlay := Control.new()
|
var overlay := Control.new()
|
||||||
overlay.name = "MapLatticeOverlay"
|
overlay.name = "MapLatticeOverlay"
|
||||||
@@ -3605,9 +3651,9 @@ func _create_hud() -> void:
|
|||||||
|
|
||||||
title_panel = PanelContainer.new()
|
title_panel = PanelContainer.new()
|
||||||
title_panel.name = "TitleMenuPanel"
|
title_panel.name = "TitleMenuPanel"
|
||||||
title_panel.position = Vector2(58, 76)
|
title_panel.position = Vector2(58, 46)
|
||||||
title_panel.size = Vector2(708, 568)
|
title_panel.size = Vector2(708, 628)
|
||||||
title_panel.custom_minimum_size = Vector2(708, 568)
|
title_panel.custom_minimum_size = Vector2(708, 628)
|
||||||
_apply_panel_style(title_panel, "paper")
|
_apply_panel_style(title_panel, "paper")
|
||||||
title_screen_root.add_child(title_panel)
|
title_screen_root.add_child(title_panel)
|
||||||
|
|
||||||
@@ -3634,6 +3680,8 @@ func _create_hud() -> void:
|
|||||||
_apply_label_style(title_subtitle_label, UI_OLD_BRONZE, 17)
|
_apply_label_style(title_subtitle_label, UI_OLD_BRONZE, 17)
|
||||||
title_column.add_child(title_subtitle_label)
|
title_column.add_child(title_subtitle_label)
|
||||||
|
|
||||||
|
title_column.add_child(_make_title_story_preview_strip())
|
||||||
|
|
||||||
var title_body_panel := PanelContainer.new()
|
var title_body_panel := PanelContainer.new()
|
||||||
title_body_panel.custom_minimum_size = Vector2(616, 314)
|
title_body_panel.custom_minimum_size = Vector2(616, 314)
|
||||||
_apply_panel_style(title_body_panel, "edict")
|
_apply_panel_style(title_body_panel, "edict")
|
||||||
|
|||||||
@@ -74,6 +74,22 @@ func _check_title_menu_start_load_and_settings(failures: Array[String]) -> void:
|
|||||||
failures.append("title menu panel should sit on the left side of the cinematic title screen")
|
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 != "조조전":
|
if scene.title_caption_label == null or scene.title_caption_label.text != "조조전":
|
||||||
failures.append("title screen should present the campaign title in Korean")
|
failures.append("title screen should present the campaign title in Korean")
|
||||||
|
var title_story_strip: Node = null
|
||||||
|
if scene.title_screen_root != null:
|
||||||
|
title_story_strip = scene.title_screen_root.find_child("TitleStoryPreviewStrip", true, false)
|
||||||
|
if title_story_strip == null:
|
||||||
|
failures.append("title screen should preview the four generated opening story panels")
|
||||||
|
else:
|
||||||
|
var story_cards: Array = title_story_strip.find_children("TitleStoryPreviewCard*", "", true, false)
|
||||||
|
if story_cards.size() != 4:
|
||||||
|
failures.append("title story preview should expose four story beats: %d" % story_cards.size())
|
||||||
|
for story_card in story_cards:
|
||||||
|
var story_image := (story_card as Node).find_child("TitleStoryPreviewImage", true, false) as TextureRect
|
||||||
|
var story_label := (story_card as Node).find_child("TitleStoryPreviewLabel", true, false) as Label
|
||||||
|
if story_image == null or story_image.texture == null:
|
||||||
|
failures.append("title story preview card should load generated artwork")
|
||||||
|
if story_label == null or story_label.text.strip_edges().is_empty():
|
||||||
|
failures.append("title story preview card should name its story beat")
|
||||||
if scene.briefing_panel == null or scene.briefing_panel.visible:
|
if scene.briefing_panel == null or scene.briefing_panel.visible:
|
||||||
failures.append("briefing should stay hidden behind the title screen")
|
failures.append("briefing should stay hidden behind the title screen")
|
||||||
if scene.title_start_button == null or scene.title_start_button.text != "처음부터 시작":
|
if scene.title_start_button == null or scene.title_start_button.text != "처음부터 시작":
|
||||||
|
|||||||
Reference in New Issue
Block a user