feat(bundle): ship a game as a macOS .app, with a splash it controls
`ludic build` produces a program. Double-clicked it opens a Terminal window, it wears the generic executable icon, it calls itself whatever the file is called, and it carries none of its assets. `ludic bundle` produces an application. Everything it needs is in package.ludic, so the command takes no arguments: an Info.plist and PkgInfo from `app` lines, an .icns built by sips and iconutil at all ten sizes macOS asks for from a single source PNG, the asset pack in Contents/Resources, and an ad-hoc signature - which is not optional on Apple silicon, where an unsigned binary is killed rather than warned about. The bundle identifier falls back to the package path reversed, so a project that never thinks about it still gets a defensible one instead of two apps sharing a key Launch Services hangs the Dock, saved state and permissions off. A bundled game is moved to ~/Library/Application Support/<name> before main, because Finder starts a .app with its working directory at "/" where no save could ever be written. Reads come out of the pack, writes land somewhere real and per-user, and the game's save code needs no change and no platform knowledge. The splash is the other half of looking like an application. A game that loads 165 MB spends a visible moment doing it with nothing on screen, which from the outside is indistinguishable from a launch that failed. splash_show puts a borderless window up from the same constructor that mounts the pack - before main, so it appears while the process is still starting rather than after the slow part it exists to cover - and reads the artwork out of the pack like any other asset. It turns the run loop enough times to be mapped and composited there and then; once composited the backing store survives a busy main thread, so it stays up for the whole load. Nothing hides it automatically. Only the game knows when its first real frame is ready, and a splash that vanishes before that leaves the same black gap it was covering, so the game calls App.splash_hide(). Headless there is no splash and the call lowers to nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
ce5bf0fe0e
commit
be74b4de6f
14 changed files with 34667 additions and 33621 deletions
7
docs/language/app/_section.md
Normal file
7
docs/language/app/_section.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
id: app
|
||||
title: App
|
||||
order: 48
|
||||
---
|
||||
|
||||
The running application, as distinct from its window. Today that is the boot splash: the runtime raises it before <code>main</code> from the game's asset pack, and <a href="app-splash_hide"><code>App.splash_hide</code></a> takes it down when the game has something to show instead.
|
||||
33
docs/language/app/app-splash_hide.md
Normal file
33
docs/language/app/app-splash_hide.md
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
id: app-splash_hide
|
||||
name: App.splash_hide
|
||||
category: app
|
||||
kind: namespace-method
|
||||
tokens: App.splash_hide
|
||||
sig: App.splash_hide() -> void
|
||||
tip: Dismiss the boot splash.
|
||||
order: 1
|
||||
ns: App
|
||||
member: splash_hide
|
||||
---
|
||||
|
||||
Dismisses the boot splash. Safe to call when there is no splash, and safe to call twice.
|
||||
|
||||
A bundled game shows a splash while it starts: `ludic bundle` records `app splash` from the manifest into the bundle, and the runtime puts it on screen before `main` runs, out of the asset pack. Nothing takes it down on its own, because nothing else knows when the game has a first frame worth showing - a splash that disappears while the terrain is still loading leaves the same black gap it was there to cover.
|
||||
|
||||
So the game says when:
|
||||
|
||||
```ludic skip
|
||||
program MyGame {
|
||||
entry {
|
||||
load_the_world() # the slow part the splash is covering
|
||||
open_the_window()
|
||||
draw_one_frame()
|
||||
App.splash_hide() # ...and only now
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Headless there is no splash and no window, and the call lowers to nothing.
|
||||
|
||||
See also: <a href="../../SHIPPING">shipping a game</a>.
|
||||
Loading…
Add table
Add a link
Reference in a new issue