Animações Voxel
Crie cenas que parecem um jogo de construção de blocos, sem usar nada de um jogo real: cada textura é gerada em código em tempo de execução e o personagem é um design original. A saída é uma única página HTML autocontida (interativa, compartilhável) e, quando solicitado, um vídeo quadro a quadro renderizado a partir dessa mesma página.
Arquivos nesta skill
assets/voxel-kit.js: o kit (texturas, materiais, loop do app, câmera orbital, céu com dia/noite, terreno de ilha, plataforma de estúdio, rig do personagem, partículas, pop-in, explosão, tochas, helpers de roteamento, gravador, modo de captura). Leia-o antes de escrever uma cena: a referência da API abaixo é um resumo, o arquivo é a verdade.assets/template.html: página inicial com o marcador do kit, ilha, personagem e uma pequena timeline.examples/house-builder.html: um construtor coloca uma casa bloco por bloco, comemora, explode, loop.examples/melting-crystal.html: exemplo de física (fusão de Lindemann de uma rede de gelo 6×6×6, com um termômetro voxel, poça e recongelamento). Copie sua estrutura para explicadores científicos.scripts/inline_kit.py: substitui<!-- VOXEL_KIT -->em uma página pelo kit, gerando um único arquivo.scripts/render.py: renderização quadro a quadro para quadros PNG e.mov/.mp4/.webm.
Se apenas este SKILL.md estiver disponível (a pasta estiver faltando), obtenha a skill completa em https://github.com/normix93/voxel-animations antes de construir.
Fluxo de trabalho
- Fixar a ideia em uma linha: o que é construído, transformado ou explicado, e como o loop termina (reset, explode, congelar, câmera voa para fora). Decida o destino: página interativa, vídeo para edição (fundo transparente ou não), curta vertical (1080×1920).
- Storyboard como uma timeline: 3–6 beats com durações, ex.
0–2 s local vazio → 2–40 s construção → 40–44 s comemoração → 44–49 s explode → loop. Cada beat é ummodeem uma máquina de estadosapp.onUpdate(veja o exemplo da casa). - Comece a partir de
assets/template.html, mantenha o marcador do kit, escreva a seção SCENE. Reutilize peças do kit em vez de reescrevê-las. Mantenha tudo em uma página. - Construa a página:
python3 scripts/inline_kit.py cena.src.html cena.html. - Verifique-a: abra-a (ou renderize alguns quadros com
render.pyem uma pasta e olhe para eles). Procure por: blocos flutuando ou sobrepostos, personagem andando através de paredes, câmera colidindo com árvores, primeiros segundos vazios, cintilação em blocos transparentes. - Entregue: publique a página como um artefato quando o ambiente suportar e também entregue o arquivo .html; renderize o vídeo se solicitado (veja Exportação).
Regras de estilo
- Original apenas. Nunca use texturas, sons, logotipos, mobs, personagens ou nomes de um jogo existente. Não chame a saída de "Minecraft" de forma alguma: diga voxel, blocos, mundo de blocos. As texturas processuais e o construtor de capacete duro no kit são seguros de usar e modificar.
- Pixel-crisp: texturas 16×16 com
NearestFilter(o kit faz isso). Luz forte, sombras nítidas, poucas cores por material, pouco ruído. - Movimento tem peso: blocos aparecem com overshoot (
app.pop), detritos usam gravidade (≈20–22 blocos/s²) e quiques amortecidos, o personagem anda a ~5 blocos/s e vira suavemente. Evite tweens lineares para qualquer coisa física. - Legível de relance: um assunto principal no centro, câmera orbitando lentamente
(
autoSpeed0.05–0.1), fundo calmo (céu ou corstudio). - Texto: a página pode ter um título e linha de status. Para vídeo, renderize com
?clean(sem UI). Se rótulos forem necessários no vídeo, use palavras muito curtas; explicações pertencem à narração ou à página, não aos quadros.
API do Kit (resumo)
const app = VK.createApp({
title, subtitle, hint, // Texto da UI (oculto com ?clean ou tecla H)
sky: 'day' | 'night' | 'studio', // studio = cor sólida (studioColor), sem neblina
cycle: false, dayLength: 48, tod: .27, // hora do dia 0..1 (.25 lado do nascer do sol, .75 noite)
camera: { radius, phi, theta, target: [x,y,z], auto: true, autoSpeed: .07 },
speed: 1, seed: 7, fileName: 'minha-cena', shadowSize: 28,
});
app.M.grass | dirt | stone | sand | planks | roof | log | leaves | glass | water | ice | snow | cobble | brick | lava
VK.solid(0xff8800, { glow, opacity, noise, border }) // material de bloco colorido pixel
VK.block(app, 'planks' | material, x, y, z, { pop: true }) // malha única (movendo/aparecendo)
VK.instanced(app.scene, material, [[x,y,z], ...]) // blocos estáticos, uma chamada de draw
const world = VK.island(app, { seed, radius: 18, flatRadius: 7.5, trees: 10, water: -1, snowLine })
// → world.groundTopAt(x, z), world.hAt(ix, iz)
VK.platform(app, { size: 16, top: .5, mat: 'stone', topMat: 'cobble' }) // piso de estúdio
const hero = VK.character(app, { ground: world.groundTopAt, position: [x,0,z], yaw, colors: { shirt:[r,g,b], hat: 0xf5c518 | null, ... } })
hero.goTo([[x,z], ...]) · hero.arrived · hero.face(x, z, dt) · hero.jump(v)
hero.pose = 'idle' | 'reach' (set hero.reach 0..1) | 'cheer' | 'panic' | 'wave'
hero.lookTarget = {x,y,z} | null
VK.standOutside(x, z, { halfX, halfZ, cx, cz }) // onde ficar para trabalhar em um bloco de uma caixa
VK.routeAround(from, to, { halfX, halfZ, cx, cz }) // waypoints que contornam essa caixa
VK.explode(app, meshes, { center, power, ground, onDone })
VK.torch(app, x, y, z) // luz fica mais forte à noite
app.puff(position, material, n, power) · app.pop(mesh) · app.clearParticles()
app.onUpdate((dt, time) => { ... }) // dt já escalado por speed; determinístico no modo de captura
app.rand() // aleatório com semente: use em vez de Math.random
app.status(html) · app.button({ label, key, toggle, on, onClick }) · app.standardButtons({ cycle })
app.start()
Regras que mantêm as cenas corretas:
- Use
app.rand()(com semente), nuncaMath.random(), para que as renderizações sejam repetíveis. - Coloque todo o movimento em
app.onUpdateusandodt; nunca usesetTimeout/setIntervalpara animação (o modo de captura quebraria). - Blocos são 1×1×1 e centralizados em coordenadas inteiras; uma coluna de altura
htem sua superfície superior emh + 0.5. Um personagem fica emgroundTopAt(x, z). - Cenário estático →
VK.instanced; qualquer coisa que se move, aparece ou explode →VK.block. - Grandes quantidades: mantenha malhas em movimento abaixo de ~1500; além disso, anime um InstancedMesh.
Receitas
- Sequência de construção: faça um plano ordenado
[{type,x,y,z}](camada por camada, andando pelo perímetro; fileiras serpentinas para telhados). Para cada item: roteie parastandOutside, definapose='reach', spawn a ~45% do alcance, próximo. Vejaexamples/house-builder.html. - Explique física com blocos: mapeie a quantidade para algo visível. Temperatura →
amplitude de tremulação ∝ √T (equipartição); pressão → colisões de blocos; níveis de energia →
andares de uma torre; um campo → setas de blocos; entropia → uma parede ordenada reembaralhada;
gravidade → pilhas que tombam quando sem suporte. Mostre a variável de controle com um medidor
voxel (o termômetro em
melting-crystal.html) em vez de números na tela. - Transformações: mude
mesh.material(água ↔ gelo, pedra → lava), achate comscale.y, deslize com um lerp suavizado entre duas posições. - Átomos / moléculas: cubos
VK.solid(cor)para partículas,glow: truepara elétrons ou fótons, cubos pequenos (mesh.scale.setScalar(.3)) para rastros. - Finais que fazem loop: exploda (
VK.explode) → reset, ou congele + câmera lenta, ou a noite cai (app.sky.cycle = true) com tochas.
Exportação
Parâmetros de URL (funcionam em qualquer página construída com o kit):
?clean oculta UI · ?alpha fundo transparente (sem céu, sem neblina) · ?seed=3 ·
?speed=2 · ?night · ?capture&fps=30 modo quadro a quadro usado pelo renderizador.
Teclas: H oculta UI · Space pausa · V gravação WebM rápida em tempo real (funciona quando a
página é aberta de um arquivo local; prévias hospedadas podem bloquear o download).
Vídeo quadro a quadro (preferido para edição):
pip install playwright && python3 -m playwright install chromium # uma vez, ffmpeg também necessário
python3 scripts/render.py cena.html --seconds 12 --fps 30 --out cena.mov # ProRes 422 HQ
python3 scripts/render.py cena.html --seconds 12 --alpha --out overlay.mov # ProRes 4444 com alfa
python3 scripts/render.py cena.html --size 1080x1920 --warmup 3 --out short.mp4 # vertical H.264
python3 scripts/render.py cena.html --seconds 5 --out frames/ # apenas quadros PNG
--warmup pula segundos de cena antes da gravação; --params "seed=3&night" adiciona params
URL; --headed usa um navegador visível (GPU real, mais rápido na maioria dos laptops). Com
--alpha a câmera ainda orbita; defina camera: { auto: false } para uma sobreposição estática.
Antes de entregar
- A página abre sem erros no console; o primeiro quadro já mostra o assunto.
- O loop funciona pelo menos duas vezes (reset limpa malhas, luzes e partículas).
- O personagem nunca atravessa paredes; nada flutua a menos que seja intencional.
- Para vídeo: renderizado com
?clean, tamanho/fps corretos, alfa verificado se solicitado. - Nenhum nome, textura ou personagem de jogo de terceiros em lugar algum (código, título, nomes de arquivo).