From 0c42c33b7ecf29ebddcc84978965c2b22cd5c8d3 Mon Sep 17 00:00:00 2001 From: Elijah Voigt Date: Sat, 13 Dec 2025 22:24:59 -0800 Subject: [PATCH] We can draw a shape! --- tetris/src/blocks.rs | 74 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/tetris/src/blocks.rs b/tetris/src/blocks.rs index fd91145..7ca8236 100644 --- a/tetris/src/blocks.rs +++ b/tetris/src/blocks.rs @@ -21,10 +21,16 @@ impl Plugin for BlocksPlugin { Update, updated_shape_asset.run_if(on_message::>), ) - .add_observer(add_shape); + .add_observer(add_shape) + .add_observer(add_relative_position) + .add_observer(add_grid_position); } } +const SCALE: f32 = 20.0; +const X_MAX: usize = 10; +const Y_MAX: usize = 20; + /// Shape asset /// Stores shape data in an asset file, likely toml #[derive(Asset, TypePath, Debug, Deserialize)] @@ -44,14 +50,43 @@ fn default_tint() -> String { impl ShapeAsset { fn as_bundle(&self) -> impl Bundle { + // Get shape block's relative positions let [a, b, c, d] = self.layout.positions(); - related!(ShapeBlocks[ - (self.mesh.clone(), self.material.clone(), a), - (self.mesh.clone(), self.material.clone(), b), - (self.mesh.clone(), self.material.clone(), c), - (self.mesh.clone(), self.material.clone(), d), - ]) + ( + GridPosition { x: 5, y: 5 }, // TEMP + related!(ShapeBlocks[ + (self.mesh.clone(), self.material.clone(), a), + (self.mesh.clone(), self.material.clone(), b), + (self.mesh.clone(), self.material.clone(), c), + (self.mesh.clone(), self.material.clone(), d), + ]) + ) + } +} + +/// The main play area grid coordinates +#[derive(Component)] +#[require(Transform)] +struct GridPosition { + pub x: usize, + pub y: usize, +} + +impl GridPosition { + fn with_relative_offset(&self, other: &RelativePosition) -> GridPosition { + GridPosition { + x: self.x.checked_add_signed(other.x).unwrap(), + y: self.y.checked_add_signed(other.y).unwrap(), + } + } +} + +impl Into for &GridPosition { + fn into(self) -> Vec3 { + let x = (self.x as f32 * SCALE) - ((X_MAX / 2) as f32 * SCALE); + let y = (self.y as f32 * SCALE) - ((Y_MAX / 2) as f32 * SCALE); + Vec3::new(x, y, 0.0) } } @@ -135,7 +170,7 @@ impl AssetLoader for ShapeAssetLoader { let parsed = toml::from_slice::(bytes.as_slice())?; let mesh = { // https://docs.rs/bevy/latest/bevy/asset/struct.LoadContext.html#method.add_labeled_asset - let m: Mesh = Rectangle::new(100.0, 100.0).into(); + let m: Mesh = Rectangle::new(SCALE, SCALE).into(); let h: Handle = load_context.add_labeled_asset(format!("{}#mesh", load_context.asset_path()), m); Mesh2d(h) @@ -211,6 +246,7 @@ fn add_shape( commands.entity(event.entity).insert(shape.as_bundle()); } +/// When a shape asset is updated, propogate other required changes fn updated_shape_asset( mut messages: MessageReader>, query: Query<&AssetComponent>, @@ -228,3 +264,25 @@ fn updated_shape_asset( AssetEvent::LoadedWithDependencies { id } => debug!("Asset lodaed: {id:?}"), }) } + +/// What to do when a relative position is added to a block +fn add_relative_position( + event: On, + relative_positions: Query<&RelativePosition>, + blocks: Query<&ShapeBlock>, + grid_positions: Query<&GridPosition>, + mut commands: Commands, +) { + let parent_shape = blocks.get(event.entity).unwrap(); + let rp = relative_positions.get(event.entity).unwrap(); + let gp = grid_positions.get(parent_shape.0).unwrap(); + commands.entity(event.entity).insert(gp.with_relative_offset(rp)); +} + +fn add_grid_position( + event: On, + mut query: Query<(&GridPosition, &mut Transform)>, +) { + let (gp, mut t) = query.get_mut(event.entity).unwrap(); + t.translation = gp.into(); +}