Voltar para o Blog
Quest Log

Sprites de Visual Novel: Poses, Expressões e Camadas

Personagem de visual novel em meio corpo com variações de olhos, sobrancelhas e bocas separadas em camadas ao lado

Sprites de visual novel em camadas no Krita (corpo, roupa, expressão, boca) para usar com layeredimage do Ren'Py, sem exportar um PNG inteiro por combinação.

Ferramenta:KritaRen Py

Sprites de Visual Novel: Poses, Expressões e Camadas

Sprites de visual novel funcionam melhor quando são preparados em camadas: um corpo base, roupas, sobrancelhas, olhos e boca separados, todos no mesmo canvas e com a mesma origem. No Krita você pinta tudo num arquivo só, exporta cada camada como PNG do tamanho do canvas inteiro e monta as combinações no Ren'Py com layeredimage. Assim, 3 poses com 8 expressões não viram 24 PNGs inteiros, e trocar a cor de uma roupa não exige reexportar o personagem em todas as combinações.

Este post cobre o enquadramento, quantas poses fazer, como separar as expressões no Krita, a regra de alinhamento que evita o rosto "pulando" na tela e o código do Ren'Py para montar tudo.

Sprites de visual novel: corpo inteiro, meio corpo ou busto

O enquadramento define o quanto você vai pintar e o quanto a expressão aparece.

  • Busto (cabeça e ombros): a expressão fica grande e clara. Bom para jogos focados em diálogo, com pouca linguagem corporal. Menos área para pintar.
  • Meio corpo (até a cintura ou o quadril): o padrão da maioria das visual novels. Mostra gesto de braço e postura sem exigir pernas.
  • Corpo inteiro: mostra figurino completo e altura relativa entre personagens. O rosto fica pequeno em tela, então a expressão perde força. Dá mais trabalho em cada pose.

Para um primeiro projeto, meio corpo é o melhor custo-benefício. Ele deixa espaço para 2 ou 3 personagens na tela ao mesmo tempo e ainda mostra o rosto bem.

Resolução: o Ren'Py pergunta a resolução ao criar o projeto, e o guia oficial de início rápido usa 1280 x 720 como bom equilíbrio entre tamanho de arquivo e qualidade. Se o seu jogo vai ser em 1920 x 1080, um meio corpo que ocupa a altura da tela precisa de pelo menos 1080 px de altura. Pinte com sobra, em 1,5 a 2 vezes o tamanho final, e reduza no export. Pintar pequeno e ampliar depois sempre borra.

Poses base: quantas fazer para um jogo indie

Pose é o que mais custa, porque cada nova pose é um corpo novo pintado. Um plano realista para indie:

  • Protagonista e par principal: 2 a 3 poses (neutra, braços cruzados ou mão no queixo, gesto expansivo).
  • Personagens secundários: 1 a 2 poses.
  • Figurantes: 1 pose, poucas expressões.

A regra que mais economiza trabalho: mantenha a cabeça no mesmo lugar e no mesmo ângulo em todas as poses de um personagem. Mude braços, ombros e tronco, mas não a cabeça. Assim, as camadas de expressão servem para todas as poses. Se a cabeça inclina numa pose, você precisa de um conjunto de expressões só para ela.

Expressões em camada separada no Krita

Estrutura de camadas no Krita, de baixo para cima, num canvas de 1400 x 2000 px:

  • Grupo pose_normal
    • corpo (pele e anatomia do tronco e dos braços)
    • roupa (o uniforme pintado sobre esse corpo)
  • Grupo pose_cruzada
    • mesma estrutura, com os braços na nova posição
  • base (cabeça e pescoço com a pele pintada, sem olhos, sobrancelhas e boca)
  • Grupo rosto
    • sob_calma, sob_brava, sob_triste (sobrancelhas)
    • olhos_abertos, olhos_fechados, olhos_lado
    • boca_seria, boca_sorriso, boca_aberta, boca_tensa
    • blush (opcional)
  • cabelo_frente (acima das sobrancelhas, se a franja cobre a testa)

Separar sobrancelha, olhos e boca é o que multiplica as expressões. Sobrancelha brava com boca sorrindo vira um sorriso irônico. Olhos fechados com boca sorrindo vira alegria tranquila. Com 3 sobrancelhas, 3 olhos e 4 bocas, você tem dezenas de combinações sem pintar um rosto inteiro.

