@@ -48,12 +48,12 @@ This holds for nested literals too, including small ones such as
|
|||||||
All game code lives in one flat package, `inc`. There are no subdirectories: a
|
All game code lives in one flat package, `inc`. There are no subdirectories: a
|
||||||
file's name carries the structure, in the form `[category].[name].go`.
|
file's name carries the structure, in the form `[category].[name].go`.
|
||||||
|
|
||||||
- The category is always **singular**: `item`, `screen`, `background`,
|
- The category is always **singular**: `item`, `scene`, `background`,
|
||||||
`character`, `dialog`, `script`, `world`, `ui`, `theme`, `names`, `boot`,
|
`character`, `dialog`, `script`, `world`, `ui`, `theme`, `names`, `boot`,
|
||||||
`content`.
|
`content`.
|
||||||
- `[category].manager.go` is the file that ties a category together — its
|
- `[category].manager.go` is the file that ties a category together — its
|
||||||
manager, its entity type, whatever the category shares.
|
manager, its entity type, whatever the category shares.
|
||||||
- Every other file in a category holds exactly one entity: one screen, one
|
- Every other file in a category holds exactly one entity: one scene, one
|
||||||
background, one item. The file registers it itself, in an `init()`.
|
background, one item. The file registers it itself, in an `init()`.
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -70,14 +70,14 @@ inc/world.action.go custom actions and the action pump
|
|||||||
inc/ui.manager.go HUD layout and widget registration
|
inc/ui.manager.go HUD layout and widget registration
|
||||||
inc/ui.*.go custom widgets, coloured text
|
inc/ui.*.go custom widgets, coloured text
|
||||||
inc/content.manager.go composition root; calls every register…
|
inc/content.manager.go composition root; calls every register…
|
||||||
inc/background.*.go one image asset per screen
|
inc/background.*.go one image asset per scene
|
||||||
inc/character.*.go the cast, tapes included
|
inc/character.*.go the cast, tapes included
|
||||||
inc/item.*.go inventory
|
inc/item.*.go inventory
|
||||||
inc/dialog.*.go dialogue trees
|
inc/dialog.*.go dialogue trees
|
||||||
inc/script.*.go named action sequences
|
inc/script.*.go named action sequences
|
||||||
inc/screen.manager.go the Screen type, the deck, the scene builder
|
inc/scene.manager.go the Scene alias, the defaults every scene gets
|
||||||
inc/screen.exit.go the connections between screens
|
inc/scene.selector.go the map screen: its pins are derived from the graph
|
||||||
inc/screen.*.go one file per screen
|
inc/scene.*.go one file per scene
|
||||||
```
|
```
|
||||||
|
|
||||||
`manager` is the one category with no entities of its own: it holds the registry
|
`manager` is the one category with no entities of its own: it holds the registry
|
||||||
@@ -101,7 +101,7 @@ var CharacterManager = NewManager(func(entity Character) string { return entity.
|
|||||||
|
|
||||||
That is the whole of a category's manager file — an alias and one line. There
|
That is the whole of a category's manager file — an alias and one line. There
|
||||||
are seven managers: `BackgroundManager`, `CharacterManager`, `DialogManager`,
|
are seven managers: `BackgroundManager`, `CharacterManager`, `DialogManager`,
|
||||||
`ItemManager`, `ScriptManager`, `ScreenManager`, `ThemeManager`.
|
`ItemManager`, `ScriptManager`, `SceneManager`, `ThemeManager`.
|
||||||
|
|
||||||
`manager.interface.go` holds the contract they all keep, and asserts each one
|
`manager.interface.go` holds the contract they all keep, and asserts each one
|
||||||
against it. A new manager goes on that list.
|
against it. A new manager goes on that list.
|
||||||
@@ -118,8 +118,9 @@ type ManagerInterface[T any] interface {
|
|||||||
twice is an update, never a duplicate. `GetAll` returns the slice itself, in
|
twice is an update, never a duplicate. `GetAll` returns the slice itself, in
|
||||||
registration order.
|
registration order.
|
||||||
|
|
||||||
`Screen` is the one entity type that is not an alias: a screen carries exits and
|
Every entity type is an alias, `Scene` included. It was once a struct of our
|
||||||
an `OnSelector` flag that inkwell's `Scene` knows nothing about.
|
own, because inkwell's `Scene` could not carry exits; that gap was closed in the
|
||||||
|
engine, so there is nothing left for a second type to hold.
|
||||||
|
|
||||||
### Entities register themselves
|
### Entities register themselves
|
||||||
|
|
||||||
@@ -144,7 +145,7 @@ variables are initialised before any `init()` runs, so the managers exist by the
|
|||||||
time the first file registers into one.
|
time the first file registers into one.
|
||||||
|
|
||||||
`init()` order is file-name order, so **registration order is alphabetical**.
|
`init()` order is file-name order, so **registration order is alphabetical**.
|
||||||
Nothing may depend on it — including the order the arrow keys walk the screens,
|
Nothing may depend on it — including the order the arrow keys walk the scenes,
|
||||||
which is simply the order the files sit in.
|
which is simply the order the files sit in.
|
||||||
|
|
||||||
### Handing a category to the engine
|
### Handing a category to the engine
|
||||||
@@ -159,13 +160,13 @@ func registerContent() {
|
|||||||
registerAll(ItemManager, World.G.ItemManager.Register)
|
registerAll(ItemManager, World.G.ItemManager.Register)
|
||||||
registerAll(DialogManager, World.G.DialogueManager.Register)
|
registerAll(DialogManager, World.G.DialogueManager.Register)
|
||||||
registerAll(ScriptManager, World.G.ScriptManager.Register)
|
registerAll(ScriptManager, World.G.ScriptManager.Register)
|
||||||
registerScreen()
|
registerScene()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`registerScreen` is the one that needs its own function, because a screen has to
|
`registerScene` is the one that needs its own function: it fills in the defaults
|
||||||
be turned into an `inkwell.Scene` first, and because the selector's pins are
|
a scene may leave out (Paul's starting position, the floor walkbox), and it
|
||||||
derived from whichever screens marked themselves `OnSelector`.
|
derives the selector's pins by reading the exit graph backwards.
|
||||||
|
|
||||||
## The world
|
## The world
|
||||||
|
|
||||||
@@ -185,7 +186,7 @@ One package means one namespace, so an entity's constructor carries its
|
|||||||
category as a prefix:
|
category as a prefix:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
screenFloor screenBuild registerScreen fillSelectorPins
|
sceneFloor sceneDefaults registerScene fillSelectorPins
|
||||||
```
|
```
|
||||||
|
|
||||||
Entities themselves need no name at all — they are anonymous literals inside
|
Entities themselves need no name at all — they are anonymous literals inside
|
||||||
@@ -198,12 +199,12 @@ constants in `names.manager.go`, the colour tokens, and the action constructors
|
|||||||
|
|
||||||
Everything else is machinery and stays unexported: the HUD widgets
|
Everything else is machinery and stays unexported: the HUD widgets
|
||||||
(`tapeSlots`, `letterbox`, `hudFrame`, …), the `register…` functions, the
|
(`tapeSlots`, `letterbox`, `hudFrame`, …), the `register…` functions, the
|
||||||
runners, `screenBuild`, `exit`.
|
runners, `sceneDefaults`, `fillSelectorPins`.
|
||||||
|
|
||||||
The engine's word for a screen is `Scene`. Ours is **screen**, because the
|
The word is **scene**, the engine's own. The wiki and the concept-art deck count
|
||||||
wiki, the concept-art deck and the beat tables all count screens. "Scene"
|
*screens*, and this code used to as well, but everything a screen had that a
|
||||||
survives only where the code talks to the engine (`EnterScene`,
|
scene did not now lives in inkwell. "Screen" survives only where it means the
|
||||||
`SceneManager`).
|
display: `ScreenW`, `ScreenH`.
|
||||||
|
|
||||||
## Layering
|
## Layering
|
||||||
|
|
||||||
@@ -219,10 +220,10 @@ names ← theme ← world ← ui
|
|||||||
`world` knows nothing about the HUD or the content. Both build on it, never the
|
`world` knows nothing about the HUD or the content. Both build on it, never the
|
||||||
other way round.
|
other way round.
|
||||||
|
|
||||||
## Adding a screen
|
## Adding a scene
|
||||||
|
|
||||||
1. Constants in `inc/names.manager.go`: `Screen<Name>`, `Bg<Name>`
|
1. Constants in `inc/names.manager.go`: `Scene<Name>`, `Bg<Name>`
|
||||||
2. `inc/screen.<name>.go` — an `init()` registering a `Screen`
|
2. `inc/scene.<name>.go` — an `init()` registering a `Scene`
|
||||||
3. `inc/background.<name>.go` — an `init()` registering a `Background`
|
3. `inc/background.<name>.go` — an `init()` registering a `Background`
|
||||||
4. A 640×380 PNG in `assets/bg/`
|
4. A 640×380 PNG in `assets/bg/`
|
||||||
|
|
||||||
@@ -234,7 +235,7 @@ Nothing else moves. There is no list to update.
|
|||||||
make build native binary into bin/
|
make build native binary into bin/
|
||||||
make wasm js/wasm build into dist/
|
make wasm js/wasm build into dist/
|
||||||
make watch rebuild on change
|
make watch rebuild on change
|
||||||
go run . -screen <name> start on a given screen
|
go run . -scene <name> start on a given scene
|
||||||
go run . -finale start with the finale
|
go run . -finale start with the finale
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -25,11 +25,11 @@ go run .
|
|||||||
```bash
|
```bash
|
||||||
go run . # the alley (beat 3)
|
go run . # the alley (beat 3)
|
||||||
go run . -finale # the finale — try the Nokia-punk theme switch
|
go run . -finale # the finale — try the Nokia-punk theme switch
|
||||||
go run . -screen selector # the location selector: the map the city hangs off
|
go run . -scene selector # the location selector: the map the city hangs off
|
||||||
go run . -screen hospital # any screen in the deck, e.g. to look at the art
|
go run . -scene hospital # any scene in the deck, e.g. to look at the art
|
||||||
```
|
```
|
||||||
|
|
||||||
Screen names are the constants in `names.manager.go` (`selector`, `paul_shop`,
|
Scene names are the constants in `names.manager.go` (`selector`, `paul_shop`,
|
||||||
`noodle_house`, `alley`, `norman_apartment`, `police_station`, `hackerspace`,
|
`noodle_house`, `alley`, `norman_apartment`, `police_station`, `hackerspace`,
|
||||||
`ice_cream_shop`, `trinket_shop`, `small_restaurant`, `secret_club`,
|
`ice_cream_shop`, `trinket_shop`, `small_restaurant`, `secret_club`,
|
||||||
`bbs_terminal`, `street`, `hospital`, `server_farm`, `secret_lab`,
|
`bbs_terminal`, `street`, `hospital`, `server_farm`, `secret_lab`,
|
||||||
@@ -62,12 +62,12 @@ Release metadata lives in `metadata.json`.
|
|||||||
|---|---|
|
|---|---|
|
||||||
| left click | run the selected verb |
|
| left click | run the selected verb |
|
||||||
| right click | verb coin (Look / Use / Talk / Take) |
|
| right click | verb coin (Look / Use / Talk / Take) |
|
||||||
| `←` `→` | previous / next screen, in file order, wrapping |
|
| `←` `→` | previous / next scene, in file order, wrapping |
|
||||||
| `F1` | toggle hotspot outlines |
|
| `F1` | toggle hotspot outlines |
|
||||||
| `SPACE` | during a cutscene: let the tape speak, if it offered |
|
| `SPACE` | during a cutscene: let the tape speak, if it offered |
|
||||||
|
|
||||||
The screens are connected to each other (see **The map** below); the arrow keys
|
The scenes are connected to each other (see **The map** below); the arrow keys
|
||||||
are a reviewing tool on top of that, walking every screen in turn. The walk is
|
are a reviewing tool on top of that, walking every scene in turn. The walk is
|
||||||
inert during a cutscene, a menu, or a stopped world, so it can never cut
|
inert during a cutscene, a menu, or a stopped world, so it can never cut
|
||||||
across an authored beat.
|
across an authored beat.
|
||||||
|
|
||||||
@@ -181,15 +181,15 @@ Content is one registered entity per file, and the category prefix groups them
|
|||||||
the way directories used to:
|
the way directories used to:
|
||||||
|
|
||||||
```
|
```
|
||||||
background.*.go one file per screen: background.paul_shop.go, …
|
background.*.go one file per scene: background.paul_shop.go, …
|
||||||
character.*.go character.paul.go character.dex.go character.mystery_tape.go
|
character.*.go character.paul.go character.dex.go character.mystery_tape.go
|
||||||
item.*.go item.noodle_letter.go item.black_market_armilla.go …
|
item.*.go item.noodle_letter.go item.black_market_armilla.go …
|
||||||
dialog.*.go dialog.dex_talk.go dialog.mystery_tape_silent.go
|
dialog.*.go dialog.dex_talk.go dialog.mystery_tape_silent.go
|
||||||
script.*.go script.tape_insert.go script.awakening_finale.go
|
script.*.go script.tape_insert.go script.awakening_finale.go
|
||||||
screen.*.go one file per screen: screen.alley.go, … + screen.exit.go
|
scene.*.go one file per scene: scene.alley.go, … + scene.selector.go
|
||||||
```
|
```
|
||||||
|
|
||||||
Adding a screen means adding `screen.<name>.go` and `background.<name>.go`.
|
Adding a scene means adding `scene.<name>.go` and `background.<name>.go`.
|
||||||
Nothing else moves.
|
Nothing else moves.
|
||||||
|
|
||||||
Every category owns a manager, and they are all the same generic type,
|
Every category owns a manager, and they are all the same generic type,
|
||||||
@@ -229,13 +229,13 @@ func init() {
|
|||||||
|
|
||||||
So adding an entity is adding a file, and there is no second list to keep in
|
So adding an entity is adding a file, and there is no second list to keep in
|
||||||
step. The price is that registration order is file-name order: the arrow keys
|
step. The price is that registration order is file-name order: the arrow keys
|
||||||
walk the screens alphabetically rather than in the concept-art deck's order.
|
walk the scenes alphabetically rather than in the concept-art deck's order.
|
||||||
That was a deliberate trade — the deck order was a list that had to be kept in
|
That was a deliberate trade — the deck order was a list that had to be kept in
|
||||||
step with the files by hand, and the deck is a thing to look at, not a thing to
|
step with the files by hand, and the deck is a thing to look at, not a thing to
|
||||||
play through.
|
play through.
|
||||||
|
|
||||||
The game's own catalogue is readable without going through the engine:
|
The game's own catalogue is readable without going through the engine:
|
||||||
`ScreenManager.GetByName("alley")` answers before a single scene has been handed
|
`SceneManager.GetByName("alley")` answers before a single scene has been handed
|
||||||
over. `registerContent` is where the hand-off happens, one `registerAll` call
|
over. `registerContent` is where the hand-off happens, one `registerAll` call
|
||||||
per category.
|
per category.
|
||||||
|
|
||||||
@@ -244,51 +244,63 @@ a `*world` parameter and no widget holds a back-reference, which is what lets a
|
|||||||
script file be a literal — the tape-insert script closes over `World` rather
|
script file be a literal — the tape-insert script closes over `World` rather
|
||||||
than over a parameter someone would have had to thread to it.
|
than over a parameter someone would have had to thread to it.
|
||||||
|
|
||||||
**On the word "screen".** inkwell's entity is called a `Scene`, and that is the
|
**On the word "scene".** The wiki, the concept-art deck and the beat tables all
|
||||||
type every `screen.*.go` file returns — but the wiki, the concept-art deck and
|
count *screens*, and this code used to as well: it carried its own `Screen`
|
||||||
the beat tables all count *screens*, so the category, the files and the flag say
|
struct, because inkwell's `Scene` could not hold the things a screen needs —
|
||||||
screen. "Scene" survives only where the code is talking to the engine
|
its exits above all. Those went into the engine instead (inkwell `Exit`,
|
||||||
(`EnterScene`, `SceneManager`).
|
`Game.SceneRect`, `CurrentScene`/`PreviousScene`, `Back()`), and with the gap
|
||||||
|
closed there was nothing left for a second type to carry. The code says scene,
|
||||||
|
because that is what the thing is. "Screen" survives only where it means the
|
||||||
|
display: `ScreenW`, `ScreenH`.
|
||||||
|
|
||||||
Art lives in `assets/bg/` and is embedded into the binary (`main.go`), because
|
Art lives in `assets/bg/` and is embedded into the binary (`main.go`), because
|
||||||
js/wasm has no OS filesystem and `make binaries` packages the executable alone.
|
js/wasm has no OS filesystem and `make binaries` packages the executable alone.
|
||||||
|
|
||||||
## The map
|
## The map
|
||||||
|
|
||||||
Where a screen leads is recorded **in that screen**, in its own file, and it
|
Where a scene leads is recorded **in that scene**, in its own file, and it
|
||||||
comes from the wiki's location graph
|
comes from the wiki's location graph
|
||||||
(`projects/realworld/story#helyszín-gráf-vázlat`). That graph has two kinds of
|
(`projects/realworld/story#helyszín-gráf-vázlat`). That graph has two kinds of
|
||||||
edge and so does the code:
|
edge and so does the code:
|
||||||
|
|
||||||
- **Physical adjacency** — the alley is behind Noodle's house, the eating place
|
- **Physical adjacency** — the alley is behind Noodle's house, the eating place
|
||||||
is next door to the trinket shop, the club is through its back room, the roof
|
is next door to the trinket shop, the club is through its back room, the roof
|
||||||
is up Norman's stairs. Declared with `to:` in the screen's `exits`.
|
is up Norman's stairs. Declared with `To:` in the scene's `Exits`.
|
||||||
- **The selector** — the wiki centres its map on a *Helyszínválasztó*, "nem
|
- **The selector** — the wiki centres its map on a *Helyszínválasztó*, "nem
|
||||||
valódi helyszín, hanem a menü-képernyő": a screen every main location connects
|
valódi helyszín, hanem a menü-képernyő": a scene every main location connects
|
||||||
to both ways. A screen marks itself `onSelector: true`; `screen/selector.go`
|
to both ways. A main location lists `exitToSelector` among its exits, and
|
||||||
builds the other half of each of those edges, so the list of locations on the
|
`scene.selector.go` derives the other half of each edge by reading the graph
|
||||||
map is never written down twice.
|
backwards — every scene with an exit to the selector gets a pin on it. The
|
||||||
|
list of locations on the map is never written down twice.
|
||||||
|
|
||||||
The wiki's conditional arrows survive too: `needs:` holds the flag an exit waits
|
The wiki's conditional arrows survive too: `Needs:` holds the flag an exit waits
|
||||||
for, which is how *Bolt →|beengedés| Klub* is expressed — the way into the club
|
for, which is how *Bolt →|beengedés| Klub* is expressed — the way into the club
|
||||||
is visible and named from the first visit, and stays shut until the shopkeeper
|
is visible and named from the first visit, and stays shut until the shopkeeper
|
||||||
has been shown the underwater sun.
|
has been shown the underwater sun.
|
||||||
|
|
||||||
Until the doors are measured on the paintings, an exit is a strip along one edge
|
Until the doors are measured on the paintings, an exit is a strip along one edge
|
||||||
of the picture (`sideLeft`, `sideRight`, `sideBack`, `sideNear`) — the
|
of the picture (`inkwell.ExitLeft`, `ExitRight`, `ExitBack`, `ExitNear`), sized
|
||||||
convention every 1990s point & click used, and one field to re-aim later. A
|
from `Game.SceneRect` so it lands inside the painting rather than under the HUD
|
||||||
screen reached from several rooms has no fixed way out: the BBS terminal is the
|
— the convention every 1990s point & click used, and one field to re-aim later.
|
||||||
same terminal from the club, the flat or the roof, so its exit is `back`.
|
A scene reached from several rooms has no fixed way out: the BBS terminal is the
|
||||||
|
same terminal from the club, the flat or the roof, so its exit leaves `To` empty
|
||||||
|
and the engine binds it to `Back()`.
|
||||||
|
|
||||||
The graph stays machine-readable: exit hotspots are named `exit:<target>`, so
|
The graph stays machine-readable: exit hotspots are named `exit:<target>`, so
|
||||||
the connections can be read straight back out of the registered screens.
|
the connections can be read straight back out of the registered scenes — and
|
||||||
|
`Validate` rejects an exit that names a scene nobody registered.
|
||||||
|
|
||||||
## Engine workarounds
|
## Engine workarounds
|
||||||
|
|
||||||
Five inkwell limits turned up during implementation that the engine README does
|
Four inkwell limits turned up during implementation that the engine README does
|
||||||
not mention. All five are worked around on the domain side; each is a candidate
|
not mention. All four are worked around on the domain side; each is a candidate
|
||||||
for a small engine change.
|
for a small engine change.
|
||||||
|
|
||||||
|
Two others have been fixed in the engine since: exits are now
|
||||||
|
[`inkwell.Exit`](https://git.teletypegames.org/engines/inkwell) on the scene
|
||||||
|
itself, and `Game.CurrentScene()` / `PreviousScene()` mean the domain no longer
|
||||||
|
has to shadow where the player is.
|
||||||
|
|
||||||
1. **`drawText` discards colour.** In `asset.text.go` the colour argument is
|
1. **`drawText` discards colour.** In `asset.text.go` the colour argument is
|
||||||
`_ = c` and rendering goes through `ebitenutil.DebugPrintAt`, which only
|
`_ = c` and rendering goes through `ebitenutil.DebugPrintAt`, which only
|
||||||
draws white. Every text colour in `Theme` is therefore inert. *Workaround:*
|
draws white. Every text colour in `Theme` is therefore inert. *Workaround:*
|
||||||
@@ -308,16 +320,12 @@ for a small engine change.
|
|||||||
`handleSceneInput` and can consume the click, so unauthored pairs fail in
|
`handleSceneInput` and can consume the click, so unauthored pairs fail in
|
||||||
character instead, escalating on repeats.
|
character instead, escalating on repeats.
|
||||||
|
|
||||||
4. **No exported `CurrentScene()`**, but the pump needs `Ctx.Scene`.
|
4. **Widgets have no `Visible` field and the `Manager` cannot unregister**, so
|
||||||
*Workaround:* `EnterScene` is the first step of every scene's
|
|
||||||
`OnEnter`; the domain tracks it.
|
|
||||||
|
|
||||||
5. **Widgets have no `Visible` field and the `Manager` cannot unregister**, so
|
|
||||||
the built-in HUD cannot be hidden during a cutscene. *Workaround:* the
|
the built-in HUD cannot be hidden during a cutscene. *Workaround:* the
|
||||||
`gate` wrapper in `ui/ui.go` forwards `Tick`/`Draw`/`BlocksClickAt` only
|
`gate` wrapper in `ui/ui.go` forwards `Tick`/`Draw`/`BlocksClickAt` only
|
||||||
while the HUD is visible.
|
while the HUD is visible.
|
||||||
|
|
||||||
6. **`Run` hardcodes a 4× window** (`core.dsl.go`), which at 640×400 would be
|
5. **`Run` hardcodes a 4× window** (`core.dsl.go`), which at 640×400 would be
|
||||||
2560×1600 — bigger than most laptop screens. *Workaround:* the `windowSizer`
|
2560×1600 — bigger than most laptop screens. *Workaround:* the `windowSizer`
|
||||||
widget resizes once on the first tick, since Run sets the size before
|
widget resizes once on the first tick, since Run sets the size before
|
||||||
entering the loop.
|
entering the loop.
|
||||||
@@ -332,15 +340,15 @@ Also: the inkwell README gives the module path as
|
|||||||
stretched, but the strip is opaque and 118px of the 380 sit on top of the
|
stretched, but the strip is opaque and 118px of the 380 sit on top of the
|
||||||
picture. Either the deck gets recut so nothing that matters lives in its
|
picture. Either the deck gets recut so nothing that matters lives in its
|
||||||
bottom third, or the HUD gets a translucent panel treatment.
|
bottom third, or the HUD gets a translucent panel treatment.
|
||||||
- **The screens are empty.** 22 backgrounds are in and they are wired to each
|
- **The scenes are empty.** 22 backgrounds are in and they are wired to each
|
||||||
other, but only the alley has hotspots, NPCs and dialogue; everywhere else
|
other, but only the alley has hotspots, NPCs and dialogue; everywhere else
|
||||||
there is nothing to do but leave again.
|
there is nothing to do but leave again.
|
||||||
- **The selector has no art.** The wiki's Helyszínválasztó is the centre of the
|
- **The selector has no art.** The wiki's Helyszínválasztó is the centre of the
|
||||||
map and the deck does not include it, so it renders as a placeholder with one
|
map and the deck does not include it, so it renders as a placeholder with one
|
||||||
labelled pin per location on a plain grid.
|
labelled pin per location on a plain grid.
|
||||||
- **Two screens are missing from the deck.** The alley (the one authored beat)
|
- **Two scenes are missing from the deck.** The alley (the one authored beat)
|
||||||
and deck 05, Norman's workplace — which is in the wiki's catalogue but has no
|
and deck 05, Norman's workplace — which is in the wiki's catalogue but has no
|
||||||
screen file yet, so the workplace thread of the story has nowhere to happen.
|
scene file yet, so the workplace thread of the story has nowhere to happen.
|
||||||
- **Spent dialogue choices are hidden, not struck through.** `DialogueChoice.Once`
|
- **Spent dialogue choices are hidden, not struck through.** `DialogueChoice.Once`
|
||||||
hides them; the deck wanted them struck through but visible, so the list
|
hides them; the deck wanted them struck through but visible, so the list
|
||||||
becomes a memory of what you already tried. Needs a thin override over
|
becomes a memory of what you already tried. Needs a thin override over
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ module git.teletypegames.org/games/realworld
|
|||||||
go 1.26.3
|
go 1.26.3
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.teletypegames.org/engines/inkwell v0.1.0
|
git.teletypegames.org/engines/inkwell v0.1.1-0.20260829220920-f9745e426624
|
||||||
github.com/hajimehoshi/ebiten/v2 v2.9.9
|
github.com/hajimehoshi/ebiten/v2 v2.9.9
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
git.teletypegames.org/engines/inkwell v0.1.0 h1:NJgT924aR3e0uLVRiTEhzLrXJY+Vnj+FArkKqMJJlVI=
|
git.teletypegames.org/engines/inkwell v0.1.0 h1:NJgT924aR3e0uLVRiTEhzLrXJY+Vnj+FArkKqMJJlVI=
|
||||||
git.teletypegames.org/engines/inkwell v0.1.0/go.mod h1:/v6QtismTE8+e7kobbVR5B/CpTSrd4j2DYwJ8DvINhs=
|
git.teletypegames.org/engines/inkwell v0.1.0/go.mod h1:/v6QtismTE8+e7kobbVR5B/CpTSrd4j2DYwJ8DvINhs=
|
||||||
|
git.teletypegames.org/engines/inkwell v0.1.1-0.20260829220920-f9745e426624 h1:lzKbik6RzcqIEub13X8a1J3V/MCQOPNo2XF8oOKm+Ts=
|
||||||
|
git.teletypegames.org/engines/inkwell v0.1.1-0.20260829220920-f9745e426624/go.mod h1:/v6QtismTE8+e7kobbVR5B/CpTSrd4j2DYwJ8DvINhs=
|
||||||
github.com/ebitengine/gomobile v0.0.0-20250923094054-ea854a63cce1 h1:+kz5iTT3L7uU+VhlMfTb8hHcxLO3TlaELlX8wa4XjA0=
|
github.com/ebitengine/gomobile v0.0.0-20250923094054-ea854a63cce1 h1:+kz5iTT3L7uU+VhlMfTb8hHcxLO3TlaELlX8wa4XjA0=
|
||||||
github.com/ebitengine/gomobile v0.0.0-20250923094054-ea854a63cce1/go.mod h1:lKJoeixeJwnFmYsBny4vvCJGVFc3aYDalhuDsfZzWHI=
|
github.com/ebitengine/gomobile v0.0.0-20250923094054-ea854a63cce1/go.mod h1:lKJoeixeJwnFmYsBny4vvCJGVFc3aYDalhuDsfZzWHI=
|
||||||
github.com/ebitengine/hideconsole v1.0.0 h1:5J4U0kXF+pv/DhiXt5/lTz0eO5ogJ1iXb8Yj1yReDqE=
|
github.com/ebitengine/hideconsole v1.0.0 h1:5J4U0kXF+pv/DhiXt5/lTz0eO5ogJ1iXb8Yj1yReDqE=
|
||||||
|
|||||||
+10
-4
@@ -5,18 +5,25 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Opts struct {
|
type Opts struct {
|
||||||
Screen string
|
Scene string
|
||||||
Finale bool
|
Finale bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(o Opts) *inkwell.Game {
|
func New(o Opts) *inkwell.Game {
|
||||||
start := o.Screen
|
start := o.Scene
|
||||||
if start == "" {
|
if start == "" {
|
||||||
start = ScreenAlley
|
start = SceneAlley
|
||||||
}
|
}
|
||||||
|
|
||||||
g := inkwell.NewGame("Real World", ScreenW, ScreenH)
|
g := inkwell.NewGame("Real World", ScreenW, ScreenH)
|
||||||
g.MaxLogLines = 64
|
g.MaxLogLines = 64
|
||||||
|
g.SceneRect = inkwell.Rect(0, TopBarH, ScreenW, HUDTop-TopBarH)
|
||||||
|
g.ExitLook = func(e inkwell.Exit) inkwell.Action {
|
||||||
|
return inkwell.Say(Paul, "That way: "+e.Label+".")
|
||||||
|
}
|
||||||
|
g.ExitTake = func(inkwell.Exit) inkwell.Action {
|
||||||
|
return inkwell.Say(Paul, "It's a way out, not a thing.")
|
||||||
|
}
|
||||||
|
|
||||||
World.attach(g)
|
World.attach(g)
|
||||||
registerTheme()
|
registerTheme()
|
||||||
@@ -32,7 +39,6 @@ func New(o Opts) *inkwell.Game {
|
|||||||
|
|
||||||
func bootOpening(start string, finale bool) []inkwell.Action {
|
func bootOpening(start string, finale bool) []inkwell.Action {
|
||||||
acts := []inkwell.Action{
|
acts := []inkwell.Action{
|
||||||
EnterScene(start),
|
|
||||||
inkwell.SetFlag(FlagPoliceTip),
|
inkwell.SetFlag(FlagPoliceTip),
|
||||||
inkwell.Say(Paul, "Back alley. Just like the clerk said."),
|
inkwell.Say(Paul, "Back alley. Just like the clerk said."),
|
||||||
TapeSay(Dex, "A government office tipped you off to remove something from a scene. That doesn't strike you as odd?"),
|
TapeSay(Dex, "A government office tipped you off to remove something from a scene. That doesn't strike you as odd?"),
|
||||||
|
|||||||
@@ -6,5 +6,5 @@ func registerContent() {
|
|||||||
registerAll(ItemManager, World.G.ItemManager.Register)
|
registerAll(ItemManager, World.G.ItemManager.Register)
|
||||||
registerAll(DialogManager, World.G.DialogueManager.Register)
|
registerAll(DialogManager, World.G.DialogueManager.Register)
|
||||||
registerAll(ScriptManager, World.G.ScriptManager.Register)
|
registerAll(ScriptManager, World.G.ScriptManager.Register)
|
||||||
registerScreen()
|
registerScene()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,6 @@ var (
|
|||||||
_ ManagerInterface[Dialog] = DialogManager
|
_ ManagerInterface[Dialog] = DialogManager
|
||||||
_ ManagerInterface[Item] = ItemManager
|
_ ManagerInterface[Item] = ItemManager
|
||||||
_ ManagerInterface[Script] = ScriptManager
|
_ ManagerInterface[Script] = ScriptManager
|
||||||
_ ManagerInterface[Screen] = ScreenManager
|
_ ManagerInterface[Scene] = SceneManager
|
||||||
_ ManagerInterface[Theme] = ThemeManager
|
_ ManagerInterface[Theme] = ThemeManager
|
||||||
)
|
)
|
||||||
|
|||||||
+24
-24
@@ -36,30 +36,30 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ScreenSelector = "selector"
|
SceneSelector = "selector"
|
||||||
ScreenPaulShop = "paul_shop"
|
ScenePaulShop = "paul_shop"
|
||||||
ScreenNoodleHouse = "noodle_house"
|
SceneNoodleHouse = "noodle_house"
|
||||||
ScreenNormanApartment = "norman_apartment"
|
SceneNormanApartment = "norman_apartment"
|
||||||
ScreenPoliceStation = "police_station"
|
ScenePoliceStation = "police_station"
|
||||||
ScreenAlley = "alley"
|
SceneAlley = "alley"
|
||||||
ScreenHackerspace = "hackerspace"
|
SceneHackerspace = "hackerspace"
|
||||||
ScreenIceCreamShop = "ice_cream_shop"
|
SceneIceCreamShop = "ice_cream_shop"
|
||||||
ScreenTrinketShop = "trinket_shop"
|
SceneTrinketShop = "trinket_shop"
|
||||||
ScreenSmallRestaurant = "small_restaurant"
|
SceneSmallRestaurant = "small_restaurant"
|
||||||
ScreenSecretClub = "secret_club"
|
SceneSecretClub = "secret_club"
|
||||||
ScreenBBSTerminal = "bbs_terminal"
|
SceneBBSTerminal = "bbs_terminal"
|
||||||
ScreenStreet = "street"
|
SceneStreet = "street"
|
||||||
ScreenHospital = "hospital"
|
SceneHospital = "hospital"
|
||||||
ScreenServerFarm = "server_farm"
|
SceneServerFarm = "server_farm"
|
||||||
ScreenSecretLab = "secret_lab"
|
SceneSecretLab = "secret_lab"
|
||||||
ScreenRooftopHideout = "rooftop_hideout"
|
SceneRooftopHideout = "rooftop_hideout"
|
||||||
ScreenPublicBBS = "public_bbs"
|
ScenePublicBBS = "public_bbs"
|
||||||
ScreenBVKBranch = "bvk_branch"
|
SceneBVKBranch = "bvk_branch"
|
||||||
ScreenCuratorShop = "curator_shop"
|
SceneCuratorShop = "curator_shop"
|
||||||
ScreenScrapMarket = "scrap_market"
|
SceneScrapMarket = "scrap_market"
|
||||||
ScreenSamizdatPress = "samizdat_press"
|
SceneSamizdatPress = "samizdat_press"
|
||||||
ScreenShowroom = "showroom"
|
SceneShowroom = "showroom"
|
||||||
ScreenColumbarium = "columbarium"
|
SceneColumbarium = "columbarium"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
ScreenManager.Register(Screen{
|
SceneManager.Register(Scene{
|
||||||
Name: ScreenAlley,
|
Name: SceneAlley,
|
||||||
Title: "ALLEY — BEHIND NOODLE'S HOUSE",
|
Title: "ALLEY — BEHIND NOODLE'S HOUSE",
|
||||||
Background: BgAlley,
|
Background: BgAlley,
|
||||||
Exits: []exit{
|
Exits: []inkwell.Exit{
|
||||||
{
|
{
|
||||||
to: ScreenNoodleHouse,
|
To: SceneNoodleHouse,
|
||||||
label: "back out to the street",
|
Label: "back out to the street",
|
||||||
side: sideLeft,
|
Side: inkwell.ExitLeft,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Actors: []inkwell.SceneActor{
|
Actors: []inkwell.SceneActor{
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneBBSTerminal,
|
||||||
|
Title: "TERMINAL — BBS ACCESS POINT",
|
||||||
|
Background: BgBBSTerminal,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
{
|
||||||
|
Label: "step back from the terminal",
|
||||||
|
Side: inkwell.ExitNear,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneBVKBranch,
|
||||||
|
Title: "BVK — SAN FRANCISCO BRANCH",
|
||||||
|
Background: BgBVKBranch,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
exitToSelector,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneColumbarium,
|
||||||
|
Title: "COLUMBARIUM — DEX'S MEMORIAL",
|
||||||
|
Background: BgColumbarium,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
exitToSelector,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneCuratorShop,
|
||||||
|
Title: "CURATOR SERVICE — THE MASTER'S WORKSHOP",
|
||||||
|
Background: BgCuratorShop,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
exitToSelector,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneHackerspace,
|
||||||
|
Title: "HACKERSPACE",
|
||||||
|
Background: BgHackerspace,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
exitToSelector,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneHospital,
|
||||||
|
Title: "HOSPITAL — PSYCHIATRIC WING",
|
||||||
|
Background: BgHospital,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
exitToSelector,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneIceCreamShop,
|
||||||
|
Title: "ICE CREAM SHOP — WHERE THE BAR WAS",
|
||||||
|
Background: BgIceCreamShop,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
exitToSelector,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Scene = inkwell.Scene
|
||||||
|
|
||||||
|
var SceneManager = NewManager(func(entity Scene) string { return entity.Name })
|
||||||
|
|
||||||
|
func registerScene() {
|
||||||
|
fillSelectorPins()
|
||||||
|
registerAll(SceneManager, func(entity Scene) {
|
||||||
|
World.G.SceneManager.Register(sceneDefaults(entity))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var sceneFloor = []inkwell.Polygon{
|
||||||
|
inkwell.Poly(
|
||||||
|
inkwell.Point{
|
||||||
|
X: 16,
|
||||||
|
Y: 196,
|
||||||
|
}, inkwell.Point{
|
||||||
|
X: 624,
|
||||||
|
Y: 196,
|
||||||
|
},
|
||||||
|
inkwell.Point{
|
||||||
|
X: 624,
|
||||||
|
Y: 258,
|
||||||
|
}, inkwell.Point{
|
||||||
|
X: 16,
|
||||||
|
Y: 258,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
func sceneDefaults(s Scene) Scene {
|
||||||
|
if s.Actors == nil {
|
||||||
|
s.Actors = []inkwell.SceneActor{
|
||||||
|
{
|
||||||
|
CharacterName: Paul,
|
||||||
|
At: inkwell.Point{
|
||||||
|
X: 320,
|
||||||
|
Y: 232,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if s.Walkboxes == nil {
|
||||||
|
s.Walkboxes = sceneFloor
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func setVarIfEmpty(name string, v any) inkwell.Action {
|
||||||
|
return Fn(func(ctx *inkwell.Ctx) {
|
||||||
|
if ctx.Game.State.Var(name) == nil {
|
||||||
|
ctx.Game.State.SetVar(name, v)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneNoodleHouse,
|
||||||
|
Title: "NOODLE'S HOUSE — SEALED",
|
||||||
|
Background: BgNoodleHouse,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
exitToSelector,
|
||||||
|
{
|
||||||
|
To: SceneAlley,
|
||||||
|
Label: "the alley behind the house",
|
||||||
|
Side: inkwell.ExitRight,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneNormanApartment,
|
||||||
|
Title: "NORMAN'S APARTMENT",
|
||||||
|
Background: BgNormanApartment,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
exitToSelector,
|
||||||
|
{
|
||||||
|
To: SceneRooftopHideout,
|
||||||
|
Label: "the stairs up to the roof",
|
||||||
|
Side: inkwell.ExitBack,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
To: SceneBBSTerminal,
|
||||||
|
Label: "Norman's terminal",
|
||||||
|
Side: inkwell.ExitRight,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: ScenePaulShop,
|
||||||
|
Title: "PAUL'S SHOP — JUNK AND GARAGE",
|
||||||
|
Background: BgPaulShop,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
{
|
||||||
|
To: SceneNoodleHouse,
|
||||||
|
Label: "the bus to San Francisco",
|
||||||
|
Side: inkwell.ExitNear,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: ScenePoliceStation,
|
||||||
|
Title: "SFPD — STATION AND HOLDING",
|
||||||
|
Background: BgPoliceStation,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
exitToSelector,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: ScenePublicBBS,
|
||||||
|
Title: "PUBLIC BBS TERMINAL",
|
||||||
|
Background: BgPublicBBS,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
exitToSelector,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneRooftopHideout,
|
||||||
|
Title: "NORMAN'S ROOFTOP HIDEOUT",
|
||||||
|
Background: BgRooftopHideout,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
{
|
||||||
|
To: SceneNormanApartment,
|
||||||
|
Label: "back down into the flat",
|
||||||
|
Side: inkwell.ExitNear,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
To: SceneBBSTerminal,
|
||||||
|
Label: "the old terminal",
|
||||||
|
Side: inkwell.ExitRight,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneSamizdatPress,
|
||||||
|
Title: "SAMIZDAT PRINTING HOUSE",
|
||||||
|
Background: BgSamizdatPress,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
exitToSelector,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneScrapMarket,
|
||||||
|
Title: "SCRAP MARKET",
|
||||||
|
Background: BgScrapMarket,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
exitToSelector,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneSecretClub,
|
||||||
|
Title: "SECRET CLUB — THE UNDERWATER SUN",
|
||||||
|
Background: BgSecretClub,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
{
|
||||||
|
To: SceneBBSTerminal,
|
||||||
|
Label: "the terminal in the corner",
|
||||||
|
Side: inkwell.ExitBack,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
To: SceneTrinketShop,
|
||||||
|
Label: "back out through the shop",
|
||||||
|
Side: inkwell.ExitNear,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneSecretLab,
|
||||||
|
Title: "SECRET RESEARCH LABORATORY",
|
||||||
|
Background: BgSecretLab,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
exitToSelector,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -6,9 +6,15 @@ import (
|
|||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var exitToSelector = inkwell.Exit{
|
||||||
|
To: SceneSelector,
|
||||||
|
Label: "the rest of the city",
|
||||||
|
Side: inkwell.ExitNear,
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
ScreenManager.Register(Screen{
|
SceneManager.Register(Scene{
|
||||||
Name: ScreenSelector,
|
Name: SceneSelector,
|
||||||
Title: "SAN FRANCISCO",
|
Title: "SAN FRANCISCO",
|
||||||
Background: BgSelector,
|
Background: BgSelector,
|
||||||
Actors: []inkwell.SceneActor{},
|
Actors: []inkwell.SceneActor{},
|
||||||
@@ -17,23 +23,32 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func fillSelectorPins() {
|
func fillSelectorPins() {
|
||||||
selector, ok := ScreenManager.GetByName(ScreenSelector)
|
selector, ok := SceneManager.GetByName(SceneSelector)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var exits []exit
|
var exits []inkwell.Exit
|
||||||
for _, entity := range ScreenManager.GetAll() {
|
for _, entity := range SceneManager.GetAll() {
|
||||||
if !entity.OnSelector {
|
if !leadsToSelector(entity) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
exits = append(exits, exit{
|
exits = append(exits, inkwell.Exit{
|
||||||
to: entity.Name,
|
To: entity.Name,
|
||||||
label: pinLabel(entity.Title),
|
Label: pinLabel(entity.Title),
|
||||||
area: pin(len(exits)),
|
Area: pin(len(exits)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
selector.Exits = exits
|
selector.Exits = exits
|
||||||
ScreenManager.Register(selector)
|
SceneManager.Register(selector)
|
||||||
|
}
|
||||||
|
|
||||||
|
func leadsToSelector(s Scene) bool {
|
||||||
|
for _, e := range s.Exits {
|
||||||
|
if e.To == SceneSelector {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneServerFarm,
|
||||||
|
Title: "SERVER FARM",
|
||||||
|
Background: BgServerFarm,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
exitToSelector,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneShowroom,
|
||||||
|
Title: "NEUMATRONIC SHOWROOM",
|
||||||
|
Background: BgShowroom,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
exitToSelector,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneSmallRestaurant,
|
||||||
|
Title: "SMALL RESTAURANT — NEXT DOOR",
|
||||||
|
Background: BgSmallRestaurant,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
{
|
||||||
|
To: SceneTrinketShop,
|
||||||
|
Label: "back to the trinket shop",
|
||||||
|
Side: inkwell.ExitLeft,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneStreet,
|
||||||
|
Title: "STREET",
|
||||||
|
Background: BgStreet,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
exitToSelector,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SceneManager.Register(Scene{
|
||||||
|
Name: SceneTrinketShop,
|
||||||
|
Title: "CHINATOWN — TRINKET SHOP",
|
||||||
|
Background: BgTrinketShop,
|
||||||
|
Exits: []inkwell.Exit{
|
||||||
|
exitToSelector,
|
||||||
|
{
|
||||||
|
To: SceneSmallRestaurant,
|
||||||
|
Label: "the eating place next door",
|
||||||
|
Side: inkwell.ExitRight,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
To: SceneSecretClub,
|
||||||
|
Label: "the way in at the back",
|
||||||
|
Side: inkwell.ExitBack,
|
||||||
|
Needs: FlagClubEntry,
|
||||||
|
Blocked: inkwell.Say(Paul, "Just a shop, as far as the man behind the counter is concerned."),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenBBSTerminal,
|
|
||||||
Title: "TERMINAL — BBS ACCESS POINT",
|
|
||||||
Background: BgBBSTerminal,
|
|
||||||
Exits: []exit{
|
|
||||||
{
|
|
||||||
label: "step back from the terminal",
|
|
||||||
side: sideNear,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenBVKBranch,
|
|
||||||
Title: "BVK — SAN FRANCISCO BRANCH",
|
|
||||||
Background: BgBVKBranch,
|
|
||||||
OnSelector: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenColumbarium,
|
|
||||||
Title: "COLUMBARIUM — DEX'S MEMORIAL",
|
|
||||||
Background: BgColumbarium,
|
|
||||||
OnSelector: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenCuratorShop,
|
|
||||||
Title: "CURATOR SERVICE — THE MASTER'S WORKSHOP",
|
|
||||||
Background: BgCuratorShop,
|
|
||||||
OnSelector: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
import (
|
|
||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
|
||||||
)
|
|
||||||
|
|
||||||
type side int
|
|
||||||
|
|
||||||
const (
|
|
||||||
sideLeft side = iota
|
|
||||||
sideRight
|
|
||||||
sideBack
|
|
||||||
sideNear
|
|
||||||
)
|
|
||||||
|
|
||||||
func (s side) area() inkwell.Shape {
|
|
||||||
switch s {
|
|
||||||
case sideLeft:
|
|
||||||
return inkwell.Rect(0, 40, 56, 212)
|
|
||||||
case sideRight:
|
|
||||||
return inkwell.Rect(584, 40, 56, 212)
|
|
||||||
case sideBack:
|
|
||||||
return inkwell.Rect(232, 28, 176, 84)
|
|
||||||
default:
|
|
||||||
return inkwell.Rect(232, 214, 176, 48)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type exit struct {
|
|
||||||
to string
|
|
||||||
label string
|
|
||||||
side side
|
|
||||||
|
|
||||||
area inkwell.Shape
|
|
||||||
|
|
||||||
needs string
|
|
||||||
blocked string
|
|
||||||
}
|
|
||||||
|
|
||||||
func toSelector() exit {
|
|
||||||
return exit{
|
|
||||||
to: ScreenSelector,
|
|
||||||
label: "the rest of the city",
|
|
||||||
side: sideNear,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func exitName(to string) string {
|
|
||||||
if to == "" {
|
|
||||||
return "exit:back"
|
|
||||||
}
|
|
||||||
return "exit:" + to
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e exit) hotspot() inkwell.Hotspot {
|
|
||||||
var travel inkwell.Action = inkwell.GoTo(e.to)
|
|
||||||
if e.to == "" {
|
|
||||||
travel = Back()
|
|
||||||
}
|
|
||||||
if e.needs != "" {
|
|
||||||
travel = inkwell.If(inkwell.Flag(e.needs), travel, inkwell.Say(Paul, e.blocked))
|
|
||||||
}
|
|
||||||
area := e.area
|
|
||||||
if area == nil {
|
|
||||||
area = e.side.area()
|
|
||||||
}
|
|
||||||
return inkwell.Hotspot{
|
|
||||||
Name: exitName(e.to),
|
|
||||||
Label: e.label,
|
|
||||||
Area: area,
|
|
||||||
Cursor: inkwell.CursorExit,
|
|
||||||
OnLook: inkwell.Say(Paul, "That way: "+e.label+"."),
|
|
||||||
OnUse: travel,
|
|
||||||
OnTake: inkwell.Say(Paul, "It's a way out, not a thing."),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenHackerspace,
|
|
||||||
Title: "HACKERSPACE",
|
|
||||||
Background: BgHackerspace,
|
|
||||||
OnSelector: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenHospital,
|
|
||||||
Title: "HOSPITAL — PSYCHIATRIC WING",
|
|
||||||
Background: BgHospital,
|
|
||||||
OnSelector: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenIceCreamShop,
|
|
||||||
Title: "ICE CREAM SHOP — WHERE THE BAR WAS",
|
|
||||||
Background: BgIceCreamShop,
|
|
||||||
OnSelector: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
import (
|
|
||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Screen struct {
|
|
||||||
Name string
|
|
||||||
Title string
|
|
||||||
Background string
|
|
||||||
|
|
||||||
Exits []exit
|
|
||||||
|
|
||||||
OnSelector bool
|
|
||||||
|
|
||||||
Hotspots []inkwell.Hotspot
|
|
||||||
Actors []inkwell.SceneActor
|
|
||||||
Walkboxes []inkwell.Polygon
|
|
||||||
OnEnter inkwell.Action
|
|
||||||
}
|
|
||||||
|
|
||||||
var ScreenManager = NewManager(func(entity Screen) string { return entity.Name })
|
|
||||||
|
|
||||||
func registerScreen() {
|
|
||||||
fillSelectorPins()
|
|
||||||
registerAll(ScreenManager, func(entity Screen) {
|
|
||||||
World.G.SceneManager.Register(screenBuild(entity))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var screenFloor = []inkwell.Polygon{
|
|
||||||
inkwell.Poly(
|
|
||||||
inkwell.Point{
|
|
||||||
X: 16,
|
|
||||||
Y: 196,
|
|
||||||
}, inkwell.Point{
|
|
||||||
X: 624,
|
|
||||||
Y: 196,
|
|
||||||
},
|
|
||||||
inkwell.Point{
|
|
||||||
X: 624,
|
|
||||||
Y: 258,
|
|
||||||
}, inkwell.Point{
|
|
||||||
X: 16,
|
|
||||||
Y: 258,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
func screenBuild(s Screen) inkwell.Scene {
|
|
||||||
exits := s.Exits
|
|
||||||
if s.OnSelector {
|
|
||||||
exits = append(exits, toSelector())
|
|
||||||
}
|
|
||||||
hotspots := make([]inkwell.Hotspot, 0, len(exits)+len(s.Hotspots))
|
|
||||||
hotspots = append(hotspots, s.Hotspots...)
|
|
||||||
for _, e := range exits {
|
|
||||||
hotspots = append(hotspots, e.hotspot())
|
|
||||||
}
|
|
||||||
|
|
||||||
actors := s.Actors
|
|
||||||
if actors == nil {
|
|
||||||
actors = []inkwell.SceneActor{
|
|
||||||
{
|
|
||||||
CharacterName: Paul,
|
|
||||||
At: inkwell.Point{
|
|
||||||
X: 320,
|
|
||||||
Y: 232,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
walkboxes := s.Walkboxes
|
|
||||||
if walkboxes == nil {
|
|
||||||
walkboxes = screenFloor
|
|
||||||
}
|
|
||||||
onEnter := inkwell.Action(EnterScene(s.Name))
|
|
||||||
if s.OnEnter != nil {
|
|
||||||
onEnter = inkwell.Seq(onEnter, s.OnEnter)
|
|
||||||
}
|
|
||||||
|
|
||||||
return inkwell.Scene{
|
|
||||||
Name: s.Name,
|
|
||||||
Title: s.Title,
|
|
||||||
Background: s.Background,
|
|
||||||
Actors: actors,
|
|
||||||
Walkboxes: walkboxes,
|
|
||||||
Hotspots: hotspots,
|
|
||||||
OnEnter: onEnter,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setVarIfEmpty(name string, v any) inkwell.Action {
|
|
||||||
return Fn(func(ctx *inkwell.Ctx) {
|
|
||||||
if ctx.Game.State.Var(name) == nil {
|
|
||||||
ctx.Game.State.SetVar(name, v)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenNoodleHouse,
|
|
||||||
Title: "NOODLE'S HOUSE — SEALED",
|
|
||||||
Background: BgNoodleHouse,
|
|
||||||
OnSelector: true,
|
|
||||||
Exits: []exit{
|
|
||||||
{
|
|
||||||
to: ScreenAlley,
|
|
||||||
label: "the alley behind the house",
|
|
||||||
side: sideRight,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenNormanApartment,
|
|
||||||
Title: "NORMAN'S APARTMENT",
|
|
||||||
Background: BgNormanApartment,
|
|
||||||
OnSelector: true,
|
|
||||||
Exits: []exit{
|
|
||||||
{
|
|
||||||
to: ScreenRooftopHideout,
|
|
||||||
label: "the stairs up to the roof",
|
|
||||||
side: sideBack,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
to: ScreenBBSTerminal,
|
|
||||||
label: "Norman's terminal",
|
|
||||||
side: sideRight,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenPaulShop,
|
|
||||||
Title: "PAUL'S SHOP — JUNK AND GARAGE",
|
|
||||||
Background: BgPaulShop,
|
|
||||||
Exits: []exit{
|
|
||||||
{
|
|
||||||
to: ScreenNoodleHouse,
|
|
||||||
label: "the bus to San Francisco",
|
|
||||||
side: sideNear,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenPoliceStation,
|
|
||||||
Title: "SFPD — STATION AND HOLDING",
|
|
||||||
Background: BgPoliceStation,
|
|
||||||
OnSelector: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenPublicBBS,
|
|
||||||
Title: "PUBLIC BBS TERMINAL",
|
|
||||||
Background: BgPublicBBS,
|
|
||||||
OnSelector: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenRooftopHideout,
|
|
||||||
Title: "NORMAN'S ROOFTOP HIDEOUT",
|
|
||||||
Background: BgRooftopHideout,
|
|
||||||
Exits: []exit{
|
|
||||||
{
|
|
||||||
to: ScreenNormanApartment,
|
|
||||||
label: "back down into the flat",
|
|
||||||
side: sideNear,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
to: ScreenBBSTerminal,
|
|
||||||
label: "the old terminal",
|
|
||||||
side: sideRight,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenSamizdatPress,
|
|
||||||
Title: "SAMIZDAT PRINTING HOUSE",
|
|
||||||
Background: BgSamizdatPress,
|
|
||||||
OnSelector: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenScrapMarket,
|
|
||||||
Title: "SCRAP MARKET",
|
|
||||||
Background: BgScrapMarket,
|
|
||||||
OnSelector: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenSecretClub,
|
|
||||||
Title: "SECRET CLUB — THE UNDERWATER SUN",
|
|
||||||
Background: BgSecretClub,
|
|
||||||
Exits: []exit{
|
|
||||||
{
|
|
||||||
to: ScreenBBSTerminal,
|
|
||||||
label: "the terminal in the corner",
|
|
||||||
side: sideBack,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
to: ScreenTrinketShop,
|
|
||||||
label: "back out through the shop",
|
|
||||||
side: sideNear,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenSecretLab,
|
|
||||||
Title: "SECRET RESEARCH LABORATORY",
|
|
||||||
Background: BgSecretLab,
|
|
||||||
OnSelector: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenServerFarm,
|
|
||||||
Title: "SERVER FARM",
|
|
||||||
Background: BgServerFarm,
|
|
||||||
OnSelector: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenShowroom,
|
|
||||||
Title: "NEUMATRONIC SHOWROOM",
|
|
||||||
Background: BgShowroom,
|
|
||||||
OnSelector: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenSmallRestaurant,
|
|
||||||
Title: "SMALL RESTAURANT — NEXT DOOR",
|
|
||||||
Background: BgSmallRestaurant,
|
|
||||||
Exits: []exit{
|
|
||||||
{
|
|
||||||
to: ScreenTrinketShop,
|
|
||||||
label: "back to the trinket shop",
|
|
||||||
side: sideLeft,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenStreet,
|
|
||||||
Title: "STREET",
|
|
||||||
Background: BgStreet,
|
|
||||||
OnSelector: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ScreenManager.Register(Screen{
|
|
||||||
Name: ScreenTrinketShop,
|
|
||||||
Title: "CHINATOWN — TRINKET SHOP",
|
|
||||||
Background: BgTrinketShop,
|
|
||||||
OnSelector: true,
|
|
||||||
Exits: []exit{
|
|
||||||
{
|
|
||||||
to: ScreenSmallRestaurant,
|
|
||||||
label: "the eating place next door",
|
|
||||||
side: sideRight,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
to: ScreenSecretClub,
|
|
||||||
label: "the way in at the back",
|
|
||||||
side: sideBack,
|
|
||||||
needs: FlagClubEntry,
|
|
||||||
blocked: "Just a shop, as far as the man behind the counter is concerned.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
+2
-2
@@ -36,8 +36,8 @@ func registerUI() {
|
|||||||
g.UIManager.Register(&actionPump{
|
g.UIManager.Register(&actionPump{
|
||||||
Name: "pump",
|
Name: "pump",
|
||||||
})
|
})
|
||||||
g.UIManager.Register(&screenNav{
|
g.UIManager.Register(&sceneNav{
|
||||||
Name: "screen_nav",
|
Name: "scene_nav",
|
||||||
})
|
})
|
||||||
g.UIManager.Register(&windowSizer{
|
g.UIManager.Register(&windowSizer{
|
||||||
Name: "window",
|
Name: "window",
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
||||||
)
|
)
|
||||||
|
|
||||||
type screenNav struct {
|
type sceneNav struct {
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *screenNav) GetName() string { return n.Name }
|
func (n *sceneNav) GetName() string { return n.Name }
|
||||||
func (n *screenNav) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {}
|
func (n *sceneNav) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {}
|
||||||
|
|
||||||
func (n *screenNav) Tick(ctx *inkwell.UICtx) {
|
func (n *sceneNav) Tick(ctx *inkwell.UICtx) {
|
||||||
if !World.HUDVisible() || World.Paused() {
|
if !World.HUDVisible() || World.Paused() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -32,13 +32,13 @@ func (n *screenNav) Tick(ctx *inkwell.UICtx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *screenNav) neighbour(g *inkwell.Game, step int) string {
|
func (n *sceneNav) neighbour(g *inkwell.Game, step int) string {
|
||||||
deck := g.SceneManager.Names()
|
deck := g.SceneManager.Names()
|
||||||
if len(deck) < 2 {
|
if len(deck) < 2 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
for i, name := range deck {
|
for i, name := range deck {
|
||||||
if name == World.Scene() {
|
if name == World.G.CurrentScene() {
|
||||||
return deck[((i+step)%len(deck)+len(deck))%len(deck)]
|
return deck[((i+step)%len(deck)+len(deck))%len(deck)]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-20
@@ -32,7 +32,7 @@ func (w *world) PumpTick(dt float64) {
|
|||||||
Game: w.G,
|
Game: w.G,
|
||||||
DT: dt,
|
DT: dt,
|
||||||
}
|
}
|
||||||
if s, ok := w.G.SceneManager.Get(w.scene); ok {
|
if s, ok := w.G.SceneManager.Get(w.G.CurrentScene()); ok {
|
||||||
ctx.Scene = &s
|
ctx.Scene = &s
|
||||||
}
|
}
|
||||||
if w.running.Tick(ctx) != inkwell.StatusRunning {
|
if w.running.Tick(ctx) != inkwell.StatusRunning {
|
||||||
@@ -41,7 +41,7 @@ func (w *world) PumpTick(dt float64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *world) sceneTitle() string {
|
func (w *world) sceneTitle() string {
|
||||||
s, ok := w.G.SceneManager.Get(w.scene)
|
s, ok := w.G.SceneManager.Get(w.G.CurrentScene())
|
||||||
if !ok {
|
if !ok {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -88,24 +88,6 @@ func SetMode(m Mode) inkwell.Action {
|
|||||||
return Fn(func(*inkwell.Ctx) { World.SetMode(m) })
|
return Fn(func(*inkwell.Ctx) { World.SetMode(m) })
|
||||||
}
|
}
|
||||||
|
|
||||||
func EnterScene(name string) inkwell.Action {
|
|
||||||
return Fn(func(*inkwell.Ctx) {
|
|
||||||
if name != World.scene {
|
|
||||||
World.prev = World.scene
|
|
||||||
}
|
|
||||||
World.scene = name
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Back() inkwell.Action {
|
|
||||||
return Fn(func(ctx *inkwell.Ctx) {
|
|
||||||
if World.prev == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
inkwell.GoTo(World.prev).Start().Tick(ctx)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TapeSay(speaker, text string) inkwell.Action {
|
func TapeSay(speaker, text string) inkwell.Action {
|
||||||
return &tapeSayAction{
|
return &tapeSayAction{
|
||||||
speaker: speaker,
|
speaker: speaker,
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ type world struct {
|
|||||||
|
|
||||||
mode Mode
|
mode Mode
|
||||||
|
|
||||||
scene string
|
|
||||||
prev string
|
|
||||||
paused bool
|
paused bool
|
||||||
pending string
|
pending string
|
||||||
queue []inkwell.Action
|
queue []inkwell.Action
|
||||||
@@ -34,8 +32,6 @@ var World = &world{}
|
|||||||
func (w *world) attach(g *inkwell.Game) {
|
func (w *world) attach(g *inkwell.Game) {
|
||||||
w.G = g
|
w.G = g
|
||||||
w.mode = ModePlay
|
w.mode = ModePlay
|
||||||
w.scene = ""
|
|
||||||
w.prev = ""
|
|
||||||
w.paused = false
|
w.paused = false
|
||||||
w.pending = ""
|
w.pending = ""
|
||||||
w.queue = nil
|
w.queue = nil
|
||||||
@@ -51,10 +47,6 @@ func (w *world) SetMode(m Mode) { w.mode = m }
|
|||||||
|
|
||||||
func (w *world) HUDVisible() bool { return w.mode == ModePlay }
|
func (w *world) HUDVisible() bool { return w.mode == ModePlay }
|
||||||
|
|
||||||
func (w *world) Scene() string { return w.scene }
|
|
||||||
|
|
||||||
func (w *world) Previous() string { return w.prev }
|
|
||||||
|
|
||||||
func (w *world) Paused() bool { return w.paused }
|
func (w *world) Paused() bool { return w.paused }
|
||||||
|
|
||||||
func (w *world) SetTopBar(t *inkwell.TopBar) { w.top = t }
|
func (w *world) SetTopBar(t *inkwell.TopBar) { w.top = t }
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ func init() { inkwell.AssetFS = assets }
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var o inc.Opts
|
var o inc.Opts
|
||||||
flag.StringVar(&o.Screen, "screen", "", "starting screen (empty: the alley)")
|
flag.StringVar(&o.Scene, "scene", "", "starting scene (empty: the alley)")
|
||||||
flag.BoolVar(&o.Finale, "finale", false,
|
flag.BoolVar(&o.Finale, "finale", false,
|
||||||
"start with the finale, to try the Nokia-punk theme switch")
|
"start with the finale, to try the Nokia-punk theme switch")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|||||||
Reference in New Issue
Block a user