为了实现我们制作完全模块化插件的目标,我们必须首先提供生成选项。我们现在将创建一个很好的配置资源,就像我们在第 1 部分
中看到的 bevy WindowDescriptor
一样。
在我们的插件中创建一个模块board_options
├── Cargo.toml
└── src
├── components
│ ├── coordinates.rs
│ └── mod.rs
├── lib.rs
└── resources
├── board_options.rs
├── mod.rs
├── tile.rs
└── tile_map.rs
并将其添加到mod.rs
文件中:
// ..
pub use board_options::*;
mod board_options;
我们想要以下选项:
- 所有图块地图的选项(宽度、高度和炸弹数量)
- 平铺精灵之间的自定义填充间距
- 自定义图块尺寸或窗口自适应尺寸
- 自定义棋盘世界位置或窗口居中并可选偏移
- 可选的安全无遮盖起始区
好多啊 !
是的,但是越多越好!我们开工吧:
// board_options.rs
use bevy::prelude::Vec3;
use serde::{Deserialize, Serialize};
/// Tile size options
/// 图块大小选项
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TileSize {
/// Fixed tile size
/// 固定图块大小
Fixed(f32),
/// Window adaptative tile size
/// 窗口自适应图块大小
Adaptive { min: f32, max: f32 },
}
/// Board position customization options
/// 棋盘位置自定义选项
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum BoardPosition {
/// Centered board
/// 居中的棋盘
Centered { offset: Vec3 },
/// Custom position
/// 自定义位置
Custom(Vec3),
}
/// Board generation options. Must be used as a resource
/// 棋盘生成选项。必须作为资源使用
// We use serde to allow saving option presets and loading them at runtime
// 我们使用 serde 来支持保存选项预设并在运行时加载它们
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BoardOptions {
/// Tile map size
/// 图块地图大小
pub map_size: (u16, u16),
/// bomb count
/// 炸弹数量
pub bomb_count: u16,
/// Board world position
/// 棋盘世界位置
pub position: BoardPosition,
/// Tile world size
/// 图块世界大小
pub tile_size: TileSize,
/// Padding between tiles
/// 图块间填充
pub tile_padding: f32,
/// Does the board generate a safe place to start
/// 棋盘是否生成一个安全的起始地方
pub safe_start: bool,
}
这看起来很复杂,但如果我们实现良好的Default
实现,我们的选项将非常易于使用
// board_options.rs
impl Default for TileSize {
fn default() -> Self {
Self::Adaptive {
min: 10.0,
max: 50.0,
}
}
}
impl Default for BoardPosition {
fn default() -> Self {
Self::Centered {
offset: Default::default(),
}
}
}
impl Default for BoardOptions {
fn default() -> Self {
Self {
map_size: (15, 15),
bomb_count: 30,
position: Default::default(),
tile_size: Default::default(),
tile_padding: 0.,
safe_start: false,
}
}
}
让我们将新资源注册到应用程序:
// main.rs
+ use board_plugin::resources::BoardOptions;
fn main() {
let mut app = App::new();
// Window setup
// 窗口设置
app.insert_resource(WindowDescriptor {
title: "Mine Sweeper!".to_string(),
width: 700.,
height: 800.,
..Default::default()
})
// Bevy default plugins
// Bevy 默认插件
.add_plugins(DefaultPlugins);
#[cfg(feature = "debug")]
// Debug hierarchy inspector
// 调试层次结构检视器
app.add_plugin(WorldInspectorPlugin::new());
+ // Board plugin options
// 棋盘插件选项
+ app.insert_resource(BoardOptions {
+ map_size: (20, 20),
+ bomb_count: 40,
+ tile_padding: 3.0,
+ ..Default::default()
+ })
.add_plugin(BoardPlugin)
// Startup system (cameras)
// 启动系统(摄像机)
.add_startup_system(camera_setup);
// Run the app
// 运行应用程序
app.run();
}