Para que as camadas combinem, pinte a cabeça na camada base, compartilhada por todas as poses, e cada traço do rosto em camada própria por cima. No export, cada grupo de pose vira um PNG só (corpo e roupa juntos). Use Inherit Alpha nas camadas de sombra da pele, mas não nas camadas de expressão: elas precisam existir sozinhas no export.

Se as expressões em si ainda são difíceis de desenhar, o post sobre expressões faciais para retrato de diálogo foca no desenho de cada emoção.

Mantendo alinhamento entre camadas (mesmo canvas, mesma origem)

Esse é o ponto onde a maioria dos pacotes de sprite quebra. A regra:

  1. Todas as camadas no mesmo canvas. Nunca pinte uma expressão num arquivo separado.
  2. Exporte cada camada no tamanho do canvas inteiro, com transparência ao redor. A boca é pequena, mas o PNG dela tem 1400 x 2000 px, com a boca exatamente onde ela fica no rosto.
  3. Não recorte o PNG ao conteúdo. Se a ferramenta de export oferecer cortar a imagem ao tamanho do conteúdo da camada, deixe desligado.

Arquivos de canvas inteiro parecem desperdício, mas não são: a área transparente comprime muito bem em PNG, e a documentação do layeredimage informa que o Ren'Py recorta internamente as imagens à área não transparente ao carregar, então não é preciso recortar à mão. O que você ganha é que todas as camadas encaixam sozinhas, sem ajuste de posição no código.

Para conferir antes de exportar, ligue e desligue cada camada de boca e olho com a pose ligada. Se algo "pula", foi pintado fora de lugar.

Organizar 4 personagens, 10 poses e 40 expressões com nomes consistentes, alinhados e prontos para o código é o tipo de tarefa que parece simples até o projeto crescer. É onde muita gente que estuda sozinha trava, e onde um processo de arte para jogos, da pintura ao asset funcionando na engine, poupa semanas de retrabalho.

Curso de Arte 2D
Quer fazer a arte do seu jogo?

No curso de Arte 2D para Jogos da CursoGame.Dev você vai do rabisco ao portfólio: personagens, cenários, tilesets, UI e animação, sem precisar saber desenhar.

Conhecer o curso de Arte 2D
Suporte no WhatsAppAcesso vitalícioGarantia de 7 dias

Exportando camadas e montando no Ren'Py com layeredimage

Exportar no Krita. O Krita traz o script Export Layers (menu Tools > Scripts > Export Layers), que exporta as camadas de um documento de forma organizada em PNG. Se ele não aparecer no menu, ative-o em Settings > Configure Krita, na aba Python Plugin Manager. Para poucos arquivos, também dá para desligar todas as camadas menos uma e usar File > Export.

Nomes de arquivo. O Ren'Py consegue encontrar camadas automaticamente quando o nome segue o padrão <imagem>_<grupo>_<atributo>. Para uma personagem chamada Lia:

  • lia_base.png
  • lia_pose_normal.png, lia_pose_cruzada.png
  • lia_sob_calma.png, lia_sob_brava.png, lia_sob_triste.png
  • lia_olhos_abertos.png, lia_olhos_fechados.png
  • lia_boca_seria.png, lia_boca_sorriso.png, lia_boca_aberta.png

Repare que nenhum atributo se repete entre grupos (não existe "neutra" em pose e em boca ao mesmo tempo). Isso importa porque, no show, você escreve só o nome do atributo, e o Ren'Py precisa saber sem ambiguidade a qual grupo ele pertence.

Coloque todos em game/images/ (subpastas são permitidas). Repare no sublinhado: segundo a documentação, nomes com espaço no lugar do sublinhado não são encontrados pelos grupos automáticos.

O código. Num arquivo .rpy do projeto, por exemplo game/personagens.rpy:

define l = Character("Lia")

layeredimage lia:

    group pose auto:
        attribute normal default

    always:
        "lia_base"

    group sob auto:
        attribute calma default

    group olhos auto:
        attribute abertos default

    group boca auto:
        attribute seria default

Como funciona, pela documentação do Ren'Py 8.5:

  • always é uma camada sempre visível, com a imagem indicada.
  • group torna os atributos mutuamente exclusivos: mostrar sorriso esconde a boca anterior.
  • auto faz o Ren'Py procurar os arquivos lia_<grupo>_<atributo> e criar os atributos sozinho. Você só declara à mão o atributo que leva default.
  • default define o que aparece quando nada daquele grupo foi pedido.

