11个版本 (4个破坏性更新)

0.5.1 2024年7月18日
0.5.0 2024年7月17日
0.4.1 2024年7月8日
0.3.1 2024年6月4日
0.1.2 2024年3月13日

#117 in 游戏开发

Download history 197/week @ 2024-05-06 17/week @ 2024-05-13 9/week @ 2024-05-20 139/week @ 2024-06-03 6/week @ 2024-06-10 125/week @ 2024-07-01 144/week @ 2024-07-08 219/week @ 2024-07-15 14/week @ 2024-07-22 35/week @ 2024-07-29

每月275次下载

MIT/Apache

110KB
2K SLoC

bevy_trenchbroom

crates.io docs.rs

全Bevy集成TrenchBroom,支持加载.map文件,使用代码定义TrenchBroom游戏配置和实体定义等!

(我制作的测试地图,使用bevy_trenchbroom加载)

如何使用

首先将bevy_trenchbroom添加到您的项目中:cargo add bevy_trenchbroom

然后,像这样简单地添加带有提供的TrenchBroomConfigTrenchBroomPlugin到您的应用程序中

use bevy::prelude::*;
use bevy_trenchbroom::prelude::*;

fn main() {
    App::new()
        // ...
        // TrenchBroom maps use repeating textures, and currently by default bevy's images don't repeat.
        // Use `repeating_image_sampler` to easily create a sampler for this that is optionally filtered.
        .add_plugins(DefaultPlugins.set(ImagePlugin { default_sampler: repeating_image_sampler(false) }))
        .add_plugins(TrenchBroomPlugin::new(trenchbroom_config()))
        // ...
    ;
}

// Because of how big it tends to get, I recommend putting your `TrenchBroomConfig` in a separate function, most likely in its own module.
fn trenchbroom_config() -> TrenchBroomConfig {
    TrenchBroomConfig::new("example_game") // <- The name of your game
        // Here you can customize the resulting game configuration with a builder-like syntax
        .entity_scale_expression("scale")
        // ...


        // You can define entity definitions here with a rust-like macro-powered domain specific language, these are written to your game's FGD file, and used for spawning entities

        // It's standard practice to make the first defined entity your `worldspawn`
        .entity_definitions(entity_definitions! {
            /// World Entity
            Solid worldspawn {} |world, entity, view| {
                // This is the code to spawn the entity into the world, note that the TrenchBroomConfig resource is not available in this scope
                // If you need to access the TrenchBroomConfig, access it via view.tb_config
                view.spawn_brushes(world, entity, BrushSpawnSettings::new().smooth_by_default_angle().pbr_mesh());
                // Here, we also call smooth_by_default_angle(), which smooths the normals of connected surfaces curving less than a default threshold
            }

            // Some useful base classes
            Base angles {
                /// Pitch Yaw Roll (Y Z X)
                angles: Vec3,
            }
            Base target_name {
                /// Name
                targetname: "target_source", // A custom type for a FGD property
            }
            Base target {
                /// Target
                target: "target_destination",
            }
            Base parent {
                parent: "target_destination",
            }

            // A more advanced example of a prop class

            /// A GLTF model with no physics
            Point prop( model({ "path": model, "skin": skin, "scale": {{ scale == undefined -> $tb_scale$, scale * $tb_scale$ }} }) ) : angles, target_name, parent {
                model: "studio",
                scale: f32 = 1.,
                /// Title : Description
                skin: u32 = 0,
                collision_type: [
                    "model" : "Uses colliders defined in the model, or none if the model doesn't have any",
                    "bounding_box" : "Mesh bounding box collider",
                    "none": "No collision",
                ] = "model",
                enable_shadows: bool = true,
            } |world, entity, view| {
                let scene = world.resource::<AssetServer>().load(format!("{}#Scene0", view.get::<String>("model")?));

                world.entity_mut(entity).insert((
                    SceneBundle {
                        scene,
                        ..default()
                    },
                    TrenchBroomGltfRotationFix,
                ));
            }
        })
}

然后要访问TrenchBroom中的配置,在您的应用程序的某个位置调用TrenchBroomConfig::write_folder。示例

use bevy::prelude::*;
use bevy_trenchbroom::prelude::*;

// app.add_systems(Startup, write_trenchbroom_config)

fn write_trenchbroom_config(config: Res<TrenchBroomConfig>) {
    if let Err(err) = config.write_folder("<folder_path>") {
        error!("Could not write TrenchBroom config: {err}");
    }

    // This will write <folder_path>/GameConfig.cfg, and <folder_path>/example_game.fgd
}

这将在您的应用程序启动时写入它,但根据您要执行的操作,您可能需要在其他时间写入。

写入后,需要将文件放入的文件夹是您的TrenchBroom游戏配置文件夹,您可以在此处找到其路径。

材质属性

bevy_trenchbroom使用材质属性系统来确保纹理在游戏中正确显示。在您的纹理旁边(textures/example.png),添加一个同名的toml文件(textures/example.toml)。
在此文件中,您可以定义材质的某些属性,包括用户定义的属性。(参见MaterialProperties文档

为了避免渲染或用于trimesh碰撞的过多多边形,建议在您的纹理根目录中包含__TB_empty.toml,内容如下

render = false
collide = false

这将使创建刷子网格时忽略没有纹理的任何面。

加载地图

现在您已经设置好了环境,并假设已经创建好了地图,加载地图相当简单:只需在实体中放入一个 Handle<Map> 组件,它将使用 spawn_maps 系统生成地图。
您也可以使用 MapBundle 更容易地完成此操作。

use bevy::prelude::*;
use bevy_trenchbroom::prelude::*;

// app.add_systems(Startup, spawn_test_map)

fn spawn_test_map(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn(MapBundle {
        map: asset_server.load("maps/test.map"),
        ..default()
    });
}

地图支持热重载资产,意味着迭代时间几乎是瞬间的。

多人游戏

如果您正在制作多人游戏,请在创建配置时调用 is_server,并传递当前运行的应用程序是否为服务器。

然后,如果您的网络解决方案具有唯一标识符类型,您可以为您配置定义一个自定义的全局生成器,它添加此类标识符。

物理/碰撞

bevy_trenchbroom 支持 bevy_rapier3davian3d,以便在生成画笔时轻松添加碰撞器。

首先,在 crate 上启用 rapieravian 功能,然后在生成画笔时在您的 BrushSpawnSettings 上调用 convex_collidertrimesh_collider 来创建相应类型的碰撞器。

已知问题

如果您正在使用 GLTF 模型,您可能会注意到,与 Bevy 相比,在 TrenchBroom 中它们旋转了 90 度。为了解决这个问题,请在它的生成器中将 TrenchBroomGltfRotationFix 组件添加到您的实体中。

可能的未来计划

  • entity_definitions! 宏中支持表达式语言
  • 减少同步执行的文件系统调用次数
  • 实体 IO
  • 地图 GLTF 导出
  • BSP 加载

如果您想尝试解决这些问题或提出解决方法,非常欢迎提交 PR/issue!

支持的 Bevy && TrenchBroom 版本

Bevy bevy_trenchbroom TrenchBroom
0.14 0.4 2024.1
0.13 0.1-0.3 2024.1

注意:它很可能适用于除 bevy_trenchbroom 版本之外的 TrenchBroom 版本。

此 crate 仍在早期开发中,确实缺少一些功能。如果您的用例未被覆盖,请提交 issue!

依赖项

~43–81MB
~1.5M SLoC