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

@ -149,12 +149,9 @@ fn test_shape_block_layout_rotation() {
fn test_shape_block_center() { fn test_shape_block_center() {
{ {
let actual = ShapeBlockLayout { let actual = ShapeBlockLayout {
inner: vec![ inner: vec![vec![0], vec![0], vec![0]],
vec![0], }
vec![0], .center();
vec![0],
]
}.center();
let expected = (0, 1); let expected = (0, 1);
@ -163,13 +160,9 @@ fn test_shape_block_center() {
{ {
let actual = ShapeBlockLayout { let actual = ShapeBlockLayout {
inner: vec![ inner: vec![vec![0], vec![0], vec![0], vec![0]],
vec![0], }
vec![0], .center();
vec![0],
vec![0],
]
}.center();
let expected = (0, 2); let expected = (0, 2);
@ -178,11 +171,9 @@ fn test_shape_block_center() {
{ {
let actual = ShapeBlockLayout { let actual = ShapeBlockLayout {
inner: vec![ inner: vec![vec![0, 0], vec![0, 0]],
vec![0, 0], }
vec![0, 0], .center();
]
}.center();
let expected = (0, 1); let expected = (0, 1);
@ -191,12 +182,9 @@ fn test_shape_block_center() {
{ {
let actual = ShapeBlockLayout { let actual = ShapeBlockLayout {
inner: vec![ inner: vec![vec![0, 0, 0], vec![0, 0, 0], vec![0, 0, 0]],
vec![0, 0, 0], }
vec![0, 0, 0], .center();
vec![0, 0, 0],
]
}.center();
let expected = (1, 1); 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], vec![0, 0, 0, 0],
vec![0, 0, 0, 0], vec![0, 0, 0, 0],
] ],
}.center(); }
.center();
let expected = (1, 2); let expected = (1, 2);

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

Loading…
Cancel
Save