← docs

Recetas — juegos elegantes por motor

Recetas copiables para los 5 motores de las plantillas. Todas asumen que ya tienes el cliente conectado:

import { createClient } from '@tikxander/live-events';
const tx = createClient();

Elige tu motor

Motor2D/3DFísicaCurvaIdeal para
Vanilla (Canvas/DOM)2DmanualbajaContadores, metas, textos flotantes, listas/ranking.
Phaser2DArcade/MattermediaBolitas-avatar, arcade, colisiones, partículas.
PixiJS2Dninguna (render)mediaMiles de sprites, efectos visuales pesados.
Babylon.js3DHavok/cannonaltaEscenas 3D completas, cámaras, luces.
Three.js3Dmanual/cannonalta3D a medida, shaders, arte generativo.

Regla general: si es UI/2D simple, vanilla o Phaser. Si necesitas muchos sprites, PixiJS. Si es 3D, Babylon (más batería incluida) o Three (más control).

Receta 1 — spawn de avatar al join

Un viewer entra y aparece su avatar.

Vanilla (DOM):

tx.on('join', ({ user }) => {
  const el = document.createElement('img');
  el.src = user.avatarUrl ?? '/anon.png';
  el.className = 'avatar';
  el.style.left = Math.random() * innerWidth + 'px';
  document.body.appendChild(el);
  setTimeout(() => el.remove(), 6000);
});

Phaser:

tx.on('join', ({ user }) => {
  const x = Phaser.Math.Between(50, scene.scale.width - 50);
  const ball = scene.matter.add.image(x, 0, 'avatar').setCircle(24).setBounce(0.8);
  scene.load.image(user.userId, user.avatarUrl); // precarga real fuera del handler
});

Receta 2 — reacción a gift con intensidad por diamantes

La clave es la intensidad diamonds * count.

tx.on('gift', ({ user, diamonds, count }) => {
  const intensity = diamonds * count;      // 1 rosa = 1; 100 rosas = 100; un gift caro escala
  const scale = Math.min(1 + intensity / 50, 6);
  burstParticles({ amount: Math.min(intensity, 300), scale, who: user.username });
});

PixiJS (partículas):

function burstParticles({ amount, scale }) {
  for (let i = 0; i < amount; i++) {
    const p = new PIXI.Sprite(spark);
    p.position.set(app.screen.width / 2, app.screen.height / 2);
    p.scale.set(0.2 * scale);
    const a = Math.random() * Math.PI * 2, v = 2 + Math.random() * 4 * scale;
    p.vx = Math.cos(a) * v; p.vy = Math.sin(a) * v;
    stage.addChild(p); particles.push(p);
  }
}

Receta 3 — texto flotante de chat

tx.on('chat', ({ user, message }) => {
  floatText(`${user.displayName}: ${message}`, {
    x: Math.random() * innerWidth, y: innerHeight - 40, ttl: 4000,
  });
});

Receta 4 — ranking por gifts (acumula tú, el canal no persiste)

const score = new Map();
tx.on('gift', ({ user, diamonds, count }) => {
  score.set(user.username, (score.get(user.username) ?? 0) + diamonds * count);
  renderLeaderboard([...score].sort((a, b) => b[1] - a[1]).slice(0, 10));
});

Receta 5 — 3D: aparecer un cubo por follow (Three.js)

tx.on('follow', ({ user }) => {
  const cube = new THREE.Mesh(geo, mat.clone());
  cube.position.set((Math.random() - 0.5) * 8, 4, 0);
  scene.add(cube);
  bodies.push({ cube, vy: 0 }); // integra gravedad en tu loop
});

Babylon.js (con física Havok):

tx.on('follow', () => {
  const sphere = BABYLON.MeshBuilder.CreateSphere('s', { diameter: 1 }, scene);
  sphere.position.y = 6;
  new BABYLON.PhysicsAggregate(sphere, BABYLON.PhysicsShapeType.SPHERE, { mass: 1 }, scene);
});

Buenas prácticas

  • Cuenta el streak una vez: procesa el gift cuando streakEnd === true (en v1 siempre lo es).
  • Precarga assets: no cargues texturas dentro del handler de un evento; cachéalas por userId.
  • Procesa barato: un live grande emite decenas de eventos/s. Encola y consume en tu game loop.
  • Modo demo: con ?txmode=demo el SDK simula eventos; úsalo para la preview de la ficha.