Saving my place before basically starting over

main
Elijah Voigt 2 weeks ago
parent 570b4916bc
commit e1dcda4584

@ -39,15 +39,11 @@ fn main() {
init_battler,
),
)
.add_systems(
OnEnter(DebuggingState::On), toggle_art
)
.add_systems(
OnExit(DebuggingState::On), toggle_art
)
.add_systems(OnEnter(DebuggingState::On), toggle_art)
.add_systems(OnExit(DebuggingState::On), toggle_art)
.add_systems(
Update,
game_state_machine.run_if(state_changed::<GameState>)
game_state_machine.run_if(state_changed::<GameState>),
)
// Input and basic systems
.add_systems(
@ -70,12 +66,17 @@ fn main() {
.run_if(in_state(GameState::Play))
.run_if(on_timer(Duration::from_secs(1))),
movement.run_if(on_message::<Movement>),
update_position.run_if(any_component_changed::<GridPosition>),
update_line_position.run_if(any_component_changed::<Line>),
update_block_position.run_if(any_component_changed::<GridPosition>),
update_shape_blocks
.run_if(any_component_changed::<ShapeLayout>.or(any_component_changed::<GridPosition>))
.after(update_position),
.run_if(
any_component_changed::<ShapeLayout>
.or(any_component_changed::<GridPosition>),
)
.after(update_block_position),
deactivate_shape
.run_if(any_component_removed::<Shape>)
.after(game_state_machine)
.after(update_shape_blocks),
// Clearing lines systems
clear_line.run_if(any_component_changed::<LineBlocks>),
@ -146,6 +147,14 @@ struct LineBlock {
#[derive(Component, Debug, Clone, Copy)]
struct Line(usize);
impl From<&Line> for Vec3 {
fn from(Line(y): &Line) -> Vec3 {
let y_0 = -SCALE * 10.0 + (0.5 * SCALE);
let y = y_0 + ((*y as f32) * SCALE);
Vec3::new(0.0, y, 0.0)
}
}
// Just marks a block either of a shape or line
#[derive(Component, Debug)]
struct Block;
@ -277,9 +286,9 @@ fn game_state_machine(
// Set goal based on current goal
next.set(GameState::Play);
},
GameState::Play => (), // handled by user input
GameState::Pause => (), // handled by user input
}
GameState::Play => (), // handled by user input
GameState::Pause => (), // handled by user input
GameState::LevelComplete => (), // hanled by user input
GameState::NextLevel => {
// Increase goal
@ -298,7 +307,7 @@ fn game_state_machine(
// Progress to play
next.set(GameState::Play)
}
GameState::GameOver => (),// handled by user input
GameState::GameOver => (), // handled by user input
}
}
@ -316,7 +325,7 @@ impl Default for LevelGoal {
impl Display for LevelGoal {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
LevelGoal::Score(n) => write!(f, "{n}")
LevelGoal::Score(n) => write!(f, "{n}"),
}
}
}
@ -337,7 +346,7 @@ struct Visuals {
/// Stores the art assets that may be toggled on and off for development
#[derive(Component, Debug, Clone)]
struct Art {
texture: Handle<Image>
texture: Handle<Image>,
}
#[derive(Resource, Debug, Default)]
@ -446,7 +455,23 @@ fn init_tetris(
});
// Spawn line for holding blocks
commands.spawn((Line(y), LineBlocks::default(), TETRIS));
commands
.spawn((
Line(y),
LineBlocks::default(),
TETRIS,
Transform::default(),
Visibility::default(),
))
.with_children(|parent| {
// Spawn a line number next to the line so we can track it
parent.spawn((
Text2d(format!("{}", y)),
TETRIS,
Transform::from_xyz(0.0, 0.0, 99.0),
Visibility::default(),
));
});
});
}
@ -646,41 +671,50 @@ fn init_ui(mut commands: Commands, output_images: Res<OutputImages>, images: Res
});
});
commands
.spawn((
Node {
align_self: AlignSelf::Center,
justify_self: JustifySelf::Center,
..default()
},
ZIndex(1),
GameState::Pause,
children![(Text::new("paused"), TextColor(WHITE.into()), GameState::Pause)],
));
commands
.spawn((
Node {
align_self: AlignSelf::Center,
justify_self: JustifySelf::Center,
..default()
},
ZIndex(1),
GameState::LevelComplete,
children![(Text::new("you did it!"), TextColor(WHITE.into()), GameState::LevelComplete)],
));
commands
.spawn((
Node {
align_self: AlignSelf::Center,
justify_self: JustifySelf::Center,
..default()
},
ZIndex(1),
GameState::GameOver,
children![(Text::new("aww, you suck. i'm sorry."), TextColor(WHITE.into()), GameState::GameOver)],
));
commands.spawn((
Node {
align_self: AlignSelf::Center,
justify_self: JustifySelf::Center,
..default()
},
ZIndex(1),
GameState::Pause,
children![(
Text::new("paused"),
TextColor(WHITE.into()),
GameState::Pause
)],
));
commands.spawn((
Node {
align_self: AlignSelf::Center,
justify_self: JustifySelf::Center,
..default()
},
ZIndex(1),
GameState::LevelComplete,
children![(
Text::new("you did it!"),
TextColor(WHITE.into()),
GameState::LevelComplete
)],
));
commands.spawn((
Node {
align_self: AlignSelf::Center,
justify_self: JustifySelf::Center,
..default()
},
ZIndex(1),
GameState::GameOver,
children![(
Text::new("aww, you suck. i'm sorry."),
TextColor(WHITE.into()),
GameState::GameOver
)],
));
commands
.spawn((
@ -815,11 +849,7 @@ impl ShapeLayout {
}
fn new_t() -> Self {
vec![
vec![0, 1, 0],
vec![1, 1, 1],
vec![0, 0, 0]
].into()
vec![vec![0, 1, 0], vec![1, 1, 1], vec![0, 0, 0]].into()
}
fn new_l() -> Self {
@ -923,7 +953,7 @@ impl ShapeLayout {
}
}
fn update_position(
fn update_block_position(
mut changed: Query<
(Entity, &GridPosition, &mut Transform),
Or<(Added<GridPosition>, Changed<GridPosition>)>,
@ -941,13 +971,25 @@ fn update_position(
});
}
fn update_line_position(
mut changed: Query<(Entity, &Line, &mut Transform), Or<(Added<Line>, Changed<Line>)>>,
) {
changed.iter_mut().for_each(|(e, gp, mut t)| {
let v3: Vec3 = gp.into();
debug!(
"Updating {e} with grid position {:?} to coordinates {:?}",
gp, v3
);
t.translation.x = v3.x;
t.translation.y = v3.y;
});
}
fn update_shape_blocks(
query: Query<
(Entity, &ShapeLayout, &GridPosition),
Or<(
Changed<ShapeLayout>,
Changed<GridPosition>,
)>,
Or<(Changed<ShapeLayout>, Changed<GridPosition>)>,
>,
mut blocks: Query<&mut GridPosition, (With<ShapeBlock>, Without<ShapeLayout>)>,
) {
@ -957,14 +999,12 @@ fn update_shape_blocks(
debug_assert!(!blocks.is_empty());
let mut p = sl.coordinates_at(center);
blocks.iter_mut().for_each(|mut gp| {
match p.next() {
Some(next) => match next {
Ok(next_gp) => *gp = next_gp,
Err(_) => warn!("Next coordinate was an Err?"),
},
None => warn!("Next coordinate was a None?"),
}
blocks.iter_mut().for_each(|mut gp| match p.next() {
Some(next) => match next {
Ok(next_gp) => *gp = next_gp,
Err(_) => warn!("Next coordinate was an Err?"),
},
None => warn!("Next coordinate was a None?"),
});
});
}
@ -991,7 +1031,14 @@ fn on_add_shape_layout(
.entity(e)
.with_related_entities::<ShapeBlock>(|parent| {
sl.coordinates_at(center).for_each(|gp| {
parent.spawn((mesh.clone(), MeshMaterial2d(mat.clone()), art.clone(), gp.unwrap(), Block, TETRIS));
parent.spawn((
mesh.clone(),
MeshMaterial2d(mat.clone()),
art.clone(),
gp.unwrap(),
Block,
TETRIS,
));
});
});
}
@ -1052,17 +1099,17 @@ fn kb_input(
},
GameState::Pause => match key_code {
KeyCode::Escape | KeyCode::Enter => next.set(GameState::Play),
_ => ()
}
_ => (),
},
GameState::GameOver => match key_code {
KeyCode::Escape => todo!("Quit the game"),
KeyCode::Enter => next.set(GameState::NewGame),
_ => ()
_ => (),
},
GameState::LevelComplete => match key_code {
KeyCode::Escape => todo!("Quit the game"),
KeyCode::Enter => next.set(GameState::NextLevel),
_ => ()
_ => (),
},
GameState::NewGame | GameState::NextLevel => (),
}
@ -1243,15 +1290,15 @@ fn movement(
// For each of the proposed positions
for position in new_positions {
if let Ok(new_center) = position {
let new_blocks: Vec<Result<GridPosition, OutOfBoundsError>> = new_shape_layout
.coordinates_at(&new_center)
.collect();
let new_blocks: Vec<Result<GridPosition, OutOfBoundsError>> =
new_shape_layout.coordinates_at(&new_center).collect();
// If the move would cause one block to be out of bounds,
// Not a valid move so return.
if new_blocks.contains(&Err(OutOfBoundsError::Left))
|| new_blocks.contains(&Err(OutOfBoundsError::Right)) {
return
|| new_blocks.contains(&Err(OutOfBoundsError::Right))
{
return;
}
// If would be out of bounds at the bottom of play
@ -1274,10 +1321,9 @@ fn movement(
next_state.set(GameState::GameOver);
}
// We are moving down
if [
MovementDirection::Down,
MovementDirection::Skip,
].contains(&message.direction) {
if [MovementDirection::Down, MovementDirection::Skip]
.contains(&message.direction)
{
// De-activate this piece
commands.entity(message.entity).remove::<Shape>();
}
@ -1374,16 +1420,26 @@ fn update_next_shapes(mut buffer: ResMut<ShapesBuffer>) {
}
fn assert_grid_position_uniqueness(
grid_positions: Query<(Entity, &GridPosition, Option<&LineBlock>, Option<&ShapeBlock>), With<Block>>,
grid_positions: Query<
(
Entity,
&GridPosition,
Option<&LineBlock>,
Option<&ShapeBlock>,
),
With<Block>,
>,
) {
grid_positions.iter_combinations().for_each(|[(e1, a, lb1, sb1), (e2, b, lb2, sb2)]| {
if a == b {
error!("Entities {e1:?} and {e2:?} @ GP {a:?}/{b:?}!");
error!("\t{:?}: (Block: {:?}| Line: {:?})!", e1, sb1, lb1);
error!("\t{:?}: (Block: {:?}| Line: {:?})!", e2, sb2, lb2);
}
assert_ne!(a, b, "Two entities are in the same grid position!");
});
grid_positions
.iter_combinations()
.for_each(|[(e1, a, lb1, sb1), (e2, b, lb2, sb2)]| {
if a == b {
error!("Entities {e1:?} and {e2:?} @ GP {a:?}/{b:?}!");
error!("\t{:?}: (Block: {:?}| Line: {:?})!", e1, sb1, lb1);
error!("\t{:?}: (Block: {:?}| Line: {:?})!", e2, sb2, lb2);
}
assert_ne!(a, b, "Two entities are in the same grid position!");
});
}
fn sync_health(

@ -149,12 +149,9 @@ fn test_shape_block_layout_rotation() {
fn test_shape_block_center() {
{
let actual = ShapeBlockLayout {
inner: vec![
vec![0],
vec![0],
vec![0],
]
}.center();
inner: vec![vec![0], vec![0], vec![0]],
}
.center();
let expected = (0, 1);
@ -163,13 +160,9 @@ fn test_shape_block_center() {
{
let actual = ShapeBlockLayout {
inner: vec![
vec![0],
vec![0],
vec![0],
vec![0],
]
}.center();
inner: vec![vec![0], vec![0], vec![0], vec![0]],
}
.center();
let expected = (0, 2);
@ -178,11 +171,9 @@ fn test_shape_block_center() {
{
let actual = ShapeBlockLayout {
inner: vec![
vec![0, 0],
vec![0, 0],
]
}.center();
inner: vec![vec![0, 0], vec![0, 0]],
}
.center();
let expected = (0, 1);
@ -191,12 +182,9 @@ fn test_shape_block_center() {
{
let actual = ShapeBlockLayout {
inner: vec![
vec![0, 0, 0],
vec![0, 0, 0],
vec![0, 0, 0],
]
}.center();
inner: vec![vec![0, 0, 0], vec![0, 0, 0], vec![0, 0, 0]],
}
.center();
let expected = (1, 1);
@ -210,8 +198,9 @@ fn test_shape_block_center() {
vec![0, 0, 0, 0],
vec![0, 0, 0, 0],
vec![0, 0, 0, 0],
]
}.center();
],
}
.center();
let expected = (1, 2);

@ -13,16 +13,11 @@ mod ui;
mod version;
// Rust stdlib
pub use std::{
collections::VecDeque,
f32::consts::PI,
fmt::Display,
};
pub use core::time::Duration;
pub use std::{collections::VecDeque, f32::consts::PI, fmt::Display};
// Community libraries
pub use bevy::{
time::common_conditions::*,
asset::{
AssetLoader, AssetMetaCheck, LoadContext, LoadState, LoadedFolder, RenderAssetUsages,
io::Reader, uuid_handle,
@ -44,6 +39,7 @@ pub use bevy::{
reflect::TypePath,
render::render_resource::{Extent3d, TextureDimension, TextureFormat, TextureUsages},
sprite_render::*,
time::common_conditions::*,
window::{WindowResized, WindowResolution},
};
pub use itertools::Itertools;

Loading…
Cancel
Save