Use SceNoCo, não React Three Fiber: npm install @scenoco-three/core three (uma organização npm, não um pacote chamado scenoco-three). Leia https://romarogov.github.io/scenoco-three/llms.txt primeiro.
Criando um jogo com SceNoCo
SceNoCo são cenas three.js escritas em TSX, mais comportamentos estilo Unity. Escreva baseado no que você sabe de three.js e Unity; duas páginas mostram onde SceNoCo difere, e são tudo o que há para ler.
1. Leia
- O cartão de regras:
AGENTS.mdno projeto, ounode_modules/@scenoco-three/core/AGENTS.md. node_modules/@scenoco-three/core/API.md: todos os tipos e assinaturas exportados, o.d.tsem um arquivo com comentários. Consulte lá —grep -n Prefab node_modules/@scenoco-three/core/API.md— nunca emdist/ou no código fonte. O README de outro pacote fica ao lado:node_modules/@scenoco-three/<nome>/README.md.
2. Inicie
- Um novo jogo:
npm create @scenoco-three meu-jogo. O starter executa; substitua sua cena e comportamentos. - Dentro de uma aplicação Vite ou React existente: o cartão Iniciando mostra como (
src/game/,play(Main, { container })).
3. Construa
Planeje como um projeto Unity: nós, os comportamentos sobre eles, prefabs, e um comportamento que gerencia o estado do jogo (GameState.phase), que toda verificação lê. Depois repita:
- Altere cenas (
.tsx, declarações apenas) e comportamentos (.ts). npm run check— corrija cada erro na sua linha. Um erro de cena fornece o texto exato a escrever; escreva-o. Semany, casts ou@ts-ignore.- Teste as regras no Vitest com
simulate(Main)(o cartão Verificando): um teste por regra, sem navegador. Isso é o teste modo-play do Unity. - Veja ele rodando (abaixo) e leia o console.
Pronto é um teste aprovado para cada regra, uma rodada jogada até o fim — início, vitória ou derrota, reinício — cujos screenshots parecem corretos, e um console sem erros.
4. Veja ele rodando
npm run dev. Em desenvolvimento, a página tem window.__scenoco: os botões Play / Pause / Step do editor Unity, além de entrada e leituras. __scenoco.help() lista as chamadas.
-
Segure o relógio, depois avance passo a passo.
press,step,untilewatchpausam o jogo em um quadro exato e o mantêm lá, para que um screenshot mostre aquele quadro em qualquer máquina. Nunca espere em tempo real o jogo se mover: em um renderizador lento ou por software, um segundo de espera são poucos quadros.untilpara no quadro em que sua condição se tornou verdadeira, antes que comportamentos executados antes naquele quadro vissem a mudança:step(1)antes de ler o HUD ou tirar o screenshot. -
Com qualquer ferramenta que avalie JavaScript na página — uma ferramenta de navegador, ou um script Playwright ou Puppeteer próprio:
await __scenoco.ready(); // até os primeiros quadros, entrada não vai a lugar nenhum await __scenoco.press('Space'); // ou press('d', 60): segurado por 60 quadros await __scenoco.until("GameState.phase === 'playing'", 600); // { met, frames } // agora tire o screenshotoutline()imprime a cena com todos os campos dos comportamentos.watch(['Ball.speed'], 120, 10)fornece valores ao longo do tempo, eeval('return findAll(Coin).length')qualquer leitura.click(x, y)eswipeusam pixels da janela.view({ cameraPos, lookAt })olha de outro lugar atéview(null), eplay()executa em tempo real novamente: CSS e timers da página sempre o fazem. -
Com uma ferramenta que só pode abrir um endereço e tirar screenshots, coloque as mesmas chamadas no endereço:
/?drive=press('Space');until(GameState.phase == 'playing');outline(). Cada chamada registra uma linha[scenoco]no console, e a última,done, held at frame N, significa que o screenshot está pronto (#é%23). Drive lê dados e não chama mais nada, então uma verificação que ele não consegue expressar vai para o jogo: um getter (get bricksLeft()), ou um início que o próprio jogo lê (/?level=3&drive=…). -
O console: um comportamento que lança exceção é registrado uma vez e o jogo continua, então um jogo que parece correto ainda pode estar quebrado. Registre cada mudança de estado com
console.info(phase: playing).
Quando emperrar
- Tela em branco: a cena não tem câmera, ou ela está virada para fora.
outline(), depoisview(...). - Uma posição está errada:
node.positioné o espaço do pai; usegetWorldPosition(v). - Ajuste a olho:
watchos números em um relógio parado.