Detecting when to deactivate a piece

At least when there are no other blocks on the board...
main
Elijah Voigt 1 month ago
parent a668b946f2
commit cea796325e

@ -1,17 +1,14 @@
#![allow(clippy::single_match)]
#![allow(clippy::type_complexity)]
use super::*;
// TODO:
// - When shape asset is updated, shape layout update in real time
// - Debug: gizmo outline entities
// - conditional enable/disable
// - entities without mesh should draw empty cross
// - Debug: gizmo draw relationship lines
// - conditional enable/disable
// - Debug: show FPS
// - conditional enable/disable
// - Line entities
// - Debug: Nametags
// - If it has a Name component, display that at the same Translation
// - Disable shape when placed
@ -31,6 +28,7 @@ impl Plugin for BlocksPlugin {
app.init_asset::<ShapeAsset>()
.init_asset_loader::<ShapeAssetLoader>()
.add_message::<Movement>()
.add_message::<ShapeEvent>()
.add_systems(OnEnter(Loading(true)), load_assets.run_if(run_once))
.add_systems(
OnEnter(GameState::Setup),
@ -49,6 +47,7 @@ impl Plugin for BlocksPlugin {
propogate_relative_position.run_if(any_component_changed::<RelativePosition>),
handle_kb_input.run_if(on_message::<KeyboardInput>),
handle_movement.run_if(on_message::<Movement>),
handle_shape_event.run_if(on_message::<ShapeEvent>),
),
)
.add_observer(add_shape)
@ -108,11 +107,11 @@ struct GridPosition {
#[derive(Debug, Error)]
enum GridPositionError {
#[error("X > X_MAX")]
XOver,
HitRight,
#[error("X < 0")]
XUnder,
HitLeft,
#[error("Y < 0")]
YUnder,
HitFloor,
#[error("Y < 0 && X < 0")]
BothUnder,
}
@ -130,17 +129,17 @@ impl GridPosition {
// Both underflow
(None, None) => Err(GridPositionError::BothUnder),
// Just y underflows
(None, Some(_)) => Err(GridPositionError::XUnder),
(None, Some(_)) => Err(GridPositionError::HitLeft),
// y underflow or x overflow
(Some(x), None) => match x {
0..X_MAX => Err(GridPositionError::YUnder),
_ => Err(GridPositionError::XOver),
}
0..X_MAX => Err(GridPositionError::HitFloor),
_ => Err(GridPositionError::HitRight),
},
// both good, may x overflow
(Some(x), Some(y)) => match x {
0..X_MAX => Ok(GridPosition { x, y }),
_ => Err(GridPositionError::XOver),
}
0..X_MAX => Ok(GridPosition { x, y }),
_ => Err(GridPositionError::HitRight),
},
}
}
}
@ -539,6 +538,12 @@ enum Movement {
Right,
}
/// Things that can happen to a shape
#[derive(Debug, Message, PartialEq)]
enum ShapeEvent {
Deactivate,
}
/// Handle KeyBoard input
/// Nothing is handled directly in this method,
/// All key presses result in either a message, event, or state change
@ -592,40 +597,54 @@ impl Orientation {
fn handle_movement(
mut moves: MessageReader<Movement>,
mut shapes: Query<(&ShapeLayout, &mut GridPosition, &mut Orientation)>,
mut writer: MessageWriter<ShapeEvent>,
) {
moves.read().for_each(|m| {
shapes.iter_mut().for_each(|(shape_layout, mut gp, mut o)| {
'outer: for m in moves.read() {
for (shape_layout, mut gp, mut o) in shapes.iter_mut() {
// First determine if proposed positions are valid
// Determine next orientation
let proposed_orientation = if *m == Movement::Rotate {
o.rotated()
} else {
*o
let proposed_orientation = match *m == Movement::Rotate {
true => o.rotated(),
false => *o,
};
// And next position
let proposed_position = match m {
Movement::Left => gp.add((-1, 0).into()),
Movement::Right => gp.add((1, 0).into()),
Movement::Down => gp.add((0, -1).into()),
Movement::Rotate => Ok(gp.clone()),
let offset: RelativePosition = match m {
Movement::Left => (-1, 0).into(),
Movement::Right => (1, 0).into(),
Movement::Down => (0, -1).into(),
Movement::Rotate => (0, 0).into(),
};
if let Ok(pp) = proposed_position {
// Check that new positions are all valid
if shape_layout
.positions(proposed_orientation)
.iter()
.all(|rp| pp.add(*rp).is_ok()) {
// then commit the movement
*gp = pp;
*o = proposed_orientation;
} else {
// invalid position!
// TODO: See if the proposed position would collide with another block
// If would collide downward, deactivate shape
// Check that new positions are all valid for all blocks
for pos in shape_layout.positions(proposed_orientation).iter() {
match gp.add(*pos).unwrap().add(offset) {
Err(e) => {
match e {
GridPositionError::HitFloor => {
writer.write(ShapeEvent::Deactivate);
}
_ => (), // Other errors are just ignored
}
// Either way skip the rest of this iteration of the loop
continue 'outer;
}
Ok(_) => (), // Ignore OKs as no [bad] news is good news
}
} else {
// Invalid move!
}
});
// If those checks went well, commit the proposed changes
*gp = gp.add(offset).unwrap();
*o = proposed_orientation;
}
}
}
fn handle_shape_event(mut reader: MessageReader<ShapeEvent>) {
reader.read().for_each(|msg| match msg {
ShapeEvent::Deactivate => warn!("TODO: Deactivate shape"),
});
}

Loading…
Cancel
Save