diff --git a/src/bin/tetris.rs b/src/bin/tetris.rs index 9d05383..6ff92d9 100644 --- a/src/bin/tetris.rs +++ b/src/bin/tetris.rs @@ -5,19 +5,12 @@ use std::ops::{Add, Sub}; use glite::debug_plugin; -const GRID_X: f32 = 0.0; -const GRID_Y: f32 = 0.0; -const GRID_WIDTH: u32 = 15; -const GRID_HEIGHT: u32 = 10; - -const WINDOW_WIDTH: f32 = 800.0; -const WINDOW_HEIGHT: f32 = WINDOW_WIDTH * (GRID_HEIGHT as f32 / GRID_WIDTH as f32); - #[cfg_attr(feature = "debug", derive(bevy_inspector_egui::InspectorOptions))] #[derive(Component, Debug, Default, Copy, Clone, Eq, PartialEq)] struct Position { pub x: u32, pub y: u32, + pub z: u32, // render order } impl Add for Position { @@ -26,6 +19,7 @@ impl Add for Position { Self { x: self.x + other.x, y: self.y + other.y, + z: self.z + other.z, } } } @@ -36,16 +30,11 @@ impl Sub for Position { Self { x: self.x.saturating_sub(other.x), y: self.y.saturating_sub(other.y), + z: self.z.saturating_sub(other.z), } } } -impl Display for Position { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "({}, {})", self.x, self.y) - } -} - #[derive(Component)] struct Size { width: f32, @@ -61,33 +50,35 @@ impl Size { } } -fn spawn_tile(commands: &mut Commands, color: Color, size: f32, position: Position) { +fn spawn_tile(commands: &mut Commands, color: Color, size: f32, position: Position) -> Entity { commands .spawn(Sprite { color, ..Default::default() }) .insert(position) - .insert(Size::square(size)); + .insert(Size::square(size)) + .id() } fn scale_translation( - mut windows: Query<&mut Window, With>, + window: Single<&Window>, mut q: Query<(&Size, &mut Transform)>, + matrix: Res, ) { - let window = windows.single_mut(); for (sprite_size, mut transform) in q.iter_mut() { transform.scale = Vec3::new( - sprite_size.width / GRID_WIDTH as f32 * window.width(), - sprite_size.height / GRID_HEIGHT as f32 * window.height(), + sprite_size.width / matrix.width as f32 * window.width(), + sprite_size.height / matrix.height as f32 * window.height(), 1.0, ); } } fn position_translation( - mut windows: Query<&mut Window, With>, + window: Single<&Window>, mut q: Query<(&Position, &mut Transform)>, + matrix: Res, ) { // We subtract half the window width because our coordinate system starts at the bottom left, and // Translation starts from the center. We then add half the size of a single tile, because we want @@ -97,32 +88,62 @@ fn position_translation( pos / bound_game * bound_window - (bound_window / 2.) + (tile_size / 2.) } - let window = windows.single_mut(); for (pos, mut transform) in q.iter_mut() { transform.translation = Vec3::new( - convert(pos.x as f32, window.width(), GRID_WIDTH as f32) + GRID_X, - convert(pos.y as f32, window.height(), GRID_HEIGHT as f32) + GRID_Y, - 0.0, + convert(pos.x as f32, window.width(), matrix.width as f32), + convert(pos.y as f32, window.height(), matrix.height as f32), + pos.z as f32, ); } } -fn test_update() {} +#[derive(Component)] +struct Tetromino([[u32; 2]; 4]); + +// TODO: check these positions are right +const BRICK_I: Tetromino = Tetromino([[0, 0], [1, 0], [2, 0], [3, 0]]); +const BRICK_J: Tetromino = Tetromino([[0, 0], [1, 0], [2, 0], [2, 1]]); +const BRICK_L: Tetromino = Tetromino([[0, 0], [1, 0], [2, 0], [0, 1]]); +const BRICK_O: Tetromino = Tetromino([[0, 0], [1, 0], [0, 1], [1, 1]]); +const BRICK_S: Tetromino = Tetromino([[0, 0], [1, 0], [1, 1], [2, 1]]); +const BRICK_T: Tetromino = Tetromino([[0, 0], [1, 0], [2, 0], [1, 1]]); +const BRICK_Z: Tetromino = Tetromino([[0, 1], [1, 1], [1, 0], [2, 0]]); + +enum RenderLayer { + Background = 0, + Brick = 10, +} + +fn spawn_tetromino(commands: &mut Commands, tetromino: Tetromino, x: u32, y: u32) { + for coord in tetromino.0 { + spawn_tile( + commands, + Color::srgb(1.0, 1.0, 1.0), + 0.77, + Position { + x: coord[0] + x, + y: coord[1] + y, + z: RenderLayer::Brick as u32, + }, + ); + } +} fn main() { let mut app = App::new(); app.add_plugins(DefaultPlugins.set(WindowPlugin { primary_window: Some(Window { title: "Tetris".to_string(), - resolution: WindowResolution::new(WINDOW_WIDTH, WINDOW_HEIGHT), ..default() }), ..default() })); - app.add_systems(Startup, setup_scene) - .add_systems(Update, test_update) - .add_systems(PostUpdate, (scale_translation, position_translation)); + app.add_systems( + Startup, + (init_singletons, init_window, init_tile_grid).chain(), + ) + .add_systems(PostUpdate, (scale_translation, position_translation)); app.add_plugins(debug_plugin::debug_plugin); @@ -130,15 +151,74 @@ fn main() { app.run(); } -fn setup_scene(mut commands: Commands) { +#[derive(Resource)] +struct Score(u32); + +#[derive(Resource, Copy, Clone)] +struct Matrix { + width: u32, + height: u32, +} + +fn init_singletons(mut commands: Commands) { + let matrix = Matrix { + height: 15, + width: 15, + }; + commands.insert_resource(Score(0)); + commands.insert_resource(matrix); + commands.spawn(Camera2d {}); - for y in 0..GRID_HEIGHT { - for x in 0..GRID_WIDTH { - let color = match ((y * GRID_HEIGHT) + x + y) % 2 == 0 { +} + +fn init_window(matrix: Res, mut window: Single<&mut Window>) { + const SCALE_FACTOR: f32 = 77.; + + window.resolution.set( + matrix.width as f32 * SCALE_FACTOR, + matrix.height as f32 * SCALE_FACTOR, + ); +} + +#[derive(Component)] +struct Grid; + +fn init_tile_grid(mut commands: Commands, matrix: Res) { + let grid = commands + .spawn(Grid) + .insert(Name::new("Background Grid")) + .insert((Transform::default(), Visibility::default())) + .id(); + + for y in 0..matrix.height { + for x in 0..matrix.width { + let color = match (y + x) % 2 == 0 { true => Color::srgb(0.5, 0.5, 0.5), false => Color::srgb(0.55, 0.55, 0.55), }; - spawn_tile(&mut commands, color, 1.0, Position { x, y }); + let e = spawn_tile( + &mut commands, + color, + 1.0, + Position { + x, + y, + z: RenderLayer::Background as u32, + }, + ); + commands.entity(e).set_parent(grid); } } + test_render_all_tetrominos(commands); +} + +fn test_render_all_tetrominos(mut commands: Commands) { + spawn_tetromino(&mut commands, BRICK_I, 0, 0); + spawn_tetromino(&mut commands, BRICK_T, 4, 0); + spawn_tetromino(&mut commands, BRICK_J, 8, 0); + spawn_tetromino(&mut commands, BRICK_L, 12, 0); + spawn_tetromino(&mut commands, BRICK_O, 0, 4); + spawn_tetromino(&mut commands, BRICK_S, 4, 4); + spawn_tetromino(&mut commands, BRICK_Z, 8, 4); + spawn_tetromino(&mut commands, BRICK_J, 12, 4); }