|
|
|
@ -1,10 +1,9 @@
|
|
|
|
// Bevy basically forces "complex types" with Querys
|
|
|
|
// Bevy basically forces "complex types" with Querys
|
|
|
|
#![allow(clippy::type_complexity)]
|
|
|
|
#![allow(clippy::type_complexity)]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use itertools::Itertools;
|
|
|
|
use games::*;
|
|
|
|
use games::*;
|
|
|
|
|
|
|
|
|
|
|
|
// *TODO: Detect when piece is going to go out of bounds and restirct parent from moving there
|
|
|
|
|
|
|
|
// TODO: When shape touches the rest of the pieces, re-parent to line entity
|
|
|
|
|
|
|
|
// TODO: When line is "full" (has 10 children) clear line and add to score
|
|
|
|
// TODO: When line is "full" (has 10 children) clear line and add to score
|
|
|
|
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
fn main() {
|
|
|
|
@ -31,6 +30,7 @@ fn main() {
|
|
|
|
update_position,
|
|
|
|
update_position,
|
|
|
|
add_piece.run_if(not(any_with_component::<Shape>)),
|
|
|
|
add_piece.run_if(not(any_with_component::<Shape>)),
|
|
|
|
clear_line.run_if(any_component_changed::<LineBlocks>),
|
|
|
|
clear_line.run_if(any_component_changed::<LineBlocks>),
|
|
|
|
|
|
|
|
adjust_block_lines.run_if(any_component_changed::<Line>),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.add_systems(Update, draw_grid)
|
|
|
|
.add_systems(Update, draw_grid)
|
|
|
|
@ -58,7 +58,7 @@ struct ShapeBlock {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// The blocks making up this shape
|
|
|
|
// The blocks making up this shape
|
|
|
|
#[derive(Component, Default)]
|
|
|
|
#[derive(Component, Default, Debug)]
|
|
|
|
#[relationship_target(relationship = LineBlock)]
|
|
|
|
#[relationship_target(relationship = LineBlock)]
|
|
|
|
struct LineBlocks(Vec<Entity>);
|
|
|
|
struct LineBlocks(Vec<Entity>);
|
|
|
|
|
|
|
|
|
|
|
|
@ -72,8 +72,8 @@ struct LineBlock {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// A line holds up to 10 blocks before being cleared
|
|
|
|
// A line holds up to 10 blocks before being cleared
|
|
|
|
#[derive(Component, Debug)]
|
|
|
|
#[derive(Component, Debug, Clone, Copy)]
|
|
|
|
struct Line(u8);
|
|
|
|
struct Line(usize);
|
|
|
|
|
|
|
|
|
|
|
|
// Just marks a block either of a shape or line
|
|
|
|
// Just marks a block either of a shape or line
|
|
|
|
#[derive(Component, Debug)]
|
|
|
|
#[derive(Component, Debug)]
|
|
|
|
@ -570,15 +570,53 @@ fn add_piece(mut commands: Commands) {
|
|
|
|
|
|
|
|
|
|
|
|
/// When a line reaches 10 blocks, clear it
|
|
|
|
/// When a line reaches 10 blocks, clear it
|
|
|
|
fn clear_line(
|
|
|
|
fn clear_line(
|
|
|
|
lines: Query<(Entity, &LineBlocks), (With<LineBlocks>, Changed<LineBlocks>)>,
|
|
|
|
changed_lines: Query<Entity, Changed<LineBlocks>>,
|
|
|
|
|
|
|
|
mut lines: Query<(Entity, &LineBlocks, &mut Line)>,
|
|
|
|
mut commands: Commands,
|
|
|
|
mut commands: Commands,
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
lines.iter().for_each(|(e, lb)| {
|
|
|
|
let cleared_lines: Vec<usize> = changed_lines
|
|
|
|
if lb.0.len() == 10 {
|
|
|
|
.iter()
|
|
|
|
commands.entity(e).despawn_related::<LineBlocks>();
|
|
|
|
.filter_map(|e| lines.get(e).ok())
|
|
|
|
// TODO: re-parent all blocks above this to the next line down
|
|
|
|
.filter_map(|(e, lb, Line(i))| {
|
|
|
|
// TODO: Parent blocks to lines for movement
|
|
|
|
if lb.0.len() == 10 {
|
|
|
|
}
|
|
|
|
commands.entity(e).despawn_related::<LineBlocks>();
|
|
|
|
|
|
|
|
Some(*i)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
info!("Cleared lines: {:?}", cleared_lines);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (idx, cleared_line_number) in cleared_lines.into_iter().sorted().enumerate() {
|
|
|
|
|
|
|
|
info!("Processing line {cleared_line_number} ({idx})");
|
|
|
|
|
|
|
|
let cleared_line_number = cleared_line_number - idx;
|
|
|
|
|
|
|
|
lines.iter_mut().for_each(|(_, _, mut l)| {
|
|
|
|
|
|
|
|
let dest = if l.0 > cleared_line_number {
|
|
|
|
|
|
|
|
l.0 - 1
|
|
|
|
|
|
|
|
} else if l.0 == cleared_line_number {
|
|
|
|
|
|
|
|
(Y_MAX - (idx + 1) as u32) as usize
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
l.0
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
info!("Moving line {:?} to {:?}", l, dest);
|
|
|
|
|
|
|
|
l.0 = dest;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn adjust_block_lines(
|
|
|
|
|
|
|
|
query: Query<(Entity, &Line), Changed<Line>>,
|
|
|
|
|
|
|
|
parent: Query<&LineBlocks>,
|
|
|
|
|
|
|
|
mut blocks: Query<&mut GridPosition>,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
query.iter().for_each(|(e, Line(i))| {
|
|
|
|
|
|
|
|
parent.iter_descendants(e).for_each(|block| {
|
|
|
|
|
|
|
|
if let Ok(mut gp) = blocks.get_mut(block) {
|
|
|
|
|
|
|
|
gp.y = *i as u32;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -670,8 +708,13 @@ fn deactive_shape(
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
parent.iter_descendants(trigger.target()).for_each(|block| {
|
|
|
|
parent.iter_descendants(trigger.target()).for_each(|block| {
|
|
|
|
let GridPosition { y, .. } = grid_positions.get(block).unwrap();
|
|
|
|
let GridPosition { y, .. } = grid_positions.get(block).unwrap();
|
|
|
|
let parent_line = lines.iter().find_map(|(e, Line(i))| (*y == *i as u32).then_some(e)).unwrap();
|
|
|
|
let parent_line = lines
|
|
|
|
commands.entity(parent_line).add_one_related::<LineBlock>(block);
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.find_map(|(e, Line(i))| (*y == *i as u32).then_some(e))
|
|
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
commands
|
|
|
|
|
|
|
|
.entity(parent_line)
|
|
|
|
|
|
|
|
.add_one_related::<LineBlock>(block);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
commands.entity(trigger.target()).despawn();
|
|
|
|
commands.entity(trigger.target()).despawn();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|