> 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-zh/jiao-ben-bian-xie/random-math-and-more.md).

# 随机、数学及更多

本页汇集了一些“你会经常用到”的工具：RNG、格式化、时间，以及在大多数游戏中都会用到的几个核心子系统。

{% hint style="info" %}
如果你在找数组/切片，请参见 [数组和集合](/all-out-docs/docs-zh/jiao-ben-bian-xie/arrays-and-collections.md).
{% endhint %}

## 随机数（RNG）

随机性使用显式的 `u64` 种子。通过 `ref` 这样它会更新。

```go
rng: u64 = rng_root_seed();
// 或者按实体确定性生成：
// rng: u64 = rng_seed(entity.id);

// 范围值是包含端点的
roll := rng_range_int(ref rng, 1, 10);
chance := rng_range_float(ref rng, 0, 1);

// 随机点与洗牌
offset := rng_disk(ref rng, 0.5, 2.0);
spawn_points: [..]v2;
spawn_points.append({0, 0});
spawn_points.append({4, 0});
rng_shuffle(ref rng, spawn_points);
```

{% hint style="warning" %}
游戏玩法中的随机性必须运行在共享的预测游戏路径中。请从以下开始： `rng_root_seed()` 或其他稳定种子；不要使用仅本地数据为游戏玩法播种。
{% endhint %}

## 数学函数

常用数学辅助函数：

```go
angle_sin := sin(x);
angle_cos := cos(x);
angle := atan2(dir.y, dir.x);
degrees := to_degrees(angle);
radians := to_radians(degrees);

result := pow(2.0, 3.0);   // 8.0
root := sqrt(16.0);        // 4.0

value := lerp(0.0, 100.0, 0.5);  // 50.0
clamped := clamp(value, 0.0, 10.0);
stepped := linear_step(0.0, 1.0, value);

absolute := abs(-5);
minimum := min(5, 10);
maximum := max(5, 10);
direction_sign := sign(-12);

len := length(v);
len_sq := length_squared(v);
normalized := normalize(v);
facing := dot(normalized, {1, 0});
```

## 字符串格式化

使用 `%` 带参数数组的占位符：

```go
format_string("Value: %", {42});
format_string("health: 100%");
```

如果需要让参数紧挨着百分号（或另一个参数），请使用 `%0` 作为……的别名 `%`:

```go
hp := 67;
format_string("health: %0%%", {hp}); // "health: 67%"
```

对于小数四舍五入，请使用 `format_float`:

```go
value := 3.14159;
format_string("pi: %", {format_float(value, decimals=2)}); // "pi: 3.14"
```

常用字符串辅助函数：

```go
clean := string_trim("  hello  ");
parts := string_split("a,b,c", ",");
name_lower := to_lower(player.get_username());
name_upper := to_upper("ready");
short := string_substring("abcdef", 1, 3); // "bcd"
```

## 日志

日志也遵循相同的格式化规则：

```go
log_info("Name: %, age: %", {player.get_username(), 12});
```

## 时间

```go
current_time := get_time();       // 自游戏开始以来的浮点秒数
frame := get_frame_number();      // 当前帧编号
now_ns := get_nanoseconds_since_epoch();
utc := get_utc_datetime();
```

## 音效

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

desc := SFX.default_sfx_desc();
desc.entity_to_follow = entity.id;
desc.delay = 0.25;

sound_id := SFX.play(sound, desc);
SFX.stop(sound_id);
```

{% hint style="warning" %}
请从共享的游戏玩法路径调用游戏音效。引擎会协调预测播放。对于只应由一名玩家听到的声音，请设置 `desc.specific_to_player = player`; 不要包装 `SFX.play` 包裹在 `is_local()`.
{% endhint %}

## 经济快速入门（货币）

经济货币是 **每个玩家** 和 **自动持久保存**.

```go
ao_before_scene_load :: proc() {
    coin_icon := get_asset(Texture_Asset, "ui/coin.png");
    Economy.register_currency("Coins", coin_icon);
}

Economy.deposit_currency(player, "Coins", 10);
coins := Economy.get_balance(player, "Coins");

COST :: 50;
if Economy.can_withdraw_currency(player, "Coins", COST) {
    Economy.withdraw_currency(player, "Coins", COST);
}
```

存入和取出金额必须为非负数。

参见 [经济系统](/all-out-docs/docs-zh/shu-ju-yu-chi-jiu-hua/economy.md) 请参阅完整指南。
