Programando seu jogo
Seu primeiro componente
Crie um arquivo .zig dentro da pasta assets/ do seu projeto. O editor descobre os componentes varrendo esses arquivos. Cada componente é uma struct Zig simples com o marcador is_component:
const engine = @import("engine");
pub const Rotator = struct {
pub const is_component = true;
speed: f32 = 90.0,
pub fn update(self: *Rotator, time: engine.Time) void {
// a API de rotação será aplicada aqui
_ = self;
_ = time;
}
};
Regras para descoberta de componentes:
- A struct deve ser
pube seu nome deve começar com uma letra maiúscula. pub const is_component = true;marca a struct para descoberta. Defina comofalsepara desativá-la temporariamente.- Os nomes dos tipos de componentes devem ser únicos em todo o projeto.
- Tipos de campos suportados:
f32,i32,bool,engine.Vec3,engine.GameObjectRef,engine.ComponentRef,engine.AssetRef.
Depois de salvar o arquivo, clique em Refresh no Asset Browser, selecione um nó na hierarquia e escolha seu componente em Add Component ▾.
Hooks de ciclo de vida
Todos os hooks são opcionais:
| Hook | Chamado quando |
|---|---|
awake(self) |
O objeto é carregado pela primeira vez |
enable(self) |
O objeto se torna ativo |
start(self) |
A cena começa a rodar |
update(self, time: engine.Time) |
A cada frame |
disable(self) |
O objeto se torna inativo |
destroy(self) |
O objeto é destruído |
Cada hook também aceita um parâmetro frame: engine.Frame se você precisar de input, serviços ou do contexto completo da cena — use update(self, frame: engine.Frame) em vez disso.
Consulte a página de Componentes para uma explicação mais completa do ciclo de vida dos nós e de todos os hooks disponíveis.
Usando engine.Time
A struct engine.Time fornece informações sobre o tempo do frame:
| Campo | Tipo | Significado |
|---|---|---|
.delta |
f32 |
segundos desde o último frame |
.elapsed |
f32 |
total de segundos desde que a cena começou |
.frame |
u64 |
contador de frames |
Exemplo — um contador de FPS:
const std = @import("std");
const engine = @import("engine");
pub const FpsDisplay = struct {
pub const is_component = true;
_timer: f32 = 0,
pub fn update(self: *FpsDisplay, time: engine.Time) void {
self._timer += time.delta;
if (self._timer >= 1.0) {
self._timer -= 1.0;
const fps = if (time.delta > 0) 1.0 / time.delta else 0.0;
std.debug.print("FPS: {d:.0}\n", .{fps});
}
}
};
Personalizando valores de campos no Inspector
Qualquer campo público com um valor padrão torna-se um controle editável no painel Inspector. Selecione um nó, expanda seu componente e edite diretamente:
f32→ campo numérico com botões de incremento/decremento.i32→ campo de número inteiro.bool→ caixa de seleção (checkbox).engine.Vec3→ campo de vetor de três eixos com eixos rotulados.engine.GameObjectRef→ alvo de soltura (drop target) — arraste um nó a partir do Scene Hierarchy.engine.ComponentRef→ alvo de soltura — referencie outro componente.engine.AssetRef→ alvo de soltura — referencie qualquer asset.
Campos prefixados com _ (como _timer) são tratados como estado privado de runtime e ficam ocultos no Inspector.
Para definir valores padrão que diferem por instância, altere-os no Inspector após adicionar o componente — o editor grava a sobrescrita (override) no arquivo de cena.
Exemplo
const engine = @import("engine");
pub const Patrol = struct {
pub const is_component = true;
speed: f32 = 2.5,
target: engine.GameObjectRef = .{},
loop: bool = true,
};
Depois de adicionar Patrol a um nó, o Inspector exibe speed, target e loop. Ajuste speed para 5.0, arraste um nó para target e desmarque loop — tudo isso sem tocar no código.