generated from hheik/bevy-template
100 lines
3.2 KiB
Rust
100 lines
3.2 KiB
Rust
use bevy::prelude::*;
|
|
|
|
use crate::{
|
|
game::{grid::*, tetris::*},
|
|
util::Vector2I,
|
|
};
|
|
|
|
pub fn apply_gravity(
|
|
mut piece_query: Query<(&mut Gravity, &PieceControls, &ChildOf)>,
|
|
time: Res<Time>,
|
|
game_gravity_query: Query<&GameGravity>,
|
|
) {
|
|
const SOFT_DROP_SPEED: f32 = 10.0;
|
|
for (mut piece_gravity, controls, parent) in piece_query.iter_mut() {
|
|
if let Ok(game_gravity) = game_gravity_query.get(parent.0) {
|
|
piece_gravity.cumulated += game_gravity.current * time.delta_secs();
|
|
}
|
|
if controls.fast_drop {
|
|
piece_gravity.cumulated += SOFT_DROP_SPEED * time.delta_secs();
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn apply_piece_movement(
|
|
mut piece_query: Query<(
|
|
&PieceControls,
|
|
Option<&mut Gravity>,
|
|
Entity,
|
|
&ChildOf,
|
|
&Children,
|
|
)>,
|
|
game_query: Query<(&BlockSet, &GameArea)>,
|
|
mut transform_query: Query<(&mut GridTransform, Has<Block>)>,
|
|
mut commands: Commands,
|
|
) {
|
|
for (controls, maybe_gravity, entity, parent, children) in piece_query.iter_mut() {
|
|
let game_entity = parent.parent();
|
|
let (collisions, game_area) = game_query.get(game_entity).unwrap();
|
|
|
|
let blocks: Vec<Vector2I> = {
|
|
let mut blocks = vec![];
|
|
for child in children.iter() {
|
|
let block = transform_query
|
|
.get(child)
|
|
.iter()
|
|
.filter_map(|(transform, has_block)| {
|
|
if *has_block {
|
|
Some(transform.translation)
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
.next();
|
|
if let Some(pos) = block {
|
|
blocks.push(pos);
|
|
}
|
|
}
|
|
blocks
|
|
};
|
|
|
|
let cast_shape =
|
|
|pos| collisions.cast_shape(pos, &blocks) || !game_area.is_shape_inside(pos, &blocks);
|
|
|
|
let piece_pos = &mut transform_query.get_mut(entity).unwrap().0.translation;
|
|
|
|
if controls.instant_drop {
|
|
let mut drop_pos = *piece_pos;
|
|
while !cast_shape(drop_pos + Vector2I::DOWN) {
|
|
drop_pos = drop_pos + Vector2I::DOWN;
|
|
}
|
|
*piece_pos = drop_pos;
|
|
commands.trigger_targets(OnPiecePlaced { piece: entity }, game_entity);
|
|
continue;
|
|
}
|
|
|
|
let can_move_down = !cast_shape(*piece_pos + Vector2I::DOWN);
|
|
|
|
if let Some(mut gravity) = maybe_gravity {
|
|
if gravity.cumulated >= 1.0 && can_move_down {
|
|
gravity.cumulated -= 1.0;
|
|
*piece_pos = *piece_pos + Vector2I::DOWN;
|
|
}
|
|
if gravity.cumulated >= 3.0 && !can_move_down {
|
|
commands.trigger_targets(OnPiecePlaced { piece: entity }, game_entity);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if let Some(movement) = controls.movement {
|
|
let dir = match movement {
|
|
input::Move::Left => Vector2I::LEFT,
|
|
input::Move::Right => Vector2I::RIGHT,
|
|
};
|
|
if !cast_shape(*piece_pos + dir) {
|
|
*piece_pos = *piece_pos + dir;
|
|
}
|
|
}
|
|
}
|
|
}
|