code开始使用 CSL

CSL 是 All Out 的自定义编程语言,旨在让编写多人游戏像创建单人游戏一样简单。

CSL 是 All Out 的自定义脚本语言。它是静态类型的,感觉最类似于 Go/Odin —— 除了 游戏状态会自动从服务器同步到客户端.

circle-info

你不需要编写 RPC、SyncVars 或自定义复制。专注于玩法逻辑;平台为你处理网络。

你的第一个脚本(main.csl)

当你创建一个新项目时,All Out 会在你的项目中生成一个 main.csl 在你项目的 scripts/ 文件夹。

import "core:ao"

// ============================================================================
// 全局生命周期
// ============================================================================

ao_before_scene_load :: proc() {
    // 注册物品定义、货币等。
    // 在场景创建之前运行。
}

ao_start :: proc() {
    // 场景开始时调用一次。
}

ao_update :: proc(dt: float) {
    // 每帧调用。
}

ao_late_update :: proc(dt: float) {
    // 在 ao_update 之后每帧调用。
}

// ============================================================================
// 玩家生命周期
// ============================================================================

Player :: class : Player_Base {
    ao_start :: method() {
    }

    ao_update :: method(dt: float) {
    }

    ao_late_update :: method(dt: float) {
    }

    ao_end :: method() {
    }
}

例如,记录每个玩家加入时的消息:

如果你想更深入地了解这些函数何时运行,请参见 游戏/帧 生命周期.

导入

你的 main.csl 应当导入 core:ao 以及你创建的任何文件夹(例如 ui/, abilities/,等等)。

circle-exclamation

声明(变量和常量)

声明将名称绑定到一个值。

变量

可以省略 <type><expression>

常量

常量使用 :: 并且必须是编译时常量:

这是无效的(因为 一个 不是编译时常量):

类型

原始类型

  • 有符号整数: s8, s16, s32, s64

  • 无符号整数: u8, u16, u32, u64

  • 布尔值: b8, b16, b32, b64

  • 浮点数: f32, f64

  • 别名:

    • int == s64

    • uint == u64

    • bool == b8

    • float == f32

  • 向量: v2, v3, v4

  • string

  • typeid

  • 任何

向量类型

v2, v3,以及 v4 具有 .x, .y, .z, .w 浮点字段:

结构体和类

结构体是 值类型 (赋值时拷贝)。类是 引用类型 (使用 new).

结构体(值类型)

类(引用类型)

继承

foo.position = {12, 34};

dog.breed = "Labrador";

过程与方法proc)

result := add(2, 4); // 6

op = proc(a: int, b: int) -> int { return a * b; };method)

使用 方法( method() 在结构体/类内部。方法有一个隐式的 this

dog->bark();

使用 . 字段访问与方法调用 -> 字段使用

circle-info

entity->set_local_scale({2, 2});

如果一个过程的第一个参数类型与接收者类型匹配,则任何过程都可以作为“方法”被调用。这是 CSL 的常见模式。

数组

  • 固定数组: CSL 有一些你会经常使用的“类似数组”的类型:

  • 切片 / 管理数组: []T [4]int

  • 动态数组: [..]T (可调整大小的列表)

(通常用作对数组的“只读视图”) 动态数组暴露, .data,以及 .count.capacity

log_info("first: %", {numbers[0]}); 数组与集合.

完整指南(包括删除模式),请参见

控制流

// 一切正常

return {1, 1, 1, 1};

类型转换

使用 expr.(T) enemy->update_ai();

c := b.(float); // 123.0 ref 按引用传递:

(首选) 当你需要修改参数时, ref 优先使用

update_position(ref my_pos, {10, 5}, 0.16);

回调:函数指针 + userdata(无闭包) CSL 没有闭包。内联 proc(...) { ... }

不能捕获外部变量。 要携带上下文,请将回调与一个 userdata: Object

tracker.count += 1;

typeid 类型信息(类型作为值)

c := default_of([4]int); // {0, 0, 0, 0}

  • 最佳实践(All Out 中的 CSL) 避免全局玩法状态。 Player 多个玩家连接 —— 将每个玩家的状态存储在

  • 上,而不是其他地方。 使用 将装饰性逻辑与玩法逻辑分离。 is_local() 用于仅本地的 UI/粒子,和 is_local_or_server()

  • 用于必须在服务器和本地客户端上运行的玩法输入。 移动优先的默认设置。

  • 除非你的游戏明确面向 PC,否则不要依赖键盘/鼠标输入。如果你对语法或 API 不确定, 请检查项目中生成的 文件夹(它包含最新的 core.csl 表面)。

最后更新于