输入、拖放、成就和画廊
本文覆盖 Galgo 的交互系统:文本输入、变量、拖放、成就、CG 画廊和音乐画廊。
文本输入
Input 会打开阻塞输入框,玩家提交后把值写入变量:
go
galgo.Input("player_name", "What should Aria call you?",
galgo.InputDefault("Haruto"),
galgo.InputPlaceholder("Your name"),
galgo.InputMaxRunes(16),
)常用选项:
InputDefault(value):默认值。InputPlaceholder(value):占位提示。InputMaxRunes(max):最大字符数。InputAllowEmpty():允许空输入。InputSubmitLabel(label):提交按钮文本。InputValidator(fn):自定义验证。
验证示例:
go
galgo.Input("player_name", "Name?",
galgo.InputValidator(func(value string) (bool, string) {
if len([]rune(value)) < 2 {
return false, "Name is too short"
}
return true, ""
}),
)读取输入结果:
go
galgo.Text("Aria", "你好,{{player_name}}。")变量
脚本里设置变量:
go
galgo.SetVariable("walked_together", true)Go 回调里设置:
go
galgo.Callback(func(e *galgo.Engine) bool {
e.SetVariable("score", 10)
return false
})类型读取:
go
name := e.GetStringVar("player_name", "Player")
walked := e.GetBoolVar("walked_together", false)
score := e.GetIntVar("score", 0)拖放组件
拖放由可拖拽组件和投放区域组成:
go
galgo.DragDrop(
[]*galgo.DragComponent{
{ID: "promise_token", Label: "Promise", X: 500, Y: 300, W: 160, H: 48},
},
[]*galgo.DropZone{
{
ID: "promise_target",
Label: "Drop Here",
X: 540,
Y: 430,
W: 200,
H: 70,
OnDrop: func(e *galgo.Engine, component *galgo.DragComponent, zone *galgo.DropZone) {
e.SetVariable("promise_token_ready", true)
e.UnlockAchievement("first_drag")
},
},
},
)DragComponent 常用字段:
IDLabelX、Y、W、HHiddenDisabledPayloadDrawOnDrop
DropZone 常用字段:
IDLabelX、Y、W、HPayloadOccupiedByAcceptOnDrop
拖放选项
go
galgo.DragDropBlocking(true)
galgo.DragDropCompleteOnDrop(true)
galgo.DragDropOnComplete(func(e *galgo.Engine) {
e.ShowToast("Done")
})DragDrop Step 默认会阻塞脚本直到完成。你也可以用 engine.ShowDragDrop 在回调里手动打开拖放。
自定义拖放绘制
go
Draw: func(e *galgo.Engine, screen *ebiten.Image, c *galgo.DragComponent, dragging bool) bool {
clr := color.RGBA{56, 189, 248, 180}
if dragging {
clr = color.RGBA{244, 63, 94, 200}
}
vector.DrawFilledRect(screen, float32(c.X), float32(c.Y), float32(c.W), float32(c.H), clr, true)
return true
}返回 true 表示自己完成绘制,跳过默认组件样式。
成就
配置成就:
go
Achievements: []galgo.AchievementItem{
{Key: "named_player", Title: "First Name", Description: "Named the protagonist."},
{Key: "club_duties", Title: "Club Duties", Description: "Chose the club route.", Hidden: true},
},解锁:
go
galgo.UnlockAchievement("named_player")或者 Go 代码中:
go
engine.UnlockAchievement("named_player")查询:
go
if engine.IsAchievementUnlocked("named_player") {
// ...
}如果配置了 Steamworks 且启用自动同步,解锁时会同步到 Steam 成就。
CG 画廊
配置:
go
GalleryCGs: []galgo.GalleryCGItem{
{Key: "classroom", Path: "assets/bg_classroom.jpg", Name: "夕阳教室"},
},解锁:
go
engine.UnlockCG("classroom", "assets/bg_classroom.jpg")Bg("classroom", "...") 成功设置背景时会自动解锁同 key 的 CG。
音乐画廊
配置:
go
GalleryBGMs: []galgo.GalleryBGMItem{
{Key: "school_life", Path: "assets/bgm_school.mp3", Name: "校园日常"},
},解锁:
go
engine.UnlockBGM("school_life", "assets/bgm_school.mp3")BGM 播放时会自动解锁对应音乐项。
全局解锁文件
成就、CG 和 BGM 解锁状态属于全局状态,会写入 gallery.json。它不跟随单个存档 slot,因此玩家读档后仍能保留已解锁内容。
推荐实践
剧情中关键节点用 UnlockAchievement 标记进度,画廊资源用稳定 key。不要把资源路径当 key,因为后续换素材路径时会导致旧解锁状态失效。