User Interfaces
If you have questions, please ask them in our Discord server and we'll answer them promptly! 😊
Dreamlab allows you to create a UI layer on top of the game window using web technologies. You can use familiar DOM manipulation to create and update your UI.
Creating a UI Layer
UI layers are not interactable by default. This allows the underlying game
canvas to respond to click events correctly.
Set pointer-events
to all
for any elements you wish to be interactable.
import type { InitClient } from '@dreamlab.gg/core/sdk'
export const init: InitClient = async game => {
// ... initialize client
// Create a Shadow DOM root
const root = game.client.ui.create()
// Create a div and append it to the Shadow DOM
const container = document.createElement('div')
container.style.width = '100%'
container.style.height = '100%'
root.append(container)
// ... setup your UI and event listeners
}
Dreamlab UI
Dreamlab UI is a separate package dedicated to making common UI patterns easier. Currently only React is supported.
The package is published on npm as @dreamlab.gg/ui
and is available by default in the Dreamlab scripting runtime.
While Dreamlab UI is a quick way to get started using UI frameworks, you can roll your own manually should you wish.
Dreamlab UI React exposes many hooks that allow you to get references to game state in a react-safe way, such that they trigger
re-renders when their state changes. This requires some setup internally, so it also provides a renderUI
function that takes
care of all the UI setup and state tracking for you.
React Hooks
For a full list of hooks, consult the source.
Hook Signature | Description |
---|---|
useGame(): Game | Returns a reference to the current Game |
usePlayer(): Player | Returns a reference to the player |
useCamera(): Camera | Returns a reference to the camera |
useSpawnableEntities(): readonly SpawnableEntity[] | Returns a list of only spawnable entities |
Styling
CSS Files
You can use CSS files included in your world scripts in order to style your UI. Dreamlab UI provides a simple css
utility
to add a CSS file to the shadow DOM.
See the Scripting page for more information
on using static assets with world://
URLs.
h1 {
font-family: 'Comic Sans MS';
}
import type { InitClient } from '@dreamlab.gg/core/sdk'
import { css } from '@dreamlab.gg/ui'
export const init: InitClient = async game => {
// ... initialize client
const root = game.client.ui.create()
// Add your CSS file to the shadow DOM
css(root, 'world://public/styles.css')
const header = document.createElement('h1')
header.textContent = 'Hello World!'
root.append(header)
// ...
}
CSS-in-JS
You can also use CSS-in-JS libraries to make styling easier when using UI libraries such as React.
Examples
Vanilla JS
<div id="title">Counter</div>
<button id="button" type="button">Click Me</button>
<div>You have clicked <span id="counter">0</span> times.</div>
/* Make the title text slightly larger and bolder */
#title {
font-size: 1.5rem;
font-weight: 500;
}
/* Make the button interactable */
#button {
pointer-events: all;
}
import type { InitClient } from '@dreamlab.gg/core/sdk'
// Import the HTML and CSS files as raw strings
import html from './ui.html'
import css from './ui.css'
export const init: InitClient = async game => {
// Create UI layer
const ui = game.client.ui.create()
// Assign HTML to UI root
ui.innerHTML = html
// Create style tag from CSS and append to UI
const styles = document.createElement('style')
styles.appendChild(document.createTextNode(css))
ui.appendChild(styles)
// Get references to elements by ID
const button = ui.querySelector<HTMLButtonElement>('#button')
const counter = ui.querySelector<HTMLSpanElement>('#counter')
// Guard against elements being `null`
if (!button) throw new Error('cannot find element with id: button')
if (!counter) throw new Error('cannot find element with id: counter')
// Increment count on click
let count = 0
button.onclick = () => {
count += 1
counter.innerText = count.toString()
}
}
React
import type { InitClient } from '@dreamlab.gg/core/sdk'
import { renderUI } from '@dreamlab.gg/ui/react'
const Root = () => {
return <div>Hello React!</div>
}
export const init: InitClient = async game => {
// ... initialize client
// Render React using Dreamlab UI
renderUI(game, <Root />)
}
React with Styled Components
Using CSS-in-JS libraries can drastically reduce complexity introduced by styling your UI.
Native UI
It is also possible to create UI using Pixi.js natively, although this is not recommended due to the complexity with drawing using Pixi.js and managing inputs.
See the dedicated page on Graphics for more info.