Docs Extensões de jogo

Canvas

Desenhe caixas de texto, painéis, barras de progresso, imagens, círculos no chão e rotas com seta sobre a tela do jogo. O runtime desenha tudo a cada frame, sem alterar o estado do jogo, então é seguro em partidas multijogador; funciona por Python, HTTP ou escrevendo direto na memória compartilhada.

Programas externos podem desenhar caixas de texto, painéis, barras de progresso, imagens, círculos no chão e rotas no chão (com seta) sobre a tela do jogo, e o runtime desenha tudo sozinho a cada frame. Serve para o seu próprio HUD, linhas de apoio, avisos, anotações didáticas e painéis de informação para lives.

Canvas ou funções visuais do JASS: qual usar

Canvas (esta página)Funções visuais do JASS
Quem desenhaO próprio runtimeO próprio jogo (texto flutuante, efeitos, painéis, diálogo com retrato…)
Partidas multijogadorSeguro: só desenha na tela desta máquina, sem criar objetos nem alterar o estado do jogoSó partidas solo
EstiloLivre: fontes com suporte a chinês, cantos arredondados, semitransparência, bordas, qualquer cor, imagens locaisEstilo nativo do jogo
Acompanhar coisasSegue unidades, coordenadas do mundo, posições da tela; círculos no chão acompanham o relevoDepende da função
CustoMedido: 0.2 ~ 0.35 ms por frame (9 elementos)Cerca de 13 ms por chamada

Dá para usar os dois juntos: efeitos com cara nativa pelo JASS; painéis, linhas de apoio e avisos personalizados pelo canvas.

Python

c = g.canvas                               # no primeiro uso, o runtime instala o hook de desenho (cerca de 0.1 s)
c.text("title", "Olá, este é o canvas", screen=(40, 110), color=(255, 220, 80),
       bg=(0, 0, 0, 170), border="#C49C40", size=22, bold=True)
c.panel("status", "Companheiro · Luz", ["Humor: feliz", "Abates: 12"], screen=(16, 330))
c.bar("hp", 0.62, unit=hero, lift=260, width=100, height=12, color=(80, 220, 80), text="62%")   # segue a unidade
c.text("tag", "O chefe vai soltar o golpe especial!", unit=boss, lift=320, color=(255, 80, 80), size=22, bold=True)
c.circle("danger", (x, y), 300, color=(255, 60, 60), fill=(255, 60, 60, 60), width=3)          # área de perigo no chão
c.circle("aura", hero, 450, color=(80, 200, 255, 220))                                         # círculo que segue a unidade
c.path("route", [(x1, y1), (x2, y2), (x3, y3)], color=(255, 220, 0), width=5, arrow=True)
c.image("icon", "icon.png", screen=(40, 170), width=64, height=64)
c.remove("danger"); c.hide("tag"); c.clear()   # clear só limpa o que você desenhou
c.expire("tag", 5)                         # some sozinho depois de 5 s
with c.batch(): ...                        # muda vários itens de uma vez, escrevendo na memória compartilhada uma vez só
c.stats()                                  # drawnFrames subindo = está desenhando de verdade

Cada elemento é identificado por uma key: desenhar de novo com a mesma key atualiza o elemento.

Clicável: acrescente clickable=True a caixas de texto e painéis (a cor ao passar o mouse é definida por hover=). Quando o jogador clica, chega um ui.click no fluxo de eventos, com ev.key igual a essa key, e o jogo não recebe esse clique. Botões, cartões de escolha, atalhos de teclado e cliques no chão prontos estão em Interface e entrada.

Posição (uma por elemento):

  • screen=(x, y): pixels da tela; números negativos contam a partir da direita / de baixo; center=True alinha pelo centro;
  • frac=(0.5, 0.1): fração da tela;
  • world=(x, y): coordenadas do mundo;
  • unit=unidade: segue a unidade. Textos e barras no mundo e em unidades ficam com o ponto médio da borda inferior sobre aquele ponto; lift os levanta.

Por padrão, elementos no mundo e em unidades evitam o painel de comando embaixo e o relógio de dia e noite no topo (over_ui=True desenha por cima deles). Cores podem ser (r, g, b), (r, g, b, a), "#RRGGBB" ou "#RRGGBBAA".

MétodoO que desenhaParâmetros comuns
text(key, texto, ...)Caixa de texto; várias linhas com \ncolor, bg fundo (sem ele, transparente), border, size, bold, shadow, width (quebra a linha nessa largura), radius cantos arredondados
panel(key, título, [linhas...], ...)Painel (fundo escuro semitransparente, borda dourada)Os mesmos de text
bar(key, 0..1, ...)Barra de progresso: vida, recarga, conjuraçãowidth, height, color, bg, border, text
image(key, caminho, ...)Imagem local (png / jpg / bmp / gif)width, height (sem eles, tamanho original)
circle(key, unidade ou ponto, raio, ...)Círculo no chão, acompanhando o terrenocolor cor da linha, fill preenchimento (com transparência), width espessura da linha
path(key, [pontos...], ...)Linha poligonal no chãocolor, width, arrow seta no fim; os pontos podem ser coordenadas ou unidades

