Русский · English · Español · 中文 · Português
«Espacio ahora» — API de agente
Esta página es para agentes de IA (y sus humanos). Explica cómo un agente se conecta a una página «Espacio ahora» en vivo (known.html) en el navegador de una persona y qué puede hacer allí: todo lo que puede hacer la interfaz — abrir cualquier objeto, mover la cámara, avanzar el tiempo, cambiar capas y filtros, modo astronauta, buscar eclipses y desfiles de planetas, contar una historia con voz y subtítulos, mostrar sus propias imágenes, grabar vídeo, leer errores. El renderizado ocurre en el navegador de la persona (WebGL en su GPU); el agente envía comandos y recibe respuestas y capturas de pantalla.
1. Emparejamiento
- La persona abre el sitio y pulsa el botón redondo 🤖 (abajo a la derecha, encima del astronauta): se abre la barra del agente; «Encender el agente» muestra un código (20 caracteres, p. ej.
r4fxjbjsxdy6ex3pf4hd). El código es el pase: quien lo tiene controla esta pestaña. 🤖 solo oculta/muestra la barra, la conexión se mantiene; «Desconectar» en la barra la apaga. La barra siempre tiene 📂 (abrir un archivo de historia o guardar la mostrada — también sin agente) y «MCP ↗» (esta página). - La persona da el código al agente. El agente llama a
connectcon él. - Conexión permanente (opcional): en la página — 📌 «Recordar» en la barra del agente (el código se queda en este navegador, el sitio se conecta solo cada vez que se abre); el agente —
connectconsave: true(código en~/.orbit-agent.json, MCP se conecta al iniciar). Después, basta con abrir el sitio. Para olvidar: desactivar 📌 y llamar aforget. - «Desconectar» en la página (o la salida del agente) termina la sesión; entonces la página devuelve las capas y la interfaz a como estaban
antes del agente, detiene la música, la voz, los subtítulos, las imágenes y los guiones, y elimina los sitios de aterrizaje (
sites), los dibujos y las marcas (draw,mark,flybys), las ventanas multimedia y los cuerpos propios (spawn) — independientemente deonstop. La cámara, el tiempo y la selección también se restauran (por defecto;onstop {restore: false}— conservar lo que mostró el agente). Excepción:play/story runcondetach: true— la presentación se reproduce hasta el final y luego se revierte.
El sonido (voz, música) solo empieza después de que la persona haya hecho clic en la página al menos una vez — regla del navegador. La voz está desactivada por defecto: la persona la activa con 🔊 en la barra del agente (se recuerda); los subtítulos siempre se muestran.
Lista de comprobación de la presentación — hazlo siempre
[
{"cmd":"onstop","args":{"restore":true}}, // primer paso: al terminar, con Esc o ✕ todo vuelve
{"cmd":"reset"},
{"cmd":"view","args":{"on":["oplanets"]}}, // solo las capas necesarias: satélites, naves, órbitas, constelaciones apagados
{"cmd":"hideUi","args":{"on":true,"labels":false}},
{"cmd":"time","args":{"at":"<moment>","rate":0}}, // fija tú el tiempo; rate 0 — la iluminación no se desplazará
… vuelo (fly) …
… la presentación …
]
- No confíes en los valores por defecto: fija capas, tiempo, cámara e interfaz de forma explícita.
- Una vista fijada con
view(o el campoonde una historia) la conservashow(keepView: false— las capas del evento).fly,camera,sites,timeno tocan las capas;galaxy,sceneyambientfijan su propia vista — llama de nuevo aviewdespués de ellos si hace falta. - Tras la presentación la escena debe quedar como antes:
onstop {restore: true}más eliminar tus propias cosas —sites {on: false},flybys {on: false},draw {clear: true},image {clear: true},media {close: true}. Cuando el agente se va, se eliminan igualmente. - Comprueba el encuadre con
screenshotantes de decirle a la persona «mira». - El
captionestá abajo a la izquierda: manténtitlecorto, pon el texto largo ensubytext. - Un paso fallido en
playva alogs(nivel error), aplaysin argumentos (lastError: {step, cmd, error}) y al reproductor como «⚠ paso N». Un comando desconocido en los pasos es un error inmediato, antes del inicio.
2. Transporte
Ambos lados se conectan a una sala de retransmisión en el mismo sitio: wss://<site>/agent/<code>?r=agent (la página usa
?r=page). La sala reenvía mensajes entre los dos; no se almacena nada. Mensajes JSON:
agent → page { "id": 1, "cmd": "go", "args": { "search": "?o=Mars" } }
page → agent { "id": 1, "ok": true, "result": … } | { "id": 1, "ok": false, "error": "…" }
room → both { "sys": "peer", "on": true|false } (el otro lado se unió / salió)
keepalive envía { "sys": "ping" } cada 30 s, la sala responde { "sys": "pong" }
Una conexión por rol (un agente nuevo con el mismo código reemplaza al anterior, código de cierre 4000 — no te reconectes entonces).
Mensajes de hasta 4 MB. Sitios: https://space.bl2.ru, https://space.bl2.net (el mismo sitio, ru/en por defecto).
3. Servidor MCP
Servidor MCP listo para usar (stdio): scripts/agent-mcp.mjs en el repositorio orbit-proto (Node ≥ 20, dependencia ws).
Cada comando de abajo es una herramienta del mismo nombre (hide_ui → comando de página hideUi), más connect,
disconnect, help (esta página como texto; lang: es). Archivos: image toma path, record guarda
en path, screenshot devuelve una imagen.
{ "mcpServers": { "orbit-space": { "command": "node", "args": ["scripts/agent-mcp.mjs"] } } }
Env: AGENT_SITE — sitio por defecto, AGENT_CODE — conectar al inicio.
Conexión sin el servidor MCP (agentes en la nube)
- Muchos agentes se ejecutan en sandboxes en la nube cuya red saliente está limitada a una lista de permitidos, por lo que
wss://space.bl2.rupuede ser inalcanzable. Solución: abre el WebSocket desde cualquier pestaña del navegador enspace.bl2.ru(esta página de ayuda, por ejemplo) y envía los comandos desde allí. Comprobación de conexión:{"sys":"ping"}→{"sys":"pong"}. - La salida del agente =
playse detiene y la escena se revierte. Un agente con sesiones cortas (las herramientas de navegador permiten ~45 s por llamada) envía la presentación condetach: true—play {steps, detach: true}ostory {action: 'run', story, detach: true}— y vuelve de inmediato: la página reproduce la presentación por sí misma y se revierte (cononstop) al terminar. Sindetachmantén el socket abierto hasta que termine el guion. - Da a cada comando su propio tiempo de espera (digamos 8 s): de lo contrario un comando sin respuesta cuelga toda la llamada.
// «iniciar y volver» — desde la consola de una pestaña en space.bl2.ru (o Node ≥ 22)
const code = '<code>', ws = new WebSocket(`wss://space.bl2.ru/agent/${code}?r=agent`);
let id = 0; const wait = new Map();
const cmd = (name, args = {}, ms = 8000) => new Promise((res, rej) => {
const i = ++id, t = setTimeout(() => (wait.delete(i), rej(new Error('timeout ' + name))), ms);
wait.set(i, (m) => (clearTimeout(t), m.ok ? res(m.result) : rej(new Error(m.error))));
ws.send(JSON.stringify({ id: i, cmd: name, args }));
});
ws.onmessage = (e) => { const m = JSON.parse(e.data); if (!m.sys) wait.get(m.id)?.(m), wait.delete(m.id); };
ws.onopen = async () => {
await cmd('onstop', { restore: true });
await cmd('play', { detach: true, onError: 'skip', steps: [
{ cmd: 'reset' },
{ cmd: 'view', args: { on: ['oplanets'] } },
{ cmd: 'hideUi', args: { on: true, labels: false } },
{ cmd: 'fly', args: { name: 'Saturn', size: 0.5, lit: true }, wait: 6500 },
{ cmd: 'caption', args: { title: 'Saturn', sub: '1.4 billion km from the Sun' }, wait: 8000 },
] });
ws.close(); // la presentación continúa sola y luego lo devuelve todo
};
4. Comandos
Observación y estado
| cmd | args | qué hace |
|---|---|---|
| state | tiempo, velocidad, objeto seleccionado, centro de la vista, cámara (yaw, pitch, dist km, fov), estrella cercana, claves de las capas visibles, tamaño del lienzo en px | |
| screenshot | width, quality, full | JPEG de la escena 3D. full: true — toda la pestaña con la interfaz (la persona permite la captura de pestaña una vez con «📷» en la barra del agente) |
| body | name | para el encuadre: radio km, tipo, padre, lunas, ángulos de cámara, sunYaw/sunPitch (dirección de cámara desde la que el cuerpo está totalmente iluminado), fov, distForSize {0.25, 0.5, 0.66, 0.8 → km}: distancia a la que el disco llena esa proporción de la altura de pantalla (= radio / tan(fov/2) / k) |
| where | name, at | posición en un instante: km y UA desde el Sol y la Tierra, AR/Dec desde la Tierra (J2000) |
| logs | level, last, clear | errores/advertencias/info de la consola de la página (búfer circular de 300) |
| snapshot | estado completo (tiempo, velocidad, cámara, centro, selección, todas las casillas de capas, interfaz oculta, enlace del astronauta) — guárdalo para reproducir un error | |
| restore | state | volver a una instantánea |
Vista, cámara, tiempo, capas
| cmd | args | qué hace |
|---|---|---|
| search | q, limit | buscar en la base de objetos como el campo de búsqueda: cuerpos, lunas, naves espaciales, nebulosas y galaxias (cuando su capa está activa), satélites terrestres (nombre o NORAD), asteroides (nombre o número; el catálogo se carga mediante la fila load-asteroids). Devuelve filas con n |
| open | n | abrir un resultado de búsqueda: selección, ficha, vuelo — como al hacer clic en la fila |
| go | search | abrir una vista como un enlace para compartir: ?o= cuerpo (Mars, Марс, ISS…), ?a= asteroide (número o nombre), ?s= satélite NORAD, ?g= galaxia, ?n= nebulosa, ?st= estrella de constelación; extras d= cámara km, v=yaw,pitch, t= hora ISO |
| fly | name, size, lit, face, seconds | vuelo suave a un cuerpo (como un clic en el árbol). size — proporción de la altura de pantalla para el cuerpo (0.66 — dos tercios), lit: true — desde el lado iluminado; el encuadre tarda ~2,5 s más después del vuelo (~6 s en total, usa wait ≥ 6500). face: "spot" — Júpiter: el tiempo retrocede hasta que la Gran Mancha Roja está en el lado diurno |
| camera | yaw, pitch, dist, ms | cámara alrededor del centro de la vista (rad, km). ms > 0 — moverse suavemente durante ms. Ejemplo «llenar 2/3 de la pantalla, lado iluminado»: body → camera {yaw: sunYaw+0.4, pitch: sunPitch, dist: distForSize[0.66], ms: 3000} |
| time | at, rate, live, from, to | from, to, ms, ease — avance suave de una fecha a otra; at — segundos Unix o instante ISO (a. C.: -000500-01-01), velocidad (1 real, 3600 = 1 h/s, negativa = hacia atrás, 0 pausa), live: true |
| view | on, set, orbits | vista — claves estándar para cada interruptor. Sin args — lista {key, on}; on: [...] — apaga todo y enciende solo lo indicado; set: {key: true|false} — cambia solo esas; orbits: false — todas las líneas de órbita a la vez. Claves (cada grupo tiene también <key>:orbits — sus líneas de órbita): oplanets — Sol, planetas y lunas; odwarfs — planetas enanos y los mayores asteroides; ohelio — heliopausa; oshock — choque de terminación; osandbox — cuerpos propios (spawn); oknown-small — pequeños conocidos (Apofis, Bennu…); ocomets — cometas; ointerstellar — objetos interestelares (1I, 2I, 3I); okuiper — cinturón de Kuiper; ooort — nube de Oort; a0…a9 — asteroides por tamaño (a0 — más de 100 km); ocraft, ocraft-orbit, ocraft-l — naves en vuelo, en órbita alrededor de cuerpos, en puntos de Lagrange; s0…s30 — grupos de satélites terrestres, sats — todos a la vez; ogalaxy — modelo de la Vía Láctea; ouniverse — galaxias; stars — estrellas de constelaciones con nombre; conlines — líneas de las figuras de constelaciones (con stars; no aparece en view {on} — sin líneas); galmarks — etiquetas del centro galáctico y del ápex; galsun — «Sol — usted está aquí»; scenelabels — etiquetas solo de lo que necesita la escena (labels {only}). Una única trayectoria interestelar: apaga ointerstellar:orbits, select {name: '3I/ATLAS'} — su trayectoria brillante. También: earth:ph|cities|seas|mountains|volcanoes, weather, aurora (aurora), sw (clima espacial), sk:0…6, sk:neb. Las historias y diapositivas aceptan un campo on (se aplica antes de los pasos): indica solo lo necesario — las capas nuevas activadas por defecto no aparecerán en historias antiguas |
| layers | todos los grupos de capas: key, name, visible, orbits, count | |
| layer | key, visible, orbits | cambiar una capa. Claves: oplanets, odwarfs, ocomets, ocraft*, ogalaxy, ouniverse, a0…a9 asteroides por tamaño, s0… grupos de satélites… |
| galaxy | far | vista de la Vía Láctea (far — con otras galaxias). Para escenas: dist (0 — modelo en el Sol, > 0 — alejarse), pitch, center: true — órbita alrededor del centro galáctico, off: true; tiempo galáctico — galtime {rate} (años/s) |
| galaxies | count, dwell | sobrevolar N galaxias famosas por distancia, dwell segundos cada una |
| clear | deseleccionar, cerrar la ficha |
Eventos (calculados por la página, sin necesidad de fórmulas)
| cmd | args | qué hace |
|---|---|---|
| find | kind, from, to, total, count, min | lunar (total: true — «luna de sangre»), solar, parade (min planetas 3…7) desde cualquier fecha; devuelve el instante central, total?, lat/lon/región donde es visible; lunar — contact (contacto con la umbra) |
| show | kind, at, keepView | mostrar un evento como «📅 Eventos»: tiempo — media hora antes del máximo, velocidad ×100 (fija time {rate: 0} o la tuya), selección borrada, centro de la vista y cámara en la Tierra (solar: sobre el punto de la sombra) o la Luna (lunar); un desfile — vista en primera persona desde la Tierra, solo planetas. Las capas fijadas con view se mantienen (keepView: false — las del evento). Después: hideUi, camera si hace falta |
Interfaz completa
| cmd | args | qué hace |
|---|---|---|
| ui | text, within | cada botón, casilla, control deslizante, campo, fila de lista/árbol visible con ref, texto, id, atributos data, estado. Filtra por texto o área CSS |
| click | ref | selector | pulsarlo |
| set | ref | selector, value | casilla true/false, control deslizante, campo, select |
| key | code, ms, shift, ctrl | pulsación de tecla (KeyW… mantén ms para volar, Space pausa, KeyH oculta paneles, Escape…) |
| pointer | action, x, y, to, dy | ratón sobre la escena 3D: click (seleccionar), dblclick (volar hasta), move (pasar por encima), drag (rotar) hasta [x,y], wheel (dy zoom) |
| hideUi | on, labels | ocultar todo: paneles, botones de las esquinas, la barra del agente (labels: false — también las etiquetas de cuerpos); solo quedan la escena, el subtítulo, las imágenes, las ventanas multimedia, las marcas (mark) y los dibujos del agente. on: false — volver |
| astro | action, name | astronauta: enter (donde está la cámara), goto name (volar allí, orbitar), land (pararse en el suelo), exit, link, state. Caminar y mirar — key/pointer |
| eval | code | solo servidor de desarrollo (npm run dev): ejecuta una expresión JS en la página; window.__known contiene el estado. No disponible en el sitio público |
Contar una historia
| cmd | args | qué hace |
|---|---|---|
| caption | title, sub, text, seconds | subtítulo abajo a la izquierda como el salvapantallas (title vacío — ocultar) |
| say | text, title, sub, audio, keep, caption | mostrar el texto como subtítulo; audio — una locución mp3 (enlace o nombre de archivo en el ordenador; sin voz del navegador — crea el mp3 de antemano, p. ej. edge-tts); 🔇 — silencioso |
| music | on, theme, volume | música de fondo generada en el navegador: tema 0 «Nebulosa», 1 «Profundidad», 2 «Cristales», null — rotar |
| image | id, src | path, at, x, y, dx, dy, w, label, remove, clear | tu imagen sobre la escena: unida a un cuerpo (lo sigue) o en un punto de la pantalla |
| play | steps | stop | pause | seek | step | un guion completo reproducido por la página: [{cmd, args, wait}], wait = ms o "speech". Como un reproductor: pause, seek: n — saltar al paso n (los pasos anteriores se ejecutan de inmediato, sin esperas ni voz), step: ±1. La persona obtiene un reproductor abajo: ⏮ ⏪ ▶/⏸ ⏹ ⏩ ⏭, «diapositiva · paso», 💾 guardar en el sitio (contraseña), ⬇ descargar, 🗑 eliminar, ✕. Se detiene al desconectar — excepto con detach: true (se reproduce hasta el final y luego se revierte). onError: 'skip' (por defecto — continuar) | 'stop'; un paso fallido va a logs, a play sin argumentos (lastError) y al reproductor. Una presentación pasa sola a la siguiente diapositiva; ✕ o Esc — salir (la interfaz vuelve) |
| deck | slides, start, go, close | presentación: [{title, steps}]; la persona obtiene «◀ n/N ▶» abajo (y RePág/AvPág), al moverse se reproducen los pasos de esa diapositiva. Permanece visible con hideUi |
| buttons | items | tus propios botones abajo: [{label, title, steps}], un clic reproduce los pasos; [] los elimina |
| story | action, story, id, password, name | una historia = lo que compuso el agente (plan de vuelo, narración, visualización — p. ej. para NASA Space Apps): {title, summary, lang, slides:[{title, steps}] | steps}. run — mostrar; publish — guardar en el sitio con una contraseña de edición (password; sin ella — la página se la pide a la persona) → enlace known.html?story=<uuid>, cualquiera la ve sin agente (con «◀ n/N ▶»); hasta 256 KB, se conserva 30 días tras la última apertura; update — editar (id + la misma contraseña); delete — eliminar del sitio (id + la misma contraseña); download — un archivo para la persona (cualquier tamaño); open — la persona elige un archivo (o suelta un .json en la página; menú «📂» en la barra del agente); load — por id |
| steps | dónde estamos en una historia o presentación: diapositiva y lista de diapositivas, paso y lista de pasos (n, label), playing, paused. Saltar — play {seek: n} / {step: ±1}, deck {go: n}. La persona tiene ☰ en el reproductor — la lista de diapositivas y pasos, clic para saltar | |
| scene | code | una escena del modo ambiente dentro de una historia — su vuelo de cámara, subtítulo y tiempo (~20–30 s, espera hasta el final). Códigos — scenes: body:Сатурн, event:<id>, mission:…, astro:…, lapse:…, galaxy, pullback. El modo ambiente («∞») es el mismo generador de escenas en el reproductor común: ⏮ ▶/⏸ ⏭, ☰ lo reproducido y todas las escenas, 💾/⬇ — lo reproducido como una historia de pasos de escena |
| scenes | todas las escenas del modo ambiente por sección, con códigos | |
| record | action, fps, mbps / path | vídeo de la escena: start, stop (el MCP guarda WebM en path) |
Un único punto de entrada: WS, MCP, consola, historia
Los comandos y el lenguaje son los mismos venga de donde venga: WebSocket desde cualquier lenguaje, MCP, la consola de la página (el botón >_ en la barra del agente) o una historia. Escribe un guion completo y dáselo a story, o llama a los comandos uno por uno. Novedad: exec {steps} — ejecutar pasos del lenguaje ahora (las variables persisten entre llamadas), expr {e} — evaluar una expresión, js {code, timeout} — JavaScript en un sandbox (iframe aislado + Web Worker: sin DOM, cookies ni red; dentro — await cmd(name, args), await expr('…'), log(), sleep(), return).
Consola: fly Mars size=0.6 (un comando, la primera palabra es el nombre), un comando JSON, pasos {…} / […], una expresión = …, código js ….
Guion base — Node.js:
// node agent.mjs <код> (Node ≥ 22 — WebSocket integrado)
const code = process.argv[2], ws = new WebSocket(`wss://space.bl2.ru/agent/${code}?r=agent`);
let id = 0; const wait = new Map();
const cmd = (name, args = {}) => new Promise((res, rej) => {
const i = ++id; wait.set(i, { res, rej }); ws.send(JSON.stringify({ id: i, cmd: name, args }));
});
ws.onmessage = (e) => {
const m = JSON.parse(e.data);
if (m.sys) return; // peer / pong
const w = wait.get(m.id); wait.delete(m.id);
m.ok ? w.res(m.result) : w.rej(new Error(m.error));
};
setInterval(() => ws.send('{"sys":"ping"}'), 30000);
ws.onopen = async () => {
await cmd('fly', { name: 'Mars', size: 0.6, lit: true });
console.log(await cmd('expr', { e: "round(au(get('Mars','sun')),3)" }));
await cmd('exec', { steps: [{ wait: "dist('camera','Mars') < 1e5 km" }, { cmd: 'caption', args: { title: 'Mars' } }] });
process.exit(0);
};
Python:
# python agent.py <код> (pip install websockets)
import asyncio, json, sys, websockets
async def main(code):
async with websockets.connect(f"wss://space.bl2.ru/agent/{code}?r=agent") as ws:
n = 0
async def cmd(name, **args):
nonlocal n; n += 1
await ws.send(json.dumps({"id": n, "cmd": name, "args": args}))
while True:
m = json.loads(await ws.recv())
if m.get("id") == n:
if not m["ok"]: raise RuntimeError(m["error"])
return m["result"]
await cmd("fly", name="Saturn", size=0.6, lit=True)
print(await cmd("expr", e="get('Saturn','moons')"))
asyncio.run(main(sys.argv[1]))
Lenguaje de guiones v2
Versiones: una historia sin v (o v: 1) — pasos y diapositivas como arriba; v: 2 — un lenguaje con condiciones. Una nueva versión del manejador nunca cambia las antiguas.
{ "v": 2, "title": "…", "on": ["oplanets"], "vars": { "n": 0 }, "steps": [
{ "cmd": "fly", "args": { "name": "Mars", "size": 0.5, "lit": true } },
{ "wait": "dist('camera', 'Mars') < 50000 km", "timeout": 20 },
{ "set": { "n": "n + 1" } },
{ "if": "visible('Mars')", "then": [ { "cmd": "caption", "args": { "title": "Mars", "sub": "{round(au(dist('camera','Sun')),3)} AU from the Sun" } } ] },
{ "repeat": 2, "do": [ { "wait": 1 } ] }
] }
Pasos: {cmd, args, wait} (wait — ms o una expresión), {wait: expression | seconds, timeout}, {if, then, else}, {repeat: n | expression, do}, {set: {name: expression}}, {on: [...]}. Expresiones — sin eval: números con unidades km au ly m, cadenas '…', variables, + - * / %, < > <= >= == !=, && || !; funciones dist(a, b) ('camera' o un cuerpo, km), visible(body), elapsed(), time(), camdist(), au(x), ly(x), round(x, d), abs min max. Propiedades al vuelo: get(body | 'camera', 'prop') — un cuerpo tiene name, kind, radius, parent, moons, x y z, sun (km desde el Sol), earth, camera (km desde la cámara), center, visible; la cámara tiene dist, yaw, pitch, fov, x y z, sun, center; sin prop — el objeto completo. El resultado de un comando a una variable: {cmd, args, as: 'r'}, un campo — field(r, 'rows.0.text'), tamaño — count(x). En las cadenas de args — {expression}. Los errores van a logs. Próximamente: disparadores (when/once/every) y un sandbox (cuerpos propios y modelos 3D). Funciones propias: {def: name, params, e} — en expresiones, {def, params, steps} — como un paso {call, args, as}, {local}, {return}; en una historia — funcs. Más funciones: angle(a, b) — grados entre direcciones desde la cámara, edge(a, b) — cuántos grados sobresale a por el limbo de b, sin cos (grados), pow sqrt. wait: true en un comando — hasta que termine. Para escenas: fitdist(r[, margin]) — la distancia desde la que un círculo de radio r km cabe en la pantalla (lado estrecho; un cuerpo también tiene day — periodo de rotación, s); satcount('all' | 'active' | 'debris' | 'rb' | 'dead') — objetos del catálogo alrededor de la Tierra; mstat(craft, 'launch' | 'km' | 'turns' | 'rmin' | 'rnow' | 'flybys') — cifras de una misión según su trayectoria, a fecha de hoy. Las trayectorias de naves y los sobrevuelos vienen de la importación (scripts/fetch-missions.mjs, JPL Horizons, diaria): una nave nueva en la base obtiene sus sobrevuelos y cifras automáticamente; flybys {craft} dibuja los puntos de sobrevuelo en su trayectoria. Multimedia en escenas: media {url | file, title, x, y, w, h, volume, loop, start, id} — una ventana con audio o vídeo: un enlace mp3/vídeo o YouTube; file — un archivo del ordenador de la persona (el sitio no almacena archivos: la persona lo elige en la ventana, luego se reproduce sin conexión); close: true cierra las ventanas. Estado: remember {name} — guardar la cámara, el tiempo, la vista y la interfaz; recall {name} — recuperarlo; onstop {restore: true} (en un archivo de historia — el campo "onstop": "restore") — al terminar, con Esc o ✕ todo vuelve a como estaba antes del inicio. Díselo a la persona: las historias y el salvapantallas se pueden manejar con un mando a distancia — un puntero de presentaciones (PageDown/PageUp, «.» o B — pantalla negra), teclas multimedia de teclados, auriculares y TV boxes (siguiente, anterior, pausa), un gamepad (cruceta ←/→, A — pausa, B — pantalla negra), flechas del teclado, Space, Esc. Enlaces directos: ?ambient — el salvapantallas, ?ambient=<scene code from ☰> — empezando por esa escena (p. ej. ?ambient=landings:Moon:apollo), ?story=<id>&step=N o &slide=N — una historia publicada desde ese punto; el botón 🔗 del reproductor copia un enlace a lo que se está reproduciendo. El comando ambient {play: code} hace lo mismo desde un agente; reset restablece cámara, tiempo y vista antes de una escena.
Cámara y movimiento
| cmd | args | qué hace |
|---|---|---|
| fly | name, ms, ease, size, alt, lat, lon, rel, lit | Vuelo en un solo movimiento directamente al encuadre: size — proporción de la altura de pantalla para el disco, alt — km sobre la superficie, lat/lon — sobre un punto de la superficie, rel: {to, deg, elev} — lado respecto a otro objeto (0° — está detrás de la cámara, 180° — detrás del cuerpo en el encuadre; elev — elevar). Devuelve ms. |
| camera | dist, yaw, pitch, rel, ms, ease, target | Cámara alrededor del centro de la vista; rel como en fly. target: {between: [a, b], k} — mirar a un punto entre cuerpos; {sat: 25544} — orbitar alrededor de un satélite (NORAD); {sat, space: {tilt, spin, from, ms}} — vista desde el espacio (la Tierra detrás del satélite): tilt° desde la vertical, spin °/s, aproximación desde from km hasta dist durante ms; null — volver al cuerpo. |
| media | url | file, kind, title, x, y, w, h, volume, loop, start, id, anchor, dx, dy, header, close, forgetDir | Una ventana con audio o vídeo: un enlace (mp3/vídeo/YouTube) o file — un archivo del ordenador (la persona lo elige). anchor: {sat: NORAD} | {body: name} — la ventana sigue a un objeto (dx, dy — desplazamiento, px); header: false — sin barra de título (por defecto cuando está anclada). Devuelve ms para wait: true. close: true | id; forgetDir: true — olvidar la carpeta de medios. Antes de que empiece una historia — la ventana «Preparando la escena» (archivos, precarga de enlaces). |
| ambient | play | Salvapantallas «∞» desde una escena dada: código como en ☰ (hover|Mars, landings:Moon:apollo, event:eclSun, mission:Parker, satellites…); sin play — la lista de códigos. |
| lang | set | Idioma de la interfaz: sin set — el actual y la lista (ru, en, es, zh, pt); set — cambiarlo. Cambia al instante, sin recargar: el agente sigue conectado. La pantalla de reposo reproduce de nuevo la escena actual en el nuevo idioma; el reproductor, la ficha, el árbol de capas y las ventanas se redibujan. La dirección de la página pasa a ser /<idioma>/ (por ejemplo /es/; el idioma propio del dominio es simplemente /): el idioma lo fija solo la dirección, no hay parámetro ?lang=; el enlace al sitio en un idioma es https://space.bl2.net/<idioma>/ (ruso — https://space.bl2.ru/). |
| reset | — | Antes de una escena: detiene la órbita, la mirada y las rampas de tiempo; Galaxia apagada; se eliminan marcas, puntos de sobrevuelo y ventanas multimedia (las escenas del salvapantallas lo hacen solas). |
| remember / recall | name | Guardar el estado (cámara, tiempo, vista, interfaz) / recuperarlo. |
| onstop | restore | Activado por defecto: al terminar, con Esc, ✕ o la salida del agente, todo vuelve a como estaba antes del primer comando del agente: capas e interruptores de vista, paneles e interfaz oculta, cámara (ángulo, distancia, centro, seguimiento), selección, tiempo y velocidad (o «live»); la música y la voz se detienen. Las cosas propias del agente (sites, draw, mark, flybys, image, media, spawn) siempre se eliminan. restore: false (en un archivo de historia — "onstop": "keep") — conservar la cámara, el tiempo y la selección como los dejó el agente. exec se revierte al terminar solo con un onstop {restore: true} explícito. |
| console | open | Abrir / cerrar la consola >_. |
| sites | body | code, group, ids, light, on | Sitios de aterrizaje: fichas en puntos de la superficie (en la escena). body puede omitirse — el cuerpo sale del grupo (apollo, luna, rovers, new, farside, first, china — Luna; mars, chryse — Marte; venera — Venus) o de ids. Ejemplo: sites {group: 'apollo', light: true} → {lat, lon, alt, at, ids}; luego time {at, rate: 0} y fly {name: 'Moon', lat, lon, alt}. Sin volar a lat/lon la cámara puede mirar la cara oculta — no se ven fichas. light: true — una hora en que los sitios están a la luz del día (respuesta at). |
| flybys | craft, on | Puntos de asistencia gravitatoria e inserción orbital en la trayectoria de una nave (de la trayectoria de la misión). |
| orbit | speed (°/s), turns | ms, pitch, dist, end, blend, ease, stop | Orbitar alrededor del cuerpo. end: {to, deg, elev} — terminar exactamente en ese encuadre (una dirección, sin volver atrás). Si termina con velocidad, sigue por inercia y el siguiente fly toma esa velocidad. |
| look | to, ms, ease, clear | Mirar a un objeto: el ojo se queda (o sigue orbitando), la vista gira suavemente y lo sigue. clear: true — volver al centro. |
| select, shadow, camera target | name; name, by, center, ms, dist; target | Para escenas del salvapantallas: select {name} — resaltar la trayectoria de un cuerpo ('' — borrar); shadow {name, by, center, ms, dist} — cámara en el punto de la sombra del eclipse; camera {target: {between: [a, b], k}, ms} — punto de mira entre cuerpos (orbit gira alrededor), target: null — volver; look {to: 'galcenter'}; fly {frame: {path, from, to, with}, elev, deg} — encuadrar toda la trayectoria de una nave. |
| follow | name, ms, dist, ease | Seguir a otro objeto: traspaso suave manteniendo el encuadre. |
Mostrar un cuerpo pequeño (un cometa, un objeto interestelar — invisible desde decenas de millones de km): follow {name} o fly {name}, luego mark {name, label: true} — un marcador multicolor parpadeante en el cuerpo (visible también con hideUi; también color, speed), select {name} — su trayectoria brillante. Quitar: mark {remove: name} o mark {clear: true}, select {name: ''}; la reversión de onstop y la salida del agente eliminan las marcas por sí solas.
Suavizado ease — como una función de temporización CSS: linear, ease, ease-in, ease-out, ease-in-out, smooth, cubic-bezier(x1,y1,x2,y2) o una fórmula de t (0…1): 1-pow(1-t,2), t*t*t*(t*(6*t-15)+10).
Solapamiento: {cmd, args, then: [steps], before_end: ms | after_begin: ms | when: "condition"} — los pasos anidados se ejecutan junto con el comando. Ejemplo: orbitar la Tierra, girar hacia Ío, volar hasta él:
[ {"cmd": "fly", "args": {"name": "Earth", "size": 0.4, "rel": {"to": "sun", "deg": 0, "elev": 10}, "ms": 3000, "ease": "ease-in-out"}, "wait": true},
{"cmd": "orbit", "args": {"speed": 60, "ms": 6000, "ease": "ease-in"},
"when": "edge('Io','Earth') < 15", "then": [{"cmd": "look", "args": {"to": "Io", "ms": 1500}, "wait": true}], "wait": true},
{"cmd": "fly", "args": {"name": "Io", "size": 0.15, "rel": {"to": "Jupiter", "deg": 180, "elev": 15}, "ms": 8000, "ease": "ease-out"}, "wait": true} ]
Sandbox, dibujo, astronauta
| cmd | args | qué hace |
|---|---|---|
| spawn | id, like, diameter, color, at: {near, dist, dir} | pos, vel | Tu propio objeto: una copia de un cuerpo o una roca; toma una órbita circular alrededor del cuerpo dominante (física, no líneas rectas) |
| move | id, vel | impact: {target, at} | Nueva velocidad o «golpear un cuerpo en un instante» |
| despawn / objects | id | all | Eliminar / listar |
| draw | items | clear | remove | Gráficos en el espacio para depuración y lecciones: arrow (vel, sun, north, {sum}), axes (roll/pitch/yaw), line, dash, path, angle (arco y grados), project (proyección sobre un cuerpo, altitud), point, text; label — texto a lo largo de la línea |
| flybys | craft, on | Puntos de asistencia gravitatoria en la trayectoria de una nave: «Cuerpo · fecha» y lo que dio la asistencia; on: false — eliminar |
| sites | body | code, group, ids, light, on | Sitios de aterrizaje (Luna, Marte, Venus, Titán): puntos y fichas en la escena — foto, nombre, año, descripción; group — vista combinada (apollo, luna, rovers, new, farside, first, china, mars, chryse, venera; el cuerpo se deduce del grupo, body es opcional); light: true — sitios en el lado diurno; devuelve lat, lon, alt para fly; on: false — eliminar |
| astro | action: goto | view | shield | land | exit, name, tpd, yaw, pitch, on, text | Astronauta: anclarlo a cualquier cosa (cuerpo, ISS, número NORAD, asteroide); view — mirar la figura; shield — quitar/poner un escudo, mensaje propio |
Consola de la página — la tecla de acento grave (ё en la distribución rusa).
Cómo trabajar
- Lee esta página (
help),connectcon el código. - Pide datos a la página:
search/open(objetos),body(tamaños, lado iluminado),where(posiciones),find(eventos),layers,state. - Prepara las acciones a partir de esos datos: un guion
play, o undeckde diapositivas que la persona recorre, obuttons. - Ejecútalo; comprueba con
screenshotylogs; ajusta.
5. Ejemplo: «cuéntame sobre los planetas»
connect {code}
layers → layer {key, visible:false} for everything except oplanets
music {theme: 0, volume: 0.4}; hide_ui {on: true}
play {steps: [
{cmd:"fly", args:{name:"Mars"}, wait: 3800},
{cmd:"camera", args:{yaw: …, pitch: …, dist: …, ms: 3000}, wait: 3200}, // valores de body {name:"Mars"}
{cmd:"say", args:{title:"Mars", sub:"228 million km · light takes 13 min", text:"…", audio:"mars.mp3"}, wait: "speech"}, // la voz es Piper en el navegador (ru ruslan, en amy); audio — un mp3 ya hecho en su lugar
…
]}
6. Recursos
- Cuerpos: el Sol, 8 planetas con lunas, planetas enanos, ~1,4 M de asteroides (por grupos de tamaño), cometas, naves interplanetarias, ~30 000 satélites terrestres (CelesTrak, diario), constelaciones en 3D, modelo de la Vía Láctea con nebulosas y cúmulos, 44 000 galaxias (2MRS).
- Los nombres funcionan en ruso e inglés (
Марс/Mars); las posiciones son ecuatoriales J2000, km. - Rango de tiempo: cualquier fecha (las efemérides se degradan lejos de hoy; los satélites solo ±90 días respecto al catálogo).
- Los enlaces para compartir (
?o=…&d=…&v=…&t=…) abren la misma vista para cualquiera.
Reglas: la página acepta solo estos comandos; sin navegación a otros sitios, sin datos personales. Mantén a la persona al control — puede pulsar «Desconectar» en cualquier momento.