扫雷游戏 bevy 实践(bevy 0.12)-1-主板选项

时间:2024-01-26 17:42:38

为了实现我们制作完全模块化插件的目标,我们必须首先提供生成选项。我们现在将创建一个很好的配置资源,就像我们在第 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();
}