HTTP (qualquer linguagem)

Backend do Farsight (só escuta na máquina local):

POST /api/instances/20/canvas
{"set": [
   {"key": "banner", "kind": "text", "text": "Canvas via HTTP", "frac": [0.5, 0.12], "center": true,
    "color": "#FFDC50", "bg": [0, 0, 0, 180]},
   {"key": "hp", "kind": "bar", "value": 0.8, "unit": 596125988, "lift": 260, "text": "80%"},
   {"key": "zone", "kind": "circle", "center": 596125988, "radius": 600, "color": [255, 200, 0], "width": 4},
   {"key": "route", "kind": "path", "points": [[-4587, -9092], [-5387, -8792]], "color": "#50C8FF"}
 ],
 "remove": ["old"], "clear": false}

GET  /api/instances/20/canvas        elementos desenhados agora + quantos frames já foram desenhados

kind é o nome do método em Python, e os nomes dos parâmetros também são os mesmos; para unidades, use o endereço addr do snapshot.

Escrevendo direto na memória compartilhada

Também dá para dispensar o Python e o Farsight: envie uma vez o comando semântico canvas_enable (opcode W3P 73), e o runtime cria o bloco de memória compartilhada Local\War3Canvas_<pid>: cabeçalho de 64 bytes + 256 entradas × 112 bytes + pool de 64 KB para textos / pontos. A escrita segue o seqlock (o número de sequência fica ímpar → as entradas e o pool são escritos → o número fica par); o runtime lê uma vez por frame, reaproveita o frame anterior se pegar uma escrita pela metade e devolve o número de frames desenhados, o número de elementos e o contador de falhas. A implementação de referência em Python é sdk/python/w3canvas.py, e as estruturas estão definidas no header do protocolo; veja Protocolo W3P.

Vários programas desenhando ao mesmo tempo

Mods, Farsight, MCP e gateway podem desenhar na mesma partida ao mesmo tempo, mas só existe um canvas. A regra é: cada programa só mexe nos próprios elementos.

  • Antes de escrever, pega-se um lock nomeado, leem-se os elementos existentes, mantêm-se os dos outros, trocam-se os próprios e grava-se tudo de volta;
  • Cada elemento registra quem o desenhou (PID + número sequencial dentro do processo); quando o programa que o desenhou termina, ele é limpo na próxima vez que alguém escrever, e os botões dele deixam de interceptar cliques;
  • Os números dos elementos vêm de um contador compartilhado, então não colidem.

O SDK em Python já faz assim, e clear() também só limpa o que é seu. Se você escrever direto na memória compartilhada, siga essas regras; do contrário, vai apagar o que os outros desenharam. Os detalhes do layout estão em Protocolo W3P.

Medições e cuidados

  • Medido em 2026-09-25 (1920×1080, velocidade 2×): 9 elementos, 0.27 ~ 0.34 ms por frame, cerca de 63 frames / s, 0 falhas; escrever 9 itens leva 6 ms; com o herói andando, os círculos, textos e barras de vida que seguem unidades acompanham sem atraso. A textura só é redesenhada quando o conteúdo muda; mudar só a posição não redesenha.
  • O canvas é desenhado depois da interface do jogo e antes do cursor do mouse: fica por cima das barras de vida, das unidades e da interface do próprio jogo, e o cursor fica por cima dele. Ele evita o painel de comando embaixo e o relógio de dia e noite no topo, mas não evita os painéis do próprio mapa (placar e contagem regressiva no canto superior direito) — não coloque os seus painéis no canto superior direito.
  • Fora de uma partida (menu principal, tela de resultados), elementos posicionados em coordenadas do mundo ou em unidades não são desenhados; os que estão numa posição da tela continuam aparecendo.
  • O círculo no chão projeta cada um dos 64 pontos da circunferência no terreno, então, quando o terreno tem altos e baixos, a forma acompanha o relevo — e isso está certo: ele é desenhado sobre o chão de verdade.
  • Na primeira ativação, é preciso instalar o hook e pré-aquecer as fontes, o que leva cerca de 1 segundo; nesse intervalo, os elementos de texto ainda não aparecem, mas círculos e linhas sim.
  • Se ocorrer uma falha durante o desenho, nada mais é desenhado nesta sessão (a mesma proteção dos balões sobre a cabeça), e faults em stats() passa a 1.
  • Textos, caminhos de imagem e pontos somam no máximo 64 KB, com até 256 elementos; o caminho da imagem precisa ser um caminho local que o processo do jogo consiga ler.

O painel de status do companheiro de IA é desenhado com o canvas: barra de vida, o que ele está fazendo, humor, abates e número de curas.