The interfaz service
Reference for the interfaz service. What each player sees on top of the game: HUD, messages, timers, scoreboard, menus and labels in the world.
DescribesFormato 1, API 1 For those who write code This page is generated from the SDK sources.
On this page
- Functions and properties of interfaz
- interfaz.t
- interfaz.hud
- interfaz.cronometro
- interfaz.mensaje
- interfaz.marcador
- interfaz.menu
- interfaz.cerrarMenu
- interfaz.alElegir
- interfaz.rotulo
- interfaz.flotante
- interfaz.marcadorDePuntos
- interfaz.barraRapida
- interfaz.marcarBloque
- Cronometro
- cronometro.iniciar
- cronometro.detener
- cronometro.reiniciar
- cronometro.sumar
- cronometro.quitar
- Texto
- Behavior notes
- Complete examples
- interfaz: HUD, messages and timer
- interfaz: menu
- interfaz: scoreboard
- interfaz: labels, bars and numbers in the world
- interfaz: unobtrusive messages, a menu with a disabled option, nested texts
- Next
What each player sees on top of the game: HUD, messages, timers, scoreboard, menus and labels in the world.
The types used in the signatures (Vec3, Texto, the selector) are in the API reference.
Functions and properties of interfaz#
interfaz.t#
interfaz.t(clave: string, vars?: Record<string, string | number>): TextoClaveBuilds a translatable text from a key in the manifest's textos.
From docs/EJEMPLOS.md, «mundo: zonas»:
mundo.alSalir('zona-segura', (_zona, j) => interfaz.mensaje(interfaz.t('cuidado'), { para: j, tipo: 'peligro' }));interfaz.hud#
interfaz.hud(id: string, elemento: { texto: Texto; icono?: Icono; lugar?: LugarHud; estilo?: 'normal' | 'destacado' | 'peligro' } | null, para?: Jugador): voidAdds or updates a HUD item. null removes it.
From docs/EJEMPLOS.md, «interfaz: mensajes que no estorban, menú con opción deshabilitada, textos anidados»:
// Textos mas cortos en telefonos verticales.
jugadores.alCambiarPantalla((j) => interfaz.hud('ayuda', { texto: interfaz.t(j.pantalla.vertical ? 'ayudaCorta' : 'ayuda'), lugar: 'abajo-centro' }, j));interfaz.cronometro#
interfaz.cronometro(id: string, opciones?: { lugar?: LugarHud; cuentaRegresiva?: number; alTerminar?: () => void; para?: Jugador }): CronometroA timer in the HUD. The player draws it frame by frame: you do not need to update it.
From docs/EJEMPLOS.md, «interfaz: mensajes que no estorban, menú con opción deshabilitada, textos anidados»:
interfaz.cronometro('reloj', { cuentaRegresiva: 90, formato: 'segundos' });interfaz.mensaje#
interfaz.mensaje(texto: Texto, opciones?: { duracion?: number; tipo?: 'info' | 'exito' | 'peligro'; para?: Jugador }): voidA short message. By default, large and centered. lugar moves it up or down; tamano: 'chico' does not cover the game; cola: true waits for the previous message to finish instead of stacking.
From docs/EJEMPLOS.md, «mundo: zonas»:
mundo.alSalir('zona-segura', (_zona, j) => interfaz.mensaje(interfaz.t('cuidado'), { para: j, tipo: 'peligro' }));interfaz.marcador#
interfaz.marcador(def: { titulo: Texto; filas: { nombre: Texto; valor: Texto | number; destacado?: boolean }[] } | null, para?: Jugador): voidAn on-screen table (standings, laps). null removes it. Without calling this there is no scoreboard.
From docs/EJEMPLOS.md, «interfaz: marcador»:
reloj.cada(0.5, () => {
const filas = jugadores.todos()
.sort((a, b) => b.puntos - a.puntos)
.map((j) => ({ nombre: j.nombre, valor: j.puntos, destacado: !j.esBot }));
interfaz.marcador({ titulo: interfaz.t('posiciones'), filas });
});interfaz.menu#
interfaz.menu(def: { id: string; titulo: Texto; texto?: Texto; opciones: { id: string; texto: Texto }[] }, para?: Jugador): voidOpens a menu of options for one player (or for everyone). The match is not paused.
From docs/EJEMPLOS.md, «interfaz: mensajes que no estorban, menú con opción deshabilitada, textos anidados»:
interfaz.menu({ id: 'tienda', titulo: interfaz.t('tienda'), opciones: [
{ id: 'botas', texto: interfaz.t('botas') },
{ id: 'alas', texto: interfaz.t('alas'), deshabilitada: true }
] });interfaz.cerrarMenu#
interfaz.cerrarMenu(id: string, para?: Jugador): voidCloses the menu with that id, for one player or for everyone.
From games/defensa-del-faro/scripts/principal.ts:
interfaz.cerrarMenu('inicio');interfaz.alElegir#
interfaz.alElegir(fn: (menu: string, opcion: string, jugador: Jugador) => void): voidA player picked an option. The menu has already closed.
From docs/EJEMPLOS.md, «interfaz: menú»:
interfaz.alElegir((menu, opcion, j) => {
if (menu !== 'camino') return;
j.teletransportar(opcion === 'corto' ? 'inicio-corto' : 'inicio-largo');
j.congelado = false;
});interfaz.rotulo#
interfaz.rotulo(id: string, def: { en: Vec3 | Pieza | Actor | Jugador; texto?: Texto; barra?: number; color?: string; altura?: number; estilo?; alcance?: number } | null, para?: Jugador): voidAdds, updates or (with null) removes a label in the world: text and a bar over a piece, an actor, a player or a point.
From docs/EJEMPLOS.md, «interfaz: rótulos, barras y números en el mundo»:
const pintar = () => interfaz.rotulo('vida-torre', { en: torre, texto: interfaz.t('torre'), barra: (torre.datos.vida as number) / 10, color: 'coral', altura: 1 });interfaz.flotante#
interfaz.flotante(texto: Texto, en: Vec3 | Pieza | Actor | Jugador, opciones?: { tipo?; duracion?: number; para?: Jugador }): voidText that pops out of a point in the world, rises and fades ("+10", "-3").
From docs/EJEMPLOS.md, «interfaz: rótulos, barras y números en el mundo»:
mundo.alTocar('torre', (_torre, j) => {
torre.datos.vida = (torre.datos.vida as number) - 1;
interfaz.flotante('-1', torre, { tipo: 'peligro', para: j });
if ((torre.datos.vida as number) <= 0) interfaz.rotulo('vida-torre', null);
else pintar();
});interfaz.marcadorDePuntos#
interfaz.marcadorDePuntos(def: { titulo: Texto } | null): voidAn automatic scoreboard with each player's puntos counter, sorted. null removes it.
From docs/EJEMPLOS.md, «interfaz: mensajes que no estorban, menú con opción deshabilitada, textos anidados»:
interfaz.marcadorDePuntos({ titulo: interfaz.t('puntos') });interfaz.barraRapida#
interfaz.barraRapida(def: { ranuras: { color?: string; icono?: Icono; texto?: Texto; cantidad?: number }[] } | null, para?: Jugador): voidHotbar: a row of up to 9 slots at the bottom center. The selected one is jugador.ranura. On touch screens each slot can be tapped. With null it is removed.
From games/valle-abierto/scripts/comun.ts:
interfaz.barraRapida({ ranuras }, j);interfaz.marcarBloque#
interfaz.marcarBloque(posicion: Vec3 | null, opciones?: { avance?: number; color?: string }, para?: Jugador): voidMarks a terrain block with an outline (the block pointed at). avance from 0 to 1 shows how much is left to break it. With null it is removed. Each player has their own mark.
From games/valle-abierto/scripts/principal.ts:
interfaz.marcarBloque(a.posicion, { avance, color }, j);Cronometro#
A timer in the HUD: what interfaz.cronometro returns.
| Property | Type | Description |
|---|---|---|
cronometro.valor | number | Read-only. Seconds elapsed (or remaining, for a countdown). |
cronometro.corriendo | boolean | Read-only. true while it is running. |
cronometro.iniciar#
cronometro.iniciar(): voidStarts it.
From docs/EJEMPLOS.md, «interfaz: HUD, mensajes y cronómetro»:
juego.alIniciar(() => {
const crono = interfaz.cronometro('tiempo', {
cuentaRegresiva: 60,
alTerminar: () => juego.terminar({ resultado: 'derrota' })
});
crono.iniciar();
jugadores.alEntrar((j) => {
interfaz.hud('puntos', { icono: 'estrella', texto: interfaz.t('puntos', { n: 0 }), lugar: 'arriba-izquierda' }, j);
});
interfaz.mensaje(interfaz.t('objetivo'), { duracion: 3 });
});cronometro.detener#
cronometro.detener(): voidStops it.
From games/circuito-luz-verde/scripts/principal.ts:
let crono: Cronometro;
// ...
crono.detener();cronometro.reiniciar#
cronometro.reiniciar(): voidResets it to 0 (or to the countdown total) and stops it.
cronometro.sumar#
cronometro.sumar(segundos: number): voidAdds seconds (a penalty) or subtracts them with a negative number.
From games/isla-taller/scripts/principal.ts:
let crono: Cronometro;
// ...
crono.sumar(-AJUSTES.bono);cronometro.quitar#
cronometro.quitar(): voidRemoves it from the HUD.
From games/defensa-del-faro/scripts/principal.ts:
let crono: Cronometro | null = null;
// ...
crono?.quitar();Texto#
A Texto is interfaz.t('clave', { n: 3 }) (recommended: each player translates it), { es, en } or a plain string (only for numbers and proper names). interfaz.t returns an object, not a string: do not concatenate it; put the variables in the template ("monedas": "{n} de {total}").
type Texto = string | { es: string; en: string } | TextoClave;
interface TextoClave {
clave: string;
vars?: Record<string, string | number | TextoClave | { es: string; en: string }>;
}Behavior notes#
- Icons:
moneda,reloj,corazon,estrella,bandera,llave,rayo,jugador,escudo,espada,martillo,casa,gota,hoja,fuego,engranaje,diana,diamante,calavera,flecha,caja,pregunta,luz,ola. - Places:
arriba-izquierda,arriba-centro,arriba-derecha,abajo-izquierda,abajo-centro,abajo-derecha. - The player draws the timer frame by frame: you do not need to update it.
- A menu does not pause the match. If you want nobody to move, freeze the players. An option with
deshabilitada: trueis shown but cannot be chosen. The menu scrolls if it does not fit. interfaz.mensajeacceptslugar('centro','arriba','abajo'),tamano('chico','normal','grande') andcola: true(waits for the previous message to finish instead of stacking). A small message at the top does not cover the game.interfaz.cronometroacceptsformato:'centesimas'(1:23.45, the default),'segundos'(1:23) or'entero'(83).cronometro.sumar(n)addsnto the elapsed time: in a countdown,sumar(5)takes 5 seconds off what is left andsumar(-5)gives 5 back.- A variable of
interfaz.tcan be another translatable text:interfaz.t('ganaste', { premio: interfaz.t('copa') }). interfaz.rotuloputs text, a bar (barrafrom 0 to 1), or both, over a piece, an actor, a player or a point in the world; it follows whatever it is attached to. With the sameidit is updated; withnullit is removed.interfaz.flotanteshows a text that pops out of a point, rises and fades ("+10").jugador.puntosis not drawn by itself.interfaz.marcadorDePuntos({ titulo })shows an automatic scoreboard with each player's points; or draw your own withinterfaz.hudorinterfaz.marcador.- The HUD wraps lines on narrow screens, and the scoreboard goes in the top-right column, below the chips, without overlapping them.
- The start screen (cover, difficulty, controls), the pause menu and the end panel are provided by the player: the game does not program them.
Complete examples#
Complete scripts from docs/EJEMPLOS.md. Each one assumes a scene containing what it names, and the text keys (interfaz.t('...')) must exist in textos of juego.json.
interfaz: HUD, messages and timer#
import { interfaz, juego, jugadores } from '@greengames/sdk';
juego.alIniciar(() => {
const crono = interfaz.cronometro('tiempo', {
cuentaRegresiva: 60,
alTerminar: () => juego.terminar({ resultado: 'derrota' })
});
crono.iniciar();
jugadores.alEntrar((j) => {
interfaz.hud('puntos', { icono: 'estrella', texto: interfaz.t('puntos', { n: 0 }), lugar: 'arriba-izquierda' }, j);
});
interfaz.mensaje(interfaz.t('objetivo'), { duracion: 3 });
});interfaz: menu#
import { interfaz, juego, jugadores } from '@greengames/sdk';
juego.alIniciar(() => {
for (const j of jugadores.todos()) j.congelado = true; // un menú no pausa la partida
interfaz.menu({
id: 'camino',
titulo: interfaz.t('elige'),
opciones: [{ id: 'corto', texto: interfaz.t('caminoCorto') }, { id: 'largo', texto: interfaz.t('caminoLargo') }]
});
interfaz.alElegir((menu, opcion, j) => {
if (menu !== 'camino') return;
j.teletransportar(opcion === 'corto' ? 'inicio-corto' : 'inicio-largo');
j.congelado = false;
});
});interfaz: scoreboard#
import { interfaz, juego, jugadores, reloj } from '@greengames/sdk';
juego.alIniciar(() => {
reloj.cada(0.5, () => {
const filas = jugadores.todos()
.sort((a, b) => b.puntos - a.puntos)
.map((j) => ({ nombre: j.nombre, valor: j.puntos, destacado: !j.esBot }));
interfaz.marcador({ titulo: interfaz.t('posiciones'), filas });
});
});interfaz: labels, bars and numbers in the world#
import { interfaz, juego, mundo } from '@greengames/sdk';
juego.alIniciar(() => {
const torre = mundo.pieza('torre');
torre.datos.vida = 10;
const pintar = () => interfaz.rotulo('vida-torre', { en: torre, texto: interfaz.t('torre'), barra: (torre.datos.vida as number) / 10, color: 'coral', altura: 1 });
pintar();
mundo.alTocar('torre', (_torre, j) => {
torre.datos.vida = (torre.datos.vida as number) - 1;
interfaz.flotante('-1', torre, { tipo: 'peligro', para: j });
if ((torre.datos.vida as number) <= 0) interfaz.rotulo('vida-torre', null);
else pintar();
});
});interfaz: unobtrusive messages, a menu with a disabled option, nested texts#
import { interfaz, juego, jugadores } from '@greengames/sdk';
juego.alIniciar(() => {
interfaz.mensaje(interfaz.t('pista'), { lugar: 'arriba', tamano: 'chico', cola: true, duracion: 4 });
interfaz.mensaje(interfaz.t('ganaste', { premio: interfaz.t('copa') }), { tamano: 'grande', tipo: 'exito' });
interfaz.cronometro('reloj', { cuentaRegresiva: 90, formato: 'segundos' });
interfaz.marcadorDePuntos({ titulo: interfaz.t('puntos') });
interfaz.menu({ id: 'tienda', titulo: interfaz.t('tienda'), opciones: [
{ id: 'botas', texto: interfaz.t('botas') },
{ id: 'alas', texto: interfaz.t('alas'), deshabilitada: true }
] });
// Textos mas cortos en telefonos verticales.
jugadores.alCambiarPantalla((j) => interfaz.hud('ayuda', { texto: interfaz.t(j.pantalla.vertical ? 'ayudaCorta' : 'ayuda'), lugar: 'abajo-centro' }, j));
});Next#
- The sonido service
- API reference: the eleven services and the common types.
- Scripts: the rules of a script and how it runs inside the room.