> For the complete documentation index, see [llms.txt](https://docs.allout.game/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.allout.game/all-out-docs/docs-es/ui/fundamentals.md).

# Fundamentos de UI

***

Agregar UI a tu juego requiere escribir código, pero una vez que aprendes algunos patrones puedes construir interfaces limpias y escalables rápidamente. Esta guía te lleva a través de un tutorial paso a paso que termina con un ejemplo completo de diálogo.

{% hint style="info" %}
Toda la UI de un jugador debe dibujarse dentro de la `ao_late_update` pila de llamadas y envolverse con `is_local_or_server()`. Esto evita que la UI aparezca para el cliente equivocado. No dibujes la UI del jugador desde devoluciones de llamada globales o de componentes que no sean del jugador.
{% endhint %}

En cualquier momento, puedes ir a [Referencia de UI](/all-out-docs/docs-es/ui/ui-reference.md) para ver más patrones y detalles más profundos.

### Paso 1: Crear un punto de entrada de UI

Toda la UI interactiva debe dibujarse desde la `ao_late_update`:

```go
Player :: class : Player_Base {
    ao_late_update :: method(dt: float) {
        if this.is_local_or_server() {
            draw_ui(this);
        }
    }
}
```

### Paso 2: Comenzar desde un rectángulo de pantalla

La UI de pantalla siempre debe derivarse de `UI.get_safe_screen_rect()` o `UI.get_screen_rect()`. Recuerda: (0, 0) es la esquina inferior izquierda y Y crece hacia arriba.

Los tamaños en el espacio de pantalla que se pasan a los ayudantes de rectángulo regulares son **puntos** en un lienzo de referencia de 1080 puntos de alto. El motor escala esos puntos a los píxeles reales del dispositivo, por lo que el mismo diseño mantiene un tamaño relativo consistente en todas las resoluciones.

```go
draw_ui :: proc(player: Player) {
    screen := UI.get_safe_screen_rect();

    // Un panel simple centrado
    panel := screen.center_rect().grow(120, 200, 120, 200);
    UI.quad(panel, core_globals.white_sprite, {0, 0, 0, 0.7});
}
```

### Paso 3: Usar Cut para el diseño

Al distribuir varios elementos, corta espacio de un rectángulo en lugar de posicionar todo desde el mismo origen.

```go
draw_panel_layout :: proc() {
    panel := UI.get_safe_screen_rect().center_rect().grow(140, 220, 140, 220);

    header := panel.cut_top(80);
    footer := panel.cut_bottom(70);
    body := panel;

    UI.quad(header, core_globals.white_sprite, {0.1, 0.1, 0.1, 0.8});
    UI.quad(body, core_globals.white_sprite, {0.05, 0.05, 0.05, 0.8});
    UI.quad(footer, core_globals.white_sprite, {0.1, 0.1, 0.1, 0.8});
}
```

### Paso 4: Añadir texto

Usa la configuración de texto para controlar el tamaño, el color y la alineación.

```go
draw_header_text :: proc(rect: Rect) {
    ts := UI.default_text_settings();
    ts.size = 52;
    ts.color = {1, 1, 1, 1};
    ts.halign = .CENTER;
    ts.valign = .CENTER;

    UI.text(rect, ts, "¡Nueva misión!");
}
```

### Paso 5: Añadir botones

Los botones combinan diseño e interacción. Usa un sprite de botón de los recursos proporcionados por el motor (consulta [Referencia de UI](/all-out-docs/docs-es/ui/ui-reference.md) para más).

```go
draw_button :: proc(rect: Rect) {
    bs := UI.default_button_settings();
    ts := UI.default_text_settings();

    bs.sprite = get_asset(Texture_Asset, "$AO/new/modal/buttons_2/button_2.png");
    bs.press_scaling = 0.35;

    if UI.button(rect, bs, ts, "Aceptar").clicked {
        log_info("¡Aceptado!");
    }
}
```

### Paso 6: Construir un diálogo

Ahora combina todos los pasos en un diseño de diálogo reutilizable.

```go
draw_dialog :: proc(title: string, body: string) {
    screen := UI.get_safe_screen_rect();
    dialog := screen.center_rect().grow(200, 300, 200, 300);

    UI.quad(dialog, core_globals.white_sprite, {0, 0, 0, 0.85});

    content := dialog.inset(30);
    header := content.cut_top(80);
    buttons := content.cut_bottom(90);
    body_rect := content;

    ts := UI.default_text_settings();
    ts.halign = .CENTER;
    ts.valign = .CENTER;

    ts.size = 52;
    UI.text(header, ts, title);

    ts.size = 36;
    UI.text(body_rect, ts, body);

    bs := UI.default_button_settings();
    bs.sprite = get_asset(Texture_Asset, "$AO/new/modal/buttons_2/button_2.png");
    bs.press_scaling = 0.35;

    left := buttons.cut_left(210);
    buttons.cut_left(20);
    right := buttons.cut_left(210);

    if UI.button(left, bs, ts, "Cancelar").clicked {
        log_info("Cancelado");
    }
    if UI.button(right, bs, ts, "Confirmar").clicked {
        log_info("Confirmado");
    }
}
```
