AudioPlayer keeps the *AssetManager it is handed, so attaching it during construction quietly pinned it to the manager NewGame happened to make. A domain that assigns its own registry onto the Game — legal, the fields are plain *Manager values — got a working image path and a silent audio one. Run attaches instead, once the Game is final. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -275,6 +275,23 @@ selects `classic-scumm` as the active theme. Widgets are **not**
|
|||||||
auto-registered — call `RegisterDefaultUI(g)` (or one of its siblings)
|
auto-registered — call `RegisterDefaultUI(g)` (or one of its siblings)
|
||||||
explicitly, or let `Run` install the default set if `UIManager` is empty.
|
explicitly, or let `Run` install the default set if `UIManager` is empty.
|
||||||
|
|
||||||
|
The manager fields are ordinary `*Manager` values, so a domain that keeps its
|
||||||
|
own registries can **assign them onto the Game** instead of copying every entry
|
||||||
|
across:
|
||||||
|
|
||||||
|
```go
|
||||||
|
g := inkwell.NewGame("Real World", 640, 380)
|
||||||
|
g.SceneManager = mySceneManager
|
||||||
|
g.AssetManager = myAssetManager
|
||||||
|
```
|
||||||
|
|
||||||
|
Do it before `Run` — that is where the engine wires up the parts that hold a
|
||||||
|
registry directly, so whichever managers the `*Game` carries by then are the
|
||||||
|
ones that get used. Two of them are worth a second thought before replacing:
|
||||||
|
`ThemeManager` arrives holding the four presets and `classic-scumm` selected,
|
||||||
|
and `VerbManager` the four SCUMM verbs. Replacing either throws that away —
|
||||||
|
register into them instead unless that is what you want.
|
||||||
|
|
||||||
### 4.2 Lifecycle hooks
|
### 4.2 Lifecycle hooks
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -1517,13 +1534,15 @@ func Run(g *Game) error // toplevel — same as g.Run()
|
|||||||
|
|
||||||
`Run` does, in order:
|
`Run` does, in order:
|
||||||
|
|
||||||
1. `g.Validate()` — cross-check name references between managers.
|
1. `g.Audio.attach(g.AssetManager)` — wire the audio player to whichever
|
||||||
2. If `UIManager` is empty, call `RegisterDefaultUI(g)`.
|
asset registry the game is carrying by now.
|
||||||
3. Place the start scene directly (no transition), bump
|
2. `g.Validate()` — cross-check name references between managers.
|
||||||
|
3. If `UIManager` is empty, call `RegisterDefaultUI(g)`.
|
||||||
|
4. Place the start scene directly (no transition), bump
|
||||||
`State.NoteVisit`, position registered actors, kick off music.
|
`State.NoteVisit`, position registered actors, kick off music.
|
||||||
4. Compose `Seq(scene.OnEnter, game.OnStart)` and queue it as the initial
|
5. Compose `Seq(scene.OnEnter, game.OnStart)` and queue it as the initial
|
||||||
action — the first script tick runs both in order.
|
action — the first script tick runs both in order.
|
||||||
5. `ebiten.SetWindowSize(Width*4, Height*4)`,
|
6. `ebiten.SetWindowSize(Width*4, Height*4)`,
|
||||||
`ebiten.SetWindowTitle(g.Title)`, then `ebiten.RunGame(&engine{g})`.
|
`ebiten.SetWindowTitle(g.Title)`, then `ebiten.RunGame(&engine{g})`.
|
||||||
|
|
||||||
### 15.1 `engine.Update`
|
### 15.1 `engine.Update`
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ import (
|
|||||||
// Run validates the game, then enters the ebiten main loop. The window is
|
// Run validates the game, then enters the ebiten main loop. The window is
|
||||||
// sized to 4× the internal resolution.
|
// sized to 4× the internal resolution.
|
||||||
func Run(g *Game) error {
|
func Run(g *Game) error {
|
||||||
|
// The domain may have swapped a manager in since NewGame, so the parts
|
||||||
|
// that hold a registry directly are wired here, not at construction.
|
||||||
|
g.Audio.attach(g.AssetManager)
|
||||||
|
|
||||||
if err := g.Validate(); err != nil {
|
if err := g.Validate(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -114,6 +114,10 @@ type runtimeDialog struct {
|
|||||||
// NewGame initializes a game with empty entity managers, the SCUMM-style
|
// NewGame initializes a game with empty entity managers, the SCUMM-style
|
||||||
// verb set, all preset themes, and "classic-scumm" selected. Widgets are
|
// verb set, all preset themes, and "classic-scumm" selected. Widgets are
|
||||||
// NOT auto-registered — call RegisterDefaultUI(g) explicitly.
|
// NOT auto-registered — call RegisterDefaultUI(g) explicitly.
|
||||||
|
//
|
||||||
|
// A domain is free to replace any of the entity managers with one of its
|
||||||
|
// own before Run — the registries are ordinary *Manager values, and Run
|
||||||
|
// wires the engine to whichever ones the Game holds by then.
|
||||||
func NewGame(title string, w, h int) *Game {
|
func NewGame(title string, w, h int) *Game {
|
||||||
g := &Game{
|
g := &Game{
|
||||||
Title: title,
|
Title: title,
|
||||||
@@ -138,7 +142,6 @@ func NewGame(title string, w, h int) *Game {
|
|||||||
transition: &transition{},
|
transition: &transition{},
|
||||||
selectedVerb: "look",
|
selectedVerb: "look",
|
||||||
}
|
}
|
||||||
g.Audio.attach(g.AssetManager)
|
|
||||||
for _, v := range defaultVerbs() {
|
for _, v := range defaultVerbs() {
|
||||||
g.VerbManager.Register(v)
|
g.VerbManager.Register(v)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user