Doodle
Um sistema de ilustração desenhado a código. Os temas são criados como geometria, projetados através de uma câmara e renderizados por uma 'mão' com semente que faz o traço parecer desenhado. HTML + JS puro, sem compilação, sem dependências: abra uma página no navegador.
Configuração: onde trabalhas
O motor vem incluído nesta skill em engine/ (ao lado deste ficheiro). Nunca o edites lá; uma atualização da skill substitui-o.
- Se
LOCAL.mdexistir ao lado deste ficheiro, lê-o primeiro: ele nomeia o espaço de trabalho e as ferramentas desta máquina, e substitui o padrão abaixo. - Caso contrário, o espaço de trabalho é
./.doodle(oculto) no projeto atual. Se não existir, cria-o:cp -R "<pasta desta skill>/engine" ./.doodle. - Cada caminho abaixo (
src/…,bin/…) é relativo ao espaço de trabalho. A renderização precisa de Chrome ou Chromium (CHROME=/caminhopara substituir) e python3; nada mais.
Um desenho = bin/new.sh <nome>, que cria drawings/<nome>.js (desenha dentro de draw(S), toolkit completo, com moldura automática) e a página que o renderiza. Várias coisas numa só imagem são um desenho; várias imagens separadas são vários nomes.
Os exemplos são código, não páginas. Os módulos em src/ (things.js, people.js, trials.js, scapes.js …) contêm temas trabalhados: lê-os e copia a sua construção para o teu desenho; nunca lhes adiciones ou edites. A tabela de roteamento abaixo indica qual módulo deves usar como ponto de partida.
Entrega IMAGENS, não páginas. Quando um desenho estiver pronto, executa bin/render.sh <nome>: ele escreve doodles/<nome>/<nome>.png (a cores) e <nome>-line.png (apenas linhas) no projeto e abre essa pasta para o utilizador. Diz-lhe o caminho da pasta. Não construas, abras ou direciones o utilizador para uma página HTML, canvas ou painel de controlos a menos que ele peça.
Este ficheiro é todo o contrato, e é curto de propósito para carregar completamente. O detalhe está em references/ (movido para lá na íntegra, nada omitido). A tabela de ROTEAMENTO abaixo indica qual referência deves ler para o trabalho. Lê-la faz parte do trabalho, não é opcional: cada regra nesses ficheiros foi paga com um desenho rejeitado.
O procedimento, sempre
- Nomeia a FORMA e a CLASSE (tabelas abaixo). A forma decide a página, a moldura e o orçamento de detalhe; a classe decide a caneta, o bico, o preenchimento e o tom.
- Roteia. Lê os ficheiros de referência que a tabela de roteamento indica para o teu tema, e abre o módulo que ela nomeia como ponto de partida. Nunca comeces um tema a partir de um ficheiro vazio quando já existe um kit para ele.
- Mede antes de desenhar. A partir de uma imagem de referência: proporções e paleta, sondadas, nunca recordadas. Sem uma: escreve as proporções do tema como números no cabeçalho do módulo (o sapato precisou de oito números; três renderizações sem eles falharam).
references/hand-and-craft.md§ Medição. - Constrói a LINHA PRIMEIRO. Avalia
?outline=1antes da cor. Cada valor é transportado duas vezes, como preenchimento e em linha. O detalhe diminui do foco para o plano médio para o papel.references/line-first.md. - Renderiza e OBSERVA, em linha E cor, ao tamanho da moldura. Folha de contactos para a composição, o grande plano único para a qualidade da linha. Ambos, todas as rondas.
- Corrige no KIT, não no tema, quando a rutura é de um auxiliar. Repete até cada tema se ler.
bin/check.sh drawings/<nome>.html(sem argumento = todos os desenhos): renderiza, sem NaN, sem erros de consola, sem desvio de classe.- Entrega:
bin/render.sh <nome>— PNGs emdoodles/<nome>/, pasta aberta. - Integra o que aprendeste nesta skill NA MESMA RONDA (§ Evolução).
Roteamento: o que ler, por onde começar
| Tema | Ponto de partida | Ler |
|---|---|---|
| qualquer doodle, primeira vez numa sessão | n/a | references/line-first.md, references/forms-and-classes.md |
| um objeto do quotidiano (telemóvel, chaves, garrafa, pano, óculos …) | src/things.js (o mais próximo de 20; cam, S.prism, S.on, S.dash) | things.md |
| um produto, dispositivo, gadget, eletrodoméstico | src/retro.js (Retro._kit) | products.md, geometry.md |
| um objeto redondo (chávena, vaso, fruta, garrafa) | palco src/stilllife.js (lathe, ball) ou src/still.js | still-life.md, geometry.md (construção de caminhos) |
| uma natureza-morta / arranjo / a partir de uma foto | src/stilllife.js | still-life.md |
| mobiliário | src/furniture3.js, src/kitchen.js | products.md |
| um objeto do quotidiano (portátil, tesoura, óculos, escova de dentes, secador de cabelo, t-shirt, sabonete, caderno, cadeado, urso de peluche, cabide, mochila, garrafa…) | src/things.js def(...) | products.md, geometry.md |
| uma PESSOA, pessoas, alguém numa cena | src/people.js People.figure; nunca Trials._figure (morto) | people.md |
| um animal | src/trials.js (cat) | figures-and-trials.md |
| vidro, líquido, transparência | src/trials.js (glass) | figures-and-trials.md |
| uma bicicleta, uma estrutura, qualquer coisa de tubos finos | src/trials.js (bicycle), S.limb | figures-and-trials.md |
| um sapato, uma peça de roupa, pano | src/trials.js (sneaker, fruit cloth) | figures-and-trials.md |
| plantas, flores, folhas | src/plants3.js, src/flowers.js; folhas com buracos: trials.js monstera | plants.md, figures-and-trials.md |
| um edifício, casa, fachada | src/houses.js, src/arch.js, src/arch2.js | architecture.md, geometry.md |
| uma paisagem, vista exterior | src/scapes.js (o kit de cena) | landscapes.md |
| noite, escuro, tempo, chuva | src/trials.js (night, rain) no kit de cena | figures-and-trials.md, landscapes.md |
| uma rua, um diorama, um café | src/cafe.js, src/scenes.js | landscapes.md, geometry.md |
| um quarto / interior | src/kitchen.js, src/deskscene.js | geometry.md, landscapes.md (fidelidade) |
| pena e tinta, sem cor | src/pen.js | line-first.md (tom), forms-and-classes.md (ink) |
| um storyboard / sequência | src/board.js | storyboards.md |
| lettering, um letreiro | src/letter.js | pages-and-files.md |
| um ecrã, UI, terminal (texto claro em fundo escuro) | src/letter.js + linhas com cor de tom | pages-and-files.md (entrada letter.js) |
| fazê-lo mexer (Rive) | o exportador Rive (não incluído; vê o ficheiro) | animation.md |
| vê-lo desenhar, subdesenho | ?draw=<key>, ?sketch=1 | hand-and-craft.md |
| limpo / vetorial / não rabiscado | n/a | a skill clean-illustration se estiver instalada |
| um CONJUNTO, um teste de stress | uma página de conjunto existente como modelo | checking.md |
| um doodle que deve ALINHAR com uma renderização (esboço → limpeza final) | traça a silhueta, cria o interior | registration.md |
| que página / ficheiro faz o quê | n/a | references/pages-and-files.md |
Todos os caminhos references/ são relativos à pasta desta skill.
Formas
| Disseram | Forma | Exemplo para começar | Orçamento de detalhe |
|---|---|---|---|
| "desenha-me uma caneca / uma cadeira" | tema | src/things.js, src/retro.js | tudo, uma coisa com total fidelidade |
| "faz-me N deles" | conjunto | um desenho bin/new.sh por item, ajudantes partilhados em cada | um toolkit, o detalhe vive no toolkit |
| "uma casa / uma montra" | elevação | src/houses.js, src/arch.js | três vãos, 55% preenchimento preto sólido |
| "uma rua / uma vista / uma paisagem" | cena | src/scapes.js, moldura + recorte declarados | a escada de profundidade de três degraus |
| "o quarteirão inteiro / um pequeno mundo" | diorama | src/cafe.js | as bordas do quarteirão ficam DENTRO da imagem |
| "um quarto" | interior | src/kitchen.js, src/deskscene.js | primeiro plano completo, parede de fundo característica |
| "storyboard disto" | painel | src/board.js | definido pelo TAMANHO DO PLANO, não pelo tema |
| "pena e tinta / sem cor" | registo ink | src/pen.js | tom transportado na linha, sem preenchimento algum |
Um conjunto não é uma cena (coisas numa página partilham apenas uma folha), e um painel não é um conjunto (fidelidade igual perde a sequência). O indicador: as coisas devem partilhar o MESMO ESPAÇO? Então é uma cena.
Classes (src/spec.js; texto completo em references/forms-and-classes.md)
| classe | caneta | bico | ajuste | preenchimento | tom |
|---|---|---|---|---|---|
object | 0.30 | firme | .84/.84 | liso, sombreado pela normal da face | sombra é um PREENCHIMENTO mais escuro, mais o seu gémeo em linha |
ink | 0.26 | caneta | .90/.88 | NENHUM, o papel é o objeto | apenas linha; uma trama de pontos é proibida |
product | 0.30 | firme | .84/.84 | um material = uma cor | apenas vincos > ~35° |
elevation | 0.30 | firme | .86/.84 | 55% painéis pretos sólidos | hachura nos telhados, no lado da sombra |
plant | 0.30 | firme | .84/.88 | liso; tom claro .96, outros .84 | apenas rabisco para massa de folhagem |
flower | 0.26 | firme | .92/.90 | liso | nenhum |
scene | 0.30 | firme | .96/.94 | liso; sombra é um preenchimento mais escuro | apenas hachura onde nada está à frente |
diorama | 0.22 | firme | .94/.92 | liso | nenhum |
panel | 0.26 | firme | .94/.94 | liso, menos que o tema sozinho | um valor chão, um céu |
furniture, interior | 0.16 / 0.15 | caneta | — | pesos LEGACY; novo trabalho usa object | — |
Declara a classe, nunca redigita os números: Spec.wrap(cls, label, build). bin/check.sh audita o desvio em cada página. Uma classe possui a mão; uma página possui o papel. Adiciona uma classe apenas quando a política de preenchimento ou tom for genuinamente diferente.
Regras rígidas (cada uma é um desenho rejeitado)
Linha primeiro e fidelidade
- Apenas linha (
?outline=1) deve ser um desenho ACABADO. Cada página honra?outline=1; verifica páginas que copiaste (umaoutline: falsecodificada). - Cada valor é transportado duas vezes: material escuro = hachura; uma curva = nervuras que se curvam com a superfície; uma sombra projetada = hachura sem contorno; uma marca que NOMEIA a coisa = uma marca com contorno, nunca um preenchimento
w: 0. Audita cadaw: 0. - O foco recebe detalhe completo, o plano médio contorno mais 2–3 linhas, o fundo é PAPEL (o seu único tom é a sombra que o tema projeta). Semi-fecha os olhos: se a parede for tão ocupada como o tema, corta a parede.
- A hachura é ENFILERADA como linhas (
S.hatch), nunca um tomk.T; preenchimentos posteriores cortam-na.gapé o valor: 2.4 claro, 1.5 médio, 1.1 escuro. Hachura cruzada apenas na ÚNICA coisa mais escura do foco. - Um lado de sombra é uma CRESCENTE limitada por curvas que se curvam com a forma, nunca um corte de semiplano reto (lê-se como um objeto partido em dois).
Geometria e construção de caminhos
- Uma linha reta que não criaste é um bug de caminho: uma corda de concatenar duas metades na direção errada, ou uma forma aberta traçada
closed. Imprime os pontos. - Uma faixa à volta de um corpo opaco é apenas a sua metade MAIS PRÓXIMA; apenas uma boca aberta é uma elipse completa.
- Buracos são CORTADOS (
keyhole), nunca pintados na cor de fundo. Buraco aparece em linha mas não em cor = o seu enrolamento. - Coisas finas (membros, tubos, caules) são UMA tira através das suas juntas; contorna os lados, deixa as pontas encaixarem no que é desenhado depois.
- Recipientes: interior → borda distante → conteúdo → parede frontal. O conteúdo afunda abaixo do lábio.
- Mede as proporções como números antes de desenhar um objeto conhecido. Esticar uma forma errada mantém-na errada (o sapato).
- Dimensiona o mobiliário a partir do corpo que o usa, nunca o contrário.
- Um doodle que deve registar-se com uma imagem: TRAÇA a sua silhueta a partir do alfa da imagem, cria o interior, fixa a moldura à imagem e corta o ajuste de classe na exportação (
registration.md). - Pessoas:
People.figureapenas. Gesto antes do detalhe (peso numa perna, ancas e ombros inclinam opostos); poses são ÂNGULOS, pelo que a proporção está bloqueada; mobiliário e coisas seguradas derivam das juntas devolvidas. Cabelo de trás pinta antes do corpo. - Uma longa linha tracejada reta através de uma forma suave = o bug da crescente (corrigido em
S.soft); um torno ondulado = poucos nós + easing por segmento: usa um perfil denso comsteps: 1. { dash: true }não faz nada: usaS.dash. Enquadra objetos à sua caixa de conteúdo, não a olho.- "Desajeitado" = construção, não detalhe: avalia UM tema ao tamanho real; os contornos devem UNIR-SE (sem pontas abertas nas juntas), o tom é apertado e regular ou ausente, o peso da caneta encaixa a largura da forma.
Enquadramento
- A moldura é DERIVADA, nunca digitada: nos kits de plano de imagem são os limites da PRIMEIRA região, pelo que a primeira chamada é
S.panel(<a moldura>); com uma câmara, a partir da projeção. Algo não visível? Verifica se está dentro da moldura antes de o redesenhar maior.clip = truerecorta para a moldura declarada. - Cada camada de chão vai até ao fundo da moldura (
FOOT), ou o céu mostra onde uma camada mais próxima desce. Uma regra de chão atinge ambas as bordas de uma folha, não além delas.
Cenas, noite, tempo
- Profundidade é um número
d(0 perto, 1 longe) e a caneta, o intervalo de hachura, a cor e o detalhe leem-na todos. Uma montanha com o peso do banco é O falhanço da paisagem plana. - Noite inverte o valor: o céu é a hachura mais densa, cada luz um buraco recortado; um brilho é MAIS CLARO que o céu. Uma figura contra luz é uma silhueta hachurada.
- A chuva é desenhada por último, ausente debaixo de um guarda-chuva; um reflexo é o tema invertido, esmagado, em faixas partidas, sem contorno.
Páginas e paletas
- Uma página deve declarar cada chave de paleta que os seus temas usam; uma chave desconhecida já renderizou preto silenciosamente.
- Execuções paralelas de Chrome headless precisam de um
--user-data-dirseparado cada uma, ou os screenshots saem em branco.
Verificar
cd <espaço de trabalho> # vê Configuração
bin/check.sh drawings/<nome>.html # renderiza, sem NaN, sem erros de consola, sem desvio de classe
bin/shot.sh "drawings/<nome>.html?outline=1" out.png [1120x700] # um aspeto funcional; remove ?outline=1 para cor
bin/render.sh <nome> # a entrega: doodles/<nome>/*.png, pasta aberta
O Chrome/Chromium é encontrado por bin/chrome.sh (substitui CHROME=/caminho); cada screenshot recebe o seu próprio --user-data-dir, pelo que execuções paralelas são seguras. Olha para cada PNG (abre-o, ou lê-o se conseguires ver imagens). Um check.sh que passa prova que renderizou, não que se lê.
Evoluir esta skill
Quando corrigires uma lacuna, escreve-a onde uma sessão NOVA a encontrará (se esta skill estiver instalada apenas para leitura, guarda estas notas no espaço de trabalho e diz isso):
- O ficheiro de referência do tópico (
references/<topic>.md): a regra, com o seu sintoma, declarada como instrução.
...
[truncado para tradução]