> 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/conceptos-basicos-del-motor/sound-effects.md).

# Sonido y háptica

Usa la API de SFX para reproducir efectos de sonido cortos (clics de la interfaz, pasos, impactos) y audio en bucle simple (bucles ambientales, música).

{% hint style="warning" %}
Actualmente solo **codificados en PCM `.wav`** se admiten archivos. Si tienes un `.wav` que no se importe/reproduzca, conviértelo a PCM usando Audacity (o una herramienta similar).
{% endhint %}

### Inicio rápido (reproducir un sonido)

```go
click := get_asset(SFX_Asset, "sfx/click.wav");

desc := SFX.default_sfx_desc();
SFX.play(click, desc);
```

### Referencia de la API de SFX

```go
SFX_Asset :: class : Asset {}

SFX_Channel :: enum {
    SFX;
    MUSIC;
}

SFX_Desc :: struct {
    specific_to_player: Player;
    positional:       bool;
    position:         v2 #read_only;
    delay:            float;
    volume:           float;
    speed:            float;
    volume_perturb:   float;
    speed_perturb:    float;
    range_multiplier: float;
    loop_timeout:     float;
    entity_to_follow: u64;
    loop:             bool;
    channel:          SFX_Channel;

    set_position :: method(p: v2);
}

SFX :: struct {
    play              :: proc(asset: SFX_Asset, desc: SFX_Desc) -> u64;
    stop              :: proc(id: u64);
    fade_out_and_stop :: proc(id: u64, fade_time: float);
    default_sfx_desc :: proc() -> SFX_Desc;
}
```

### Obtener un `SFX_Asset`

Los efectos de sonido viven en la `res` carpeta de tu juego (a menudo bajo `res/sfx/`).

* Arrastra sonidos desde el **Catálogo de recursos** (el editor los descarga en `res/`)
* O añade tu propio `.wav` archivo en `res/` desde tu máquina local

Luego refiérelos por ruta:

```go
pickup := get_asset(SFX_Asset, "sfx/pickup.wav");
```

{% hint style="warning" %}
Comprueba las rutas de los activos durante el desarrollo. Un activo faltante produce un identificador nulo; `SFX.play` registra una advertencia y devuelve `0`.
{% endhint %}

{% hint style="info" %}
Algunos activos integrados de la plataforma usan `$AO/...` rutas. Por ejemplo: `get_asset(SFX_Asset, "$AO/sfx/FUI Hologram Ping Tone Echoed.wav")`.
{% endhint %}

### Sonidos posicionales (algo 3D)

De forma predeterminada, SFX se reproduce como un sonido “2D” no posicional. Para hacerlo posicional, establece una posición:

```go
play_hit_sfx :: proc(world_pos: v2) {
    hit := get_asset(SFX_Asset, "sfx/hit.wav");

    desc := SFX.default_sfx_desc();
    desc.set_position(world_pos);
    desc.range_multiplier = 1.5;

    SFX.play(hit, desc);
}
```

### Seguir a una entidad (fuente de sonido en movimiento)

Si un sonido debe moverse con una entidad (zumbido de motor, proyectil zumbante, etc.), establece `entity_to_follow`:

```go
start_engine_loop :: proc(entity: Entity) -> u64 {
    engine := get_asset(SFX_Asset, "sfx/engine_loop.wav");

    desc := SFX.default_sfx_desc();
    desc.entity_to_follow = entity.id;
    desc.loop = true;
    desc.channel = .MUSIC; // opcional: trátalo como música/ambiental en lugar de SFX

    // Devuelve un ID que se puede usar para actualizar o detener el sonido.
    return SFX.play(engine, desc);
}
```

{% hint style="info" %}
Si `entity_to_follow` está establecido, normalmente no necesitas llamar también a `set_position` (no pasa nada si lo haces).
{% endhint %}

### Sonidos dirigidos a un jugador

Establece `specific_to_player` cuando el servidor deba seguir el sonido, pero solo un cliente deba oírlo realmente:

```go
play_private_ping :: proc(player: Player) {
    click := get_asset(SFX_Asset, "sfx/click.wav");

    desc := SFX.default_sfx_desc();
    desc.specific_to_player = player;
    desc.volume = 0.7;

    SFX.play(click, desc);
}
```

### Reproducción en bucle + detención

`SFX.play` devuelve un ID que puedes detener más tarde:

```go
sound_id := 0.(u64);

start_loop :: proc() {
    loop := get_asset(SFX_Asset, "sfx/ambience.wav");

    desc := SFX.default_sfx_desc();
    desc.loop = true;
    desc.volume = 0.6;
    desc.loop_timeout = 60; // seguridad: se detiene automáticamente después de ~60 s si se te olvida

    sound_id = SFX.play(loop, desc);
}

stop_loop :: proc() {
    if sound_id != 0 {
        SFX.stop(sound_id);
        sound_id = 0;
    }
}
```

### Variación (recomendada para SFX repetitivos)

Si reproduces el mismo sonido con frecuencia (pasos, recogidas), añade una variación sutil:

```go
desc := SFX.default_sfx_desc();
desc.volume_perturb = 0.2;
desc.speed_perturb  = 0.15;
SFX.play(get_asset(SFX_Asset, "sfx/footstep.wav"), desc);
```

{% hint style="info" %}
Mantén `volume_perturb` / `speed_perturb` sutiles. Valores por encima de \~`0.3` normalmente suenan mal.
{% endhint %}

### Predicción y direccionamiento

Llama a los sonidos de jugabilidad desde la misma ruta predicha compartida que el evento que los causó. El sistema de sonido reconcilia el sonido predicho de un cliente con el resultado del servidor, así que no envuelvas `SFX.play` en `Game.is_server()` o `player.is_local()`.

```go
play_round_victory :: proc(position: v2) {
    desc := SFX.default_sfx_desc();
    desc.set_position(position);
    SFX.play(get_asset(SFX_Asset, "sfx/round_victory.wav"), desc);
}
```

Para un sonido que solo un jugador debe oír, establece `desc.specific_to_player`. Esto mantiene el evento en el código de jugabilidad compartido mientras dirige la reproducción al cliente de ese jugador.

## Hápticos

`Haptics.play_impact` activa la respuesta háptica de impacto en el dispositivo local. Llámala solo para el jugador local:

```go
My_Player :: class : Player_Base {
    play_local_impact :: method() {
        if !is_local() return;

        Haptics.play_impact(.MEDIUM);
    }
}
```

Elige `.LIGHT`, `.MEDIUM`, o `.HEAVY`. Los hápticos actualmente funcionan en iOS. Las llamadas en Android, web, Windows y servidores no hacen nada.

Los hápticos no se sincronizan, no se dirigen ni se deduplican. Actívalos en el punto de interacción local, en lugar de hacerlo desde código de jugabilidad a nivel de escena.
