O que poku-pixel-fx faz?
POKU Pixel FX é um fork/derivado de código aberto, localizado para coreano e baseado em TypeScript do PixelFX by Patch, mantido como um repositório separado sem link de fork no GitHub. A licença MIT original credita Patch e Hugo Duprez; preserve os avisos de direitos autorais e atribuição em LICENSE e NOTICE.md.
Requer Node.js 18 ou superior; ffmpeg é opcional para prévias em GIF e MP4.
Efeitos de pixel art como código. Cada efeito é um arquivo, src/fx/<categoria>/<nome>.ts, que desenha em dois buffers: cor (pixels: opacos, pontilhados ou verdadeiramente translúcidos) e luz (brilho aditivo). Sem imagens, então um efeito pode ser reproduzido ao vivo, recolorido, espelhado, re-semeado e renderizado em uma folha de sprites para qualquer engine.
O método é de Hugo Duprez (How to make (good) pixel art effects with Claude): código é argila, confie nos seus olhos, alimente suas referências. Prompts únicos geram efeitos medíocres. Rascunhos que você renderiza, observa e refina geram bons efeitos.
Antes de tudo
- Trabalhe em um checkout do Poku Pixel FX contendo
package.jsonetools/render.mts. Se não existir, obtenha a biblioteca pública no projeto ou workspace escolhido pelo usuário:git clone https://github.com/Stankjedi/poku-pixel-fx.git. O arquivo de skill sozinho não contém a biblioteca de efeitos. Nunca use o caminho específico da máquina de outra pessoa. Instale as dependências do checkout comnpm ciquando necessário; não repita se já estiver instalado. - Execute
npm run buildantes de usar as ferramentas ou a galeria; o compilador emite módulos de tempo de execução parabuild/e ferramentas de CLI parabuild-tools/. - Verifique se funciona:
node build-tools/tools/render.mjs fire/torchescreverecords/fire/torch/contact.png. Abra esse PNG com sua ferramenta de leitura de imagem. Essa folha de contato é como você verá cada efeito daqui em diante.
1. Procure um efeito existente primeiro
node build-tools/tools/list.mjs <palavras> pesquisa ids, nomes, tags e descrições (node build-tools/tools/list.mjs frost, node build-tools/tools/list.mjs slash loop). docs/CATALOG.md lista tudo por categoria. Renderize os candidatos e observe-os antes de escolher. A maioria das solicitações é um efeito existente com opções diferentes:
palette: a rampa principal, de escuro a claro, como strings hex. Qualquer rampaPALemsrc/core/color.ts(fire ember lava smoke dust ice water electric volt poison holy heal arcane shadow blood earth stone gold leaf wood metal bone neon cyber matrix candy night) ou a sua própria. Um fogo azul é{"palette": PAL.ice}.seedpara uma versão diferente mas equivalente;flippara virar à esquerda;anglepara rotacionar;light(0..1+) para intensidade do brilho; além dos próprios controles de cada efeito emmeta.options(size, count, radius, text, height...).- Tente opções sem editar código:
node build-tools/tools/render.mjs fire/torch --opts '{"palette":["#102","#215","#43a","#8cf","#fff"]}'.
2. Coloque no jogo
Jogos Canvas ou WebGL em JS ou TS (canvas puro, Phaser, PixiJS, Kaplay, three.js): use o código diretamente. Ele não tem dependências; copie src/core e os arquivos de efeito que você precisa, ou dependa do repositório.
import { createFrame, clearFrame, createFx, composite } from "poku-pixel-fx"; // src/core/index.ts
import * as frostNova from "poku-pixel-fx/fx/ice/frost-nova"; // src/fx/ice/frost-nova.ts
const frame = createFrame(320, 180); // a resolução em pixels do jogo; ox, oy rolam com a câmera
const img = new ImageData(320, 180);
const fx = createFx(frostNova, { x: hero.x, y: hero.y, flip: hero.facing < 0 });
// a cada tick
fx.update(dt);
clearFrame(frame);
fx.draw(frame, "back"); // o que vai atrás dos personagens
drawCharacters(); // seus próprios sprites, ou desenhe-os em frame.color você mesmo
fx.draw(frame, "front");
composite(frame, img.data, background); // cor sobre o fundo mais luz; ou null para transparente
ctx.putImageData(img, 0, 0); // então escale o canvas para cima com image-rendering: pixelated
if (fx.done()) removeIt(); // one-shots terminam sozinhos; fx.stop() desvanece um loop
Vários efeitos podem compartilhar um único frame. Em uma engine WebGL, carregue o RGBA composto para uma textura a cada frame, ou renderize o efeito em uma folha de sprites uma vez (abaixo) e reproduza como qualquer outra animação.
Qualquer engine (Godot, Unity, GameMaker, Defold, LÖVE, Bevy, Construct): exporte folhas de sprites.
node build-tools/tools/render.mjs ice/frost-nova --sheet escreve records/ice/frost-nova/frost-nova.png (frames transparentes em uma grade) e frost-nova.json (frames no estilo Aseprite, então o carregador de atlas do Phaser, importadores Aseprite do Godot e Unity e a maioria das ferramentas o leem; meta.pokuFx tem fps, loop, tamanho do frame, colunas e o pivô). Defina o pivô para meta.pokuFx.pivot (a origem do efeito, ex.: os pés), importe com filtragem de vizinho mais próximo e sem compressão, e reproduza em meta.pokuFx.fps. O brilho é incorporado na folha como cor com alfa, que é lido como aditivo sobre cenas escuras; para cenas claras, renderize uma versão recolorida ou mantenha o efeito em uma camada escura.
Para a biblioteca completa: node build-tools/tools/render.mjs <categoria> --sheet faz uma categoria inteira.
Um golpe precisa de um corpo por trás dele. Um efeito sozinho parece um adesivo. Efeitos com um personagem carregam um act: quando o corpo se prepara, quando congelar, como o alvo reage. Use-o da maneira que o jogo for construído:
- Com o personagem padrão:
createAct(slash, { x, y })em vez decreateFx.act.update(dt),act.draw(frame), e jogue a imagem poract.shake. Ele fica parado sozinho durante um congelamento.node build-tools/tools/act.mjs <id> --sheetassa tudo em uma folha de sprites. - Com o personagem do próprio jogo: leia o tempo,
slash.actoumeta.pokuFx.actno JSON de uma folha (windup,recovery,hitscomtefreeze). Reproduza a animação de ataque do personagemwindupsegundos antes do efeito, e em cada golpe pare de atualizar tudo, efeito e personagens, porfreezesegundos. A parada de golpe do lado do host funciona em qualquer efeito, com ou sem act.
src/fx/moves/ tem ataques completos encadeados a partir dos efeitos, da preparação à recuperação: comece por lá quando alguém pedir um movimento, não um efeito.
3. Crie um novo
Leia docs/AUTHORING.md primeiro: é o contrato (meta, draw(p, t, o) para efeitos puros ou create(o) para simulados, coordenadas locais, loops contínuos, finalização vazia), o kit de ferramentas, a API do pintor e o padrão de qualidade. Leia também docs/QUALITY.md. Trate shadow/spatial-severance como a referência de curva limpa e partículas refinadas, não um estilo a impor a todos os efeitos. Novos efeitos devem usar os helpers compartilhados de ribbon, trajectory trail, envelope e path-lighting quando apropriado. Mantenha a paleta de pixels e inspecione silhuetas em tamanho nativo, tempo de impacto, espaço negativo e transparência. Testes automatizados não garantem qualidade artística. Para efeitos que carregam impacto, leia também docs/IMPACT_INTERACTIONS.md: crie um descritor de contato (tempo, ponto local, normal, material) e derive dele a resposta específica da forma e o feedback opcional de cena. Revise reação ao chão/alvo, colisões secundárias e assentamento. Não adicione o mesmo anel de choque, detritos de pedra ou tremor de tela a todo material. Preserve movimento reduzido e exportações transparentes com pivô fixo.
Então:
- Diga em uma linha com direção de arte: o que é, como se move, sua paleta, seu tempo. "Uma nova de gelo: cristais irrompem em um anel dos pés para fora, um flash branco no centro, estilhaços giram, o chão permanece congelado e desvanece."
- Encontre referências na biblioteca:
node build-tools/tools/list.mjs <palavras>, então leia os dois ou três arquivos de efeito mais próximos e pegue suas técnicas (ParticleseBitsemsrc/core/sim.tspara faíscas, fumaça e detritos,p.discpara volumes translúcidos,cyclepara partículas contínuas,tileFbmscrolls para chamas e água). Use as referências da biblioteca local como padrão de qualidade; referências externas são opcionais e exigem acesso à rede. - Rascunhe.
node build-tools/tools/new.mjs <categoria>/<nome>(adicione--looppara um loop) cria um arquivo funcional. Quando a direção estiver aberta, escreva de 3 a 5 rascunhos genuinamente diferentes (<nome>-a.ts..-e.ts), renderize todos (node build-tools/tools/render.mjs "<categoria>/<nome>-*") e olhe cada folha de contato antes de escolher. Mostre ao usuário os dois ou três mais fortes se ele estiver por perto (--giffaz animações para compartilhar). Reconstrua após alterar arquivos de origem antes de renderizar. - Olhe, julgue, corrija. Renderize, abra
records/<id>/contact.pnge julgue como um pixel artist exigente. Corrija a pior coisa, renderize novamente. Mínimo de três rodadas; uma peça de destaque leva mais.--allmostra cada frame,--mp4mostra movimento em velocidade total. - Represente se um personagem estiver envolvido: adicione
export const act(veja "Acts" emdocs/AUTHORING.md), com uma preparação antes de t = 0, uma mudança de pose no frame de liberação, um congelamento no contato e uma recuperação.node build-tools/tools/act.mjs <id>mostra passos consecutivos em 12 fps: julgue o movimento a partir deles e de--mp4, não de uma folha de contato de amostras. - Verifique.
node build-tools/tools/check.mjs <id>detecta desenho fora da tela, one-shots que não terminam vazios, emendas de loop, aleatoriedade não semeada e frames lentos, e em um act: chaves fora de ordem, campos de pose desconhecidos e mãos que teletransportam. Corrija até passar limpo. Apague os rascunhos que você não manteve.
O que procurar, e a correção usual:
| você vê | correção |
|---|---|
| lê como pasta em 1x | menos cores, uma silhueta clara, um ponto focal, formas maiores |
| pontilhado: pixels de ruído isolados dentro de formas | limite o ruído menos, quantize com at(), sem ruído em formas pequenas |
| flutuante, sem impacto | rápido de entrada, lento de saída (ease.outQuart/outExpo), um frame heroico branco de 1 a 2, tempo total mais curto |
| rígido ou mecânico | varie cada partícula (tamanho, velocidade, atraso, vida), adicione movimento secundário (faíscas, fumaça, detritos) |
| lavado | menos brilho (k 0,2 a 0,5), passos de borda mais escuros, mantenha branco apenas para o núcleo mais quente |
| plano | luz de um lado: mais claro no topo-esquerda, passo mais escuro no fundo-direita; um passo de rampa mais escuro na base |
| gradientes suaves, aparência vetorial | passos de rampa duros na cor; suavidade apenas na luz e em fumaça translúcida |
| um tabuleiro de xadrez onde deveria haver fumaça | partículas SMOKE, VAPOUR ou DUST, ou p.disc: verdadeiramente translúcido, iluminado por cima |
| emenda quando um loop envolve | cycle, loopNoise(phase), scrolls tileNoise de célula inteira, sin(phase * TAU * n) |
| um one-shot que desaparece de repente | deixe-o encolher, pontilhar ou desaparecer antes de t = duração |
| um ótimo efeito em um personagem morto | dê a ele um act: preparação, pose de liberação, congelamento no contato, um alvo que reage, recuperação |
| o act parece sem peso | uma preparação na direção oposta ao golpe, um congelamento mais longo (até 0,2 s), uma mudança de silhueta maior, tremor |
| o golpe cai fora de sincronia | mova a chave do golpe para a constante do próprio efeito, não para um tempo que você estimou |
| ele segura a arma mal | mantenha uma dobra no cotovelo, hastes na frente do peito; em um balanço, a lâmina atrasa a mão; braços alcançam cerca de 15 px e não esticam, então mova o corpo |
| seus braços se cruzam ou a pose parece plana | ele está virado três-quartos em nossa direção: para braços abertos, a mão próxima vai para a esquerda (fx < 0), a mão distante para a direita, com turn: 1; yaw realmente o vira |
Efeitos direcionais virados para a direita, efeitos de chão na altura y = 0, efeitos de ator envolvem o.actor (a máscara e pixels de um personagem padrão de 24 x 38), e nada usa Math.random. Motivos genéricos são aceitáveis; nunca recrie sprites, personagens ou logotipos de um jogo específico.
4. Código nativo em vez de JS
Se o jogo não pode executar JS e uma folha de sprites não é suficiente (um efeito que segue um alvo em movimento, ou precisa de cores por instância em tempo de execução), porte o efeito. Efeitos puros são uma função do tempo; os simulados avançam as partículas em src/core/sim.ts. Mantenha a ideia de dois buffers, o limiar Bayer 4x4 para alfa pontilhado e as consultas de rampa de paleta. Renderize o original em JS e seu porte lado a lado para verificar se combinam.
O núcleo, todos os efeitos, galeria e CLI são fontes TypeScript. Compile antes do uso; após criar ou alterar um efeito .ts, recompile antes de renderizar. A galeria e a CLI suportam pesquisa em coreano e inglês; o coreano recorre a uma fonte do sistema. Para trabalho nativo em engines, consulte docs/NATIVE_MIGRATION.md; não afirme que um runtime nativo existe.
Compartilhe um resultado
Quando o usuário solicitar compartilhamento público, use o checkout local e execute npm run build seguido de npm run share -- <categoria>/<efeito>. O comando renderiza um PNG transparente e seu JSON Poku em uma nova pasta records/share/, valida os limites atuais de tamanho e animação do site, e imprime caminhos de arquivo absolutos e a página de compartilhamento. Não publica nem faz login.
Abra https://poku-pixel-fx.stankjedi.chatgpt.site/shared, faça login com ChatGPT se necessário, e siga o fluxo de upload da página. Selecione o PNG e JSON correspondentes juntos no formulário de compartilhamento, preencha qualquer título e tags obrigatórios e envie após o uploader confirmar a declaração de direitos. Para múltiplos trabalhos, a seção em lote aceita nomes de arquivo PNG e JSON correspondentes. Use a arte solicitada pelo usuário e cumpra as regras de upload e confirmação do navegador. Nunca fabrique cabeçalhos de identidade, obtenha ou copie credenciais, ou afirme os direitos legais do usuário sem sua confirmação. Verifique a galeria por uma mensagem de sucesso e a entrada resultante antes de reivindicar uma publicação. O site pode impor cotas por conta. Preserve LICENSE, NOTICE e avisos de direitos autorais e permissão de terceiros ao redistribuir o software.