-
Hey, just getting started with bevy (and ECS), and I love it! I have a pretty simple setup, with a I am just trying to spawn two players to draw them in 2D. This works, but I don't like it, and feel like I may be missing something. Specifically, my questions:
And, here's the code (I can drop code from other files if needed as well) // player.rs
use bevy::prelude::*;
use bevy::color::palettes::basic::RED;
use bevy::color::palettes::basic::BLUE;
use crate::plugins::colorful::Colorful;
use crate::plugins::movable::Movable;
pub(crate) fn plugin(app: &mut App) {
app.add_systems(
Startup,
spawn_players
);
}
// MARK: Components
#[derive(Component, Clone)]
#[require(
Transform,
Movable,
Colorful,
Mesh2d,
MeshMaterial2d<ColorMaterial>,
)]
pub struct Player {
pub name: String, //(can use Name builtin component?)
pub slot: PlayerSlot,
pub color: Color,
pub initial_transform: Transform
}
#[derive(Clone)]
pub enum PlayerSlot {
One,
Two,
Three,
Four
}
// MARK: Systems
fn spawn_players(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>
) {
let player_one = Player {
name: "reed".to_string(),
slot: PlayerSlot::One,
color: Color::from(RED),
initial_transform: Transform::from_xyz(0.0, 0.0, 1.0).with_scale(Vec3::splat(128.))
};
let player_two = Player {
name: "deer".to_string(),
slot: PlayerSlot::Two,
color: Color::from(BLUE),
initial_transform: Transform::from_xyz(0.0, 0.0, 2.0).with_scale(Vec3::splat(64.))
};
commands.spawn((
player_one.clone(),
Colorful(player_one.color),
player_one.initial_transform,
Mesh2d(meshes.add(Rectangle::default())),
));
commands.spawn((
player_two.clone(),
Colorful(player_two.color),
player_two.initial_transform,
Mesh2d(meshes.add(Circle::default())),
));
} P.S., here's the code I'm using to set the material, which is a // colorful.rs
use bevy::prelude::*;
pub(crate) fn plugin(app: &mut App) {
app.add_systems(
PostStartup,
set_material_color
);
}
// MARK: Components
#[derive(Component)]
pub(crate) struct Colorful(pub Color);
impl Default for Colorful {
fn default() -> Self {
Colorful(Color::WHITE)
}
}
// MARK: Systems
// TODO: see if we can set this initially, when first creating the mesh (grabbing from colorful component)
// (rather than having to do it after the fact here)
fn set_material_color(
mut query: Query<(&Colorful, &mut MeshMaterial2d<ColorMaterial>)>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
for (colorful, mut mesh_material) in query.iter_mut() {
// Use the color from the Colorful component to set the material
let color = colorful.0;
mesh_material.0 = materials.add(color);
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
For the initial color of the material, the simplest way to achieve what you want would be to simply initialize the Material with the correct value when spawning the player entity: fn spawn_players(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
// Added
mut materials: ResMut<Assets<ColorMaterial>>,
) {
// ...
commands.spawn((
player_one.clone(),
player_one.initial_transform,
Mesh2d(meshes.add(Rectangle::default())),
// Added
MeshMaterial2d(materials.add(player_one.color)),
));
// ... If you could not do this for some reason, or wanted to defer the color assignment to your players. You could use Observers rather than your pub(crate) fn plugin(app: &mut App) {
app.add_systems(
Startup,
spawn_players
);
// ...
app.add_observer(on_add_colorful);
}
//...
fn on_add_colorful(
trigger: Trigger<OnAdd, Colorful>,
players: Query<(&Colorful, &mut MeshMaterial2d<ColorMaterial>)>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
let (player_color, player_mat) = players.get(trigger.entity()).unwrap();
player_mat.0 = materials.add(player_color.0);
} |
Beta Was this translation helpful? Give feedback.
-
It looks like a few of the fields in your struct Player {
slot: PlayerSlot,
}
impl Player {
fn bundle(name: String, slot: PlayerSlot, color: Color, initial_transform: Transform) -> impl Bundle {
(Player { slot }, Colorful(color), initial_transform)
}
}
fn spawn_players(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>
) {
commands.spawn((
Player::bundle(
"reed",
PlayerSlot::One,
Color::from(RED),
Transform::from_xyz(0.0, 0.0, 1.0).with_scale(Vec3::splat(128.)),
),
Mesh2d(meshes.add(Rectangle::default())),
));
commands.spawn((
Player::bundle("deer",
PlaySlot::Two,
Color::from(BLUE),
Transform::from_xyz(0.0, 0.0, 2.0).with_scale(Vec3::splat(64.)),
)
Mesh2d(meshes.add(Circle::default())),
));
} |
Beta Was this translation helpful? Give feedback.
For the initial color of the material, the simplest way to achieve what you want would be to simply initialize the Material with the correct value when spawning the player entity:
If you could not do this for some reason, or wanted to defer the color assignment to your players. You could use Obser…