尝试用 Bevy 渲染棋盘

问题描述 投票:0回答:1

我正在尝试在 Bevy 中渲染一个棋盘(或制作一个基于网格的系统)。

我有这个组件:

#[derive(Debug, Component)]
/// Defines a single grid.
/// As `Cell` is a term used in Rust terminology, Grid is a better way to refer to this.
pub(crate) struct Grid(u8, u8);

impl Grid {
    pub(crate) fn new(x: u8, y: u8) -> Self {
        Self(x, y)
    }

    pub(crate) fn x(&self) -> u8 {
        self.0
    }

    pub(crate) fn y(&self) -> u8 {
        self.1
    }

    pub(crate) fn indices(&self) -> (u8, u8) {
        (self.x(), self.y())
    }
}

还有这些启动系统:

pub(crate) fn init_grids(mut commands: Commands) {
    debug!("Initializing grids...");

    //| initializing grids up to u8::MAX
    for x in 0..u8::MAX {
        for y in 0..u8::MAX {
            commands.spawn(Grid::new(x, y));
        }
    }
}

pub(crate) fn paint_grids(
    grid_query: Query<&Grid>,
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<ColorMaterial>>,
) {
    debug!("Painting grids...");

    //| iterating over each grid
    for grid in grid_query.iter() {
        //| unpack x and y val of the grid
        let (grid_x, grid_y) = grid.indices();

        //| choose color black or white based on grid x and y value
        let color = if (grid_x + grid_y) % 2 == 0 {
            Color::BLACK
        } else {
            Color::WHITE
        };

        //| define grid's pixel position
        let pos_x = grid_x * GRID_SIZE;
        let pos_y = grid_y * GRID_SIZE;

        //| create a rectangle
        let mesh_handler =
            Mesh2dHandle(meshes.add(Rectangle::new(GRID_SIZE as f32, GRID_SIZE as f32)));

        //| draw the rectangle
        commands.spawn(MaterialMesh2dBundle {
            mesh: mesh_handler,
            material: materials.add(color), //| define its color
            transform: Transform::from_xyz(pos_x as f32, pos_y as f32, 0.0), //| define its pos in the screen
            ..Default::default()
        });
    }
}

...其中

GRID_SIZE
u8
常数,其值为
16

DefaultPlugins
Camera2dBundle
已初始化,但我看到的是纯灰色屏幕。

尽管初始化了相机和默认插件并添加了系统,但它仍呈现空白屏幕。

我对 Bevy 有点陌生(不是 Rust),所以我想知道我是否在这里遗漏了一些东西。

提前致谢。


环境

  • 贝维0.13.2
  • 铁锈1.76.0

更新1

项目有一个

CorePlugin
,用于设置所有其他插件。目前,它只有另一个名为
GridPlugin
的插件。

一些可能相关的文件:

// main.rs
use bevy::app::App;
use oxidized_pixel_dungeon::core::CorePlugin;

fn main() {
    App::new().add_plugins(CorePlugin).run();
}
// core/mod.rs
use bevy::{
    app::{Plugin, PluginGroup, Startup},
    core_pipeline::core_2d::Camera2dBundle,
    ecs::system::Commands,
    log::LogPlugin,
    utils::tracing::field::debug,
    DefaultPlugins,
};

use crate::grid::GridPlugin;

pub struct CorePlugin;

impl Plugin for CorePlugin {
    fn build(&self, app: &mut bevy::prelude::App) {
        let default_plugins = DefaultPlugins.set(if cfg!(debug_assertions) {
            LogPlugin {
                level: bevy::log::Level::TRACE,
                filter: "info,wgpu_core=warn,wgpu_hal=warn,oxidized_pixel_dungeon=trace".into(),
                ..Default::default()
            }
        } else {
            LogPlugin {
                level: bevy::log::Level::INFO,
                filter: "info,wgpu_core=warn,wgpu_hal=warn".into(),
                ..Default::default()
            }
        });

        app.add_plugins(default_plugins)
            .add_systems(Startup, init_system)
            .add_plugins(GridPlugin);
    }
}

fn init_system(mut commands: Commands) {
    debug("Running CorePlugin::init_system");
    commands.spawn(Camera2dBundle::default());
}
// grid/mod.rs
pub mod components;
pub(crate) mod constants;
mod systems;

use bevy::{
    app::{Plugin, Startup},
    asset::Assets,
    ecs::system::{Commands, ResMut},
    log::debug,
    math::primitives::Rectangle,
    render::{color::Color, mesh::Mesh},
    sprite::{ColorMaterial, MaterialMesh2dBundle, Mesh2dHandle},
    transform::components::Transform,
};

use crate::grid::systems::{init_grids, paint_grids};

pub(super) struct GridPlugin;

impl Plugin for GridPlugin {
    fn build(&self, app: &mut bevy::prelude::App) {
        debug!("Initializing GridPlugin...");
        app.add_systems(Startup, (init_grids, paint_grids));
    }
}
rust bevy
1个回答
0
投票

您的问题是两个系统

paint_grid
init_grid
的组合。 它们都在启动计划中只运行一次,这意味着游戏的第一帧。

// init_grids
//...
commands.spawn(Grid::new(x,y))
// ...

向世界发出命令,在帧末尾插入带有

Grid
组件的实体。但是,这意味着该实体仅从第 2 帧开始可见。 因此
grid_query: Query<&Grid>
在第 1 帧处为空。

解决方案

最简单的解决方案是将

init_grids
pain_grids
合并到单个系统。就目前情况而言,无论如何都不需要两个单独的系统。

另一种方法是在

paint_grids
计划中运行
Update
并查询新添加的
Grid
组件。

// GridPlugin
app.add_systems(Startup, init_grids)
.add_systems(Update, paint_grids)

// paint_grids
fn pain_grids(
grid_query: Query<&Grid, Added<Grid>>,
//...
) {
//...
}

每当将新的网格组件插入到世界中时,都会添加网格实体。您可能会担心这可能会很昂贵,因为我们查询每一帧,但实际上它非常便宜。

我也不会将视觉/网格和

Grid
组件分成两个不同的实体。这样做没有什么理由,并且可能会使同步有点乏味

© www.soinside.com 2019 - 2024. All rights reserved.