A ordem dos grupos no bloco é a ordem de empilhamento: o que vem depois aparece por cima. Por isso a pose (corpo e roupa) vem primeiro, a cabeça (lia_base) por cima dela, e as sobrancelhas, os olhos e a boca por último. Se a franja precisa ficar acima das sobrancelhas, exporte o cabelo da frente como camada própria e declare um always com ele no fim do bloco.

Uso no roteiro:

label start:
    show lia
    l "Você chegou cedo hoje."
    show lia sorriso fechados
    l "Que bom."
    show lia brava cruzada -sorriso
    l "Mas esqueceu o relatório de novo."

show lia sorriso fechados troca só a boca e os olhos. O sinal de menos remove um atributo e o grupo volta ao padrão, então -sorriso devolve a boca seria. As camadas que você não mencionou continuam como estavam, o que deixa o roteiro curto: você descreve só o que muda na expressão a cada fala.

Uma vantagem que aparece mais tarde no projeto: para uma expressão nova, como uma boca assustada, basta pintar lia_boca_assustada.png alinhada ao canvas e jogar na pasta. O grupo auto encontra o arquivo e show lia assustada já funciona, sem tocar no código e sem reexportar nada.

Roupas diferentes para a mesma pose são o próximo nível. Como a roupa depende da posição dos braços, ela precisa de um arquivo por pose, e a documentação do layeredimage descreve condições para mostrar uma camada só quando certos atributos estão ativos. Comece com uma roupa por pose e só adicione esse controle quando o roteiro pedir.

Erros comuns: resolução baixa, recorte com halo branco, pose que não combina com a expressão

Resolução baixa. Sprite pintado em 600 px de altura para um jogo em 1080. Ampliado, ele borra. Pinte no tamanho final ou maior.

Halo branco no recorte. A arte foi pintada sobre um fundo branco e a borda antisserrilhada carregou esse branco. Pinte com fundo transparente desde o início, desligue camadas de fundo antes de exportar e teste o sprite sobre um cenário escuro.

Pose que não combina com a expressão. Braços abertos de alegria com sobrancelha brava. Liste quais combinações o roteiro usa e teste as principais antes de entregar.

Cabeça mudando de lugar entre poses. Cada pose exige um conjunto novo de expressões. Fixe a cabeça.

Nomes inconsistentes. lia_Boca_Sorriso.png e lia_boca-feliz.png no mesmo projeto. Defina o padrão de nome antes de exportar o primeiro arquivo.

Checklist antes de entregar o pacote de sprites

  • Todas as camadas exportadas no tamanho do canvas inteiro
  • Nomes no padrão personagem_grupo_atributo, minúsculos, sem espaço e sem acento
  • Testado contra fundo claro e escuro, sem halo
  • Cada expressão conferida em cada pose
  • Arquivo .kra com camadas guardado junto, para edição futura
  • Bloco layeredimage testado com show de pelo menos 5 combinações

Se você ainda não tem o projeto do Ren'Py montado, o guia de como criar uma visual novel no Ren'Py mostra o caminho do zero ao primeiro diálogo. E para preparar o Krita para esse tipo de trabalho, veja o post de Krita para arte 2D de jogos.

Perguntas frequentes

Qual o tamanho de um sprite de visual novel?

Depende da resolução do projeto e do enquadramento. Num jogo em 1920 x 1080, um sprite de meio corpo que ocupa a altura da tela precisa de pelo menos 1080 px de altura, e muita gente pinta com sobra de 1,5 a 2 vezes para poder reenquadrar. Nunca pinte menor do que o tamanho em que o sprite aparece.

Quantas expressões fazer para um personagem de visual novel?

Para um projeto indie, de 6 a 10 expressões por personagem principal cobrem a maioria das cenas: neutra, feliz, triste, brava, surpresa, envergonhada, pensativa. Com sobrancelha, olhos e boca em camadas separadas, essas peças se combinam em muito mais variações sem pintar rosto inteiro de novo.

O que é layeredimage no Ren'Py?

É uma instrução do Ren'Py que monta um personagem a partir de camadas: uma base sempre visível e grupos de atributos mutuamente exclusivos, como roupa, olhos e boca. Você escreve show com os atributos que quer, e o Ren'Py compõe a imagem na hora, sem precisar de um PNG para cada combinação.

Por que meu sprite tem uma borda branca no jogo?

Normalmente é porque a arte foi pintada ou recortada sobre fundo branco, e os pixels semitransparentes da borda guardaram um pouco desse branco. Pinte sobre fundo transparente, desligue qualquer camada de fundo antes de exportar e confira o sprite contra um fundo escuro.