type GameConfig = {
/**
* The id of the container element for the game
* @default "__narraleaf_content"
*/
contentContainerId: string;
/**
* The aspect ratio of the game
* Ex: 16/9, 4/3, 1/1
* @default 16/9
*/
aspectRatio: number;
/**
* The minimum width and height of the player in pixels
* @default 800
*/
minWidth: number;
/**
* The minimum width and height of the player in pixels
* @default 450
*/
minHeight: number;
/**
* Base width of the player in pixels, Image scale will be calculated based on this value
*
* For 16/9, the recommended value is 1920
* @default 1920
*/
width: number;
/**
* Base height of the player in pixels, Image scale will be calculated based on this value
*
* For 16/9, the recommended value is 1080
* @default 1080
*/
height: number;
/**
* If true, the game will listen to the window events instead of the player element
*
* Using this will allow the game to listen to the keyboard events even when the player is not focused
* Resulting in a better user experience on skipping actions
* @default true
*/
useWindowListener: boolean;
/**
* The debounced interval in milliseconds for updating the aspect ratio
*
* Set to 0 to update the ratio immediately on every resize event.
* @default 50
*/
ratioUpdateInterval: number;
/**
* The game will preload the image with this delay between each preload task
*
* A single preload task may contain {@link GameConfig.preloadConcurrency} images
* @default 100
*/
preloadDelay: number;
/**
* Maximum number of images to preload at the same time
* @default 5
*/
preloadConcurrency: number;
/**
* Wait for the images to load before showing the game
* @default true
*/
waitForPreload: boolean;
/**
* Preload all possible images in the scene
*
* Enabling this may have a performance impact but is better for the user experience
* @default true
*/
preloadAllImages: boolean;
/**
* Force the game to clear the cache when the scene changes
* @default false
*/
forceClearCache: boolean;
/**
* The number of actions will be predicted and preloaded
* @default 10
*/
maxPreloadActions: number;
/**
* The audio bus tree, declared by the host at boot
*
* A bus is a gain node every sound routed to it passes through, and buses nest, so a bus's
* gain cascades onto everything beneath it. A bus's `volume` here is the **author's mix
* position**, not the player's slider.
*
* `bgm`, `sound` and `voice` are always present whether or not they appear here.
* Read once, when the audio subsystem starts.
* @default []
* @example
* ```ts
* new Game({
* audioBuses: [
* {id: "cast", parentId: "voice"},
* {id: "alice", parentId: "cast", volume: 0.8},
* ],
* });
* ```
*/
audioBuses: AudioBusDeclaration[];
/**
* Src of the cursor image, if null, the game will show the default cursor
* @default null
*/
cursor: string | null;
/**
* Cursor width in pixels
* @default 30
*/
cursorWidth: number;
/**
* Cursor height in pixels
* @default 30
*/
cursorHeight: number;
/**
* Show overflowed content on player components
* @default false
*/
showOverflow: boolean;
/**
* Max history size for the page router
* @default 10
*/
maxRouterHistory: number;
/**
* Quality of the screenshot, between 0 and 1
* @default 1
*/
screenshotQuality: number;
/**
* If true, the game will scale the dialog to fit the screen
*
* Text will look smaller when this is enabled
* @default true
*/
useAspectScale: boolean;
/**
* The delay in milliseconds before the game automatically shows the next sentence
*
* Counted from the end of the line: the text has finished typing AND the line's voice, if any,
* has finished playing. A voiced line therefore waits out its clip and then this delay.
*
* Only works when the player preference "autoForward" is enabled
* @default 3000
*/
autoForwardDelay: number;
/**
* The default pause duration in milliseconds when auto-forward is enabled
*
* When auto-forward is enabled, any Pause without a custom duration will use this value
* @default 1000
*/
autoForwardDefaultPause: number;
/**
* If true, when you press [GameConfig.player.skipKey], the game will skip the image transform
* @default true
*/
allowSkipImageTransform: boolean;
/**
* If true, when you press [GameConfig.player.skipKey], the game will skip the image transition
* @default true
*/
allowSkipImageTransition: boolean;
/**
* If true, when you press [GameConfig.player.skipKey], the game will skip the background transform
* @default true
*/
allowSkipBackgroundTransform: boolean;
/**
* If true, when you press [GameConfig.player.skipKey], the game will skip the background transition
* @default false
*/
allowSkipBackgroundTransition: boolean;
/**
* If true, when you press [GameConfig.player.skipKey], the game will skip the text transform
* @default true
*/
allowSkipTextTransform: boolean;
/**
* If true, when you press [GameConfig.player.skipKey], the game will skip the text transition
* @default true
*/
allowSkipTextTransition: boolean;
/**
* If true, the animation will propagate to the children
*
* This behavior is controlled by [motion](https://motion.dev): `When true, exit animations will be propagated to nested AnimatePresence components.`
* @default false
*/
animationPropagate: boolean;
/**
* Base width of the dialog in pixels
*
* For 16/9, the recommended value is 1920
* @default 1920
*/
dialogWidth: number;
/**
* Base height of the dialog in pixels
*
* For 16/9, the recommended value is 1080 * 0.2 (20% of the screen height)
* @default 1080 * 0.2
*/
dialogHeight: number;
/**
* If true, when you press [GameConfig.player.skipKey], the game will skip the text transform
* @default true
*/
allowSkipLayersTransform: boolean;
/**
* If true, when you press [GameConfig.player.skipKey], the game will skip the video transform
*
* This will only skip the "play" action
*
* @default false
*/
allowSkipVideo: boolean;
/**
* The component to use for the notification
* @default DefaultNotification
*/
notification: NotificationComponent;
/**
* The component to use for the menu
* @default DefaultMenu
*/
menu: MenuComponent;
/**
* The component to use for the say
* @default DefaultSay
*/
dialog: SayComponent;
/**
* The function to call when an error occurs
* @default () => {}
*/
onError: (error: Error) => void;
app: {
debug: boolean;
/**
* Log level for the logger
* Set to true to enable all logs
*/
logger: {
log: boolean;
info: boolean;
warn: boolean;
error: boolean;
debug: boolean;
trace: boolean;
verbose: boolean;
} | boolean;
/**
* If true, the game will show the inspector when you hover over the element
*/
inspector: boolean;
/**
* The config of {@link GameStateGuard}
*/
guard: GuardConfig;
};
/**
* Override the default stage
* @default null
*/
stage: React.ReactNode | null;
/**
* The maximum number of times a stack model can loop
* @default 1000
*/
maxStackModelLoop: number;
/**
* The maximum number of actions to store in the action history
* @default 100
*/
maxActionHistory: number;
};