You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
196 lines
6.1 KiB
Rust
196 lines
6.1 KiB
Rust
use crate::prelude::*;
|
|
|
|
/// Menu Plugin; empty struct for Plugin impl
|
|
pub(crate) struct DicePlugin;
|
|
|
|
impl Plugin for DicePlugin {
|
|
fn build(&self, app: &mut App) {
|
|
app.add_event::<DiceAction>();
|
|
app.add_systems(Startup, init_dice_ui);
|
|
app.add_systems(Startup, init_dice);
|
|
app.add_systems(
|
|
Update,
|
|
button_emit_event::<DiceAction>.run_if(any_component_changed::<Interaction>),
|
|
);
|
|
app.add_systems(Update, draw_die.run_if(any_component_changed::<Die>));
|
|
app.add_systems(Update, roll_die.run_if(on_event::<DiceAction>()));
|
|
app.add_systems(Update, move_die.run_if(on_event::<KeyboardInput>()));
|
|
}
|
|
}
|
|
|
|
#[derive(Event, Clone)]
|
|
enum DiceAction {
|
|
Roll,
|
|
}
|
|
|
|
/// Create UI for the Dice game at startup
|
|
fn init_dice_ui(mut commands: Commands) {
|
|
commands
|
|
.spawn((GameChoice::Dice, MenuState::Closed, Pickable::IGNORE))
|
|
.add(UiContainer)
|
|
.with_children(|parent| {
|
|
parent
|
|
.spawn_empty()
|
|
.add(UiTitle { text: "Dice" })
|
|
.add(UiStyle(Style {
|
|
position_type: PositionType::Absolute,
|
|
top: Val::Px(0.0),
|
|
left: Val::Px(0.0),
|
|
margin: UiRect::all(Val::Px(5.0)),
|
|
border: UiRect::all(Val::Px(1.0)),
|
|
..default()
|
|
}));
|
|
|
|
parent
|
|
.spawn((SetState(GameChoice::None), SetState(MenuState::Open)))
|
|
.add(UiButton { label: "Menu" })
|
|
.add(UiStyle(Style {
|
|
position_type: PositionType::Absolute,
|
|
top: Val::Px(0.0),
|
|
right: Val::Px(0.0),
|
|
margin: UiRect::all(Val::Px(5.0)),
|
|
padding: UiRect::all(Val::Px(5.0)),
|
|
border: UiRect::all(Val::Px(1.0)),
|
|
..default()
|
|
}));
|
|
|
|
parent
|
|
.spawn(EmitEvent(DiceAction::Roll))
|
|
.add(UiButton { label: "Roll" })
|
|
.add(UiStyle(Style {
|
|
position_type: PositionType::Absolute,
|
|
margin: UiRect::all(Val::Px(5.0)),
|
|
padding: UiRect::all(Val::Px(5.0)),
|
|
border: UiRect::all(Val::Px(1.0)),
|
|
..default()
|
|
}));
|
|
});
|
|
}
|
|
|
|
fn init_dice(
|
|
mut meshes: ResMut<Assets<Mesh>>,
|
|
mut materials: ResMut<Assets<ColorMaterial>>,
|
|
mut commands: Commands,
|
|
) {
|
|
[
|
|
["a", "b", "c", "d", "e", "f"],
|
|
["g", "h", "i", "j", "k", "l"],
|
|
["m", "n", "o", "p", "q", "r"],
|
|
]
|
|
.into_iter()
|
|
.enumerate()
|
|
.for_each(|(idx, set)| {
|
|
commands
|
|
.spawn((
|
|
GameChoice::Dice,
|
|
MenuState::Closed,
|
|
Die::new(set),
|
|
PickableBundle { ..default() },
|
|
On::<Pointer<Drag>>::target_component_mut::<Transform>(|m, transform| {
|
|
transform.translation.x += m.delta.x;
|
|
transform.translation.y -= m.delta.y;
|
|
}),
|
|
))
|
|
.insert(MaterialMesh2dBundle {
|
|
mesh: meshes
|
|
.add(Rectangle {
|
|
half_size: Vec2::splat(32.0),
|
|
})
|
|
.into(),
|
|
material: materials.add(Color::PINK),
|
|
..default()
|
|
})
|
|
.insert(Text2dBundle {
|
|
text: Text::from_section(
|
|
"",
|
|
TextStyle {
|
|
color: Color::BLACK,
|
|
font_size: 32.0,
|
|
..default()
|
|
},
|
|
),
|
|
..default()
|
|
})
|
|
.insert(Transform::from_xyz(idx as f32 * 100.0, 100.0, 0.0));
|
|
});
|
|
}
|
|
|
|
fn draw_die(mut q: Query<(&Die, &mut Text), Changed<Die>>) {
|
|
q.iter_mut().for_each(|(d, mut t)| {
|
|
info!("Dice currently reads {:?}", d.get());
|
|
t.sections[0].value.replace_range(.., d.get());
|
|
});
|
|
}
|
|
|
|
fn roll_die(mut r: EventReader<DiceAction>, mut q: Query<&mut Die>, time: Res<Time>) {
|
|
r.read().for_each(|msg| match msg {
|
|
DiceAction::Roll => {
|
|
q.iter_mut().for_each(|mut d| {
|
|
d.roll((time.elapsed_seconds() * 1000.0) as usize);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
fn move_die(
|
|
mut e: EventReader<KeyboardInput>,
|
|
mut q: Query<&mut Transform, With<Die>>,
|
|
time: Res<Time>,
|
|
) {
|
|
e.read().for_each(
|
|
|KeyboardInput {
|
|
key_code, state, ..
|
|
}| {
|
|
match state {
|
|
ButtonState::Pressed => {
|
|
q.iter_mut().for_each(|mut t| {
|
|
match key_code {
|
|
KeyCode::ArrowLeft => {
|
|
t.translation -= Vec3::X * time.delta_seconds() * 1000.0
|
|
}
|
|
KeyCode::ArrowRight => {
|
|
t.translation += Vec3::X * time.delta_seconds() * 1000.0
|
|
}
|
|
KeyCode::ArrowDown => {
|
|
t.translation -= Vec3::Y * time.delta_seconds() * 1000.0
|
|
}
|
|
KeyCode::ArrowUp => {
|
|
t.translation += Vec3::Y * time.delta_seconds() * 1000.0
|
|
}
|
|
_ => (),
|
|
}
|
|
info!("Moved die {:?}", t.translation);
|
|
});
|
|
}
|
|
_ => (),
|
|
}
|
|
},
|
|
)
|
|
}
|
|
|
|
/// Component for each dice
|
|
#[derive(Component, Debug)]
|
|
struct Die {
|
|
sides: [&'static str; 6],
|
|
top: usize,
|
|
}
|
|
|
|
impl Die {
|
|
/// Initialize all dice values
|
|
fn new(sides: [&'static str; 6]) -> Die {
|
|
Die { sides, top: 0 }
|
|
}
|
|
|
|
/// Roll the dice
|
|
fn roll(&mut self, seed: usize) -> &'static str {
|
|
let idx = seed % 6;
|
|
self.top = idx;
|
|
self.get()
|
|
}
|
|
|
|
/// Get the current value of the dice
|
|
fn get(&self) -> &'static str {
|
|
self.sides[self.top]
|
|
}
|
|
}
|