diff --git a/src/bin/fail_tetris.rs b/src/bin/fail_tetris.rs new file mode 100644 index 0000000..987ca2e --- /dev/null +++ b/src/bin/fail_tetris.rs @@ -0,0 +1,251 @@ +use bevy::window::PrimaryWindow; +use bevy::{prelude::*, window::WindowResolution}; +use std::fmt::{self, Display, Formatter}; +use std::ops::{Add, Sub}; + +use glite::debug_plugin; + +#[cfg_attr(feature = "debug", derive(bevy_inspector_egui::InspectorOptions))] +#[derive(Component, Debug, Default, Copy, Clone, Eq, PartialEq, Reflect)] +struct Position { + pub x: u32, + pub y: u32, + pub z: u32, // render order +} + +#[derive(Component, Debug, Reflect)] +struct Size { + width: f32, + height: f32, +} + +impl Size { + pub fn square(x: f32) -> Self { + Self { + width: x, + height: x, + } + } +} + +fn post_scale_tiles( + window: Single<&Window>, + matrix: Res, + mut q: Query<(&Size, &mut Transform), With>, +) { + for (sprite_size, mut transform) in q.iter_mut() { + transform.scale = Vec3::new( + sprite_size.width / matrix.width as f32 * window.width(), + sprite_size.height / matrix.height as f32 * window.height(), + 1.0, + ); + } +} + +fn post_translate_tiles( + window: Single<&Window>, + matrix: Res, + mut q: Query<(&Position, &mut Transform), With>, +) { + // 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 + // our sprites bottom left corner to be at the bottom left of a tile, not the center. + fn convert(pos: f32, bound_window: f32, bound_game: f32) -> f32 { + let tile_size = bound_window / bound_game; + pos / bound_game * bound_window - (bound_window / 2.) + (tile_size / 2.) + } + + for (pos, mut transform) in q.iter_mut() { + transform.translation = Vec3::new( + 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 translate_tetrominos( + tetrominos: Query<(&Tetromino, &mut Children)>, + mut positions: Query<&mut Position, With>, +) { + for (t, children) in tetrominos.iter() { + for child in children.iter() { + let mut p = positions.get_mut(*child).unwrap(); + p.x += t.pos.x; + p.y += t.pos.y; + } + } +} + +#[derive(Component, Debug, Clone, Reflect)] +struct TetrominoKind([[u32; 2]; 4]); + +const BRICK_I: TetrominoKind = TetrominoKind([[0, 0], [1, 0], [2, 0], [3, 0]]); +const BRICK_J: TetrominoKind = TetrominoKind([[0, 0], [1, 0], [2, 0], [2, 1]]); +const BRICK_L: TetrominoKind = TetrominoKind([[0, 0], [1, 0], [2, 0], [0, 1]]); +const BRICK_O: TetrominoKind = TetrominoKind([[0, 0], [1, 0], [0, 1], [1, 1]]); +const BRICK_S: TetrominoKind = TetrominoKind([[0, 0], [1, 0], [1, 1], [2, 1]]); +const BRICK_T: TetrominoKind = TetrominoKind([[0, 0], [1, 0], [2, 0], [1, 1]]); +const BRICK_Z: TetrominoKind = TetrominoKind([[0, 1], [1, 1], [1, 0], [2, 0]]); + +enum RenderLayer { + Background = 0, + Brick = 1, +} + +#[derive(Component, Debug)] +struct Tile; + +#[derive(Bundle, Debug)] +struct TileBundle { + position: Position, + size: Size, + sprite: Sprite, + tile: Tile, +} + +fn spawn_tile(commands: &mut Commands, color: Color, size: f32, position: Position) -> Entity { + commands + .spawn(TileBundle { + position, + size: Size::square(size), + sprite: Sprite { + color, + ..Default::default() + }, + tile: Tile, + }) + .id() +} + +#[derive(Component, Reflect)] +struct Tetromino { + pos: Position, + kind: TetrominoKind, +} + +fn spawn_tetromino(commands: &mut Commands, kind: TetrominoKind, x: u32, y: u32) { + let tetromino = commands + .spawn(Tetromino { + pos: Position { x, y, z: 0 }, + kind: kind.clone(), + }) + .insert((Transform::default(), Visibility::default())) + .id(); + + for coord in kind.0 { + let e = spawn_tile( + commands, + Color::srgb(0.3, 0.3, 0.8), + 0.9, + Position { + x: x + coord[0], + y: y + coord[1], + z: RenderLayer::Brick as u32, + }, + ); + commands.entity(e).set_parent(tetromino); + } +} + +fn main() { + let mut app = App::new(); + app.add_plugins(DefaultPlugins.set(WindowPlugin { + primary_window: Some(Window { + title: "Tetris".to_string(), + ..default() + }), + ..default() + })); + + app.add_systems( + Startup, + (init_singletons, init_window, init_tile_grid).chain(), + ) + .add_systems( + PostUpdate, + (translate_tetrominos, post_scale_tiles, post_translate_tiles).chain(), + ); + + app.add_plugins(debug_plugin::debug_plugin); + + app.register_type::(); + app.register_type::(); + app.register_type::(); + + // Run the app + app.run(); +} + +#[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 {}); +} + +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), + }; + 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); +} diff --git a/src/bin/tetris.rs b/src/bin/tetris.rs index 987ca2e..c89b901 100644 --- a/src/bin/tetris.rs +++ b/src/bin/tetris.rs @@ -1,251 +1,3 @@ -use bevy::window::PrimaryWindow; -use bevy::{prelude::*, window::WindowResolution}; -use std::fmt::{self, Display, Formatter}; -use std::ops::{Add, Sub}; - -use glite::debug_plugin; - -#[cfg_attr(feature = "debug", derive(bevy_inspector_egui::InspectorOptions))] -#[derive(Component, Debug, Default, Copy, Clone, Eq, PartialEq, Reflect)] -struct Position { - pub x: u32, - pub y: u32, - pub z: u32, // render order -} - -#[derive(Component, Debug, Reflect)] -struct Size { - width: f32, - height: f32, -} - -impl Size { - pub fn square(x: f32) -> Self { - Self { - width: x, - height: x, - } - } -} - -fn post_scale_tiles( - window: Single<&Window>, - matrix: Res, - mut q: Query<(&Size, &mut Transform), With>, -) { - for (sprite_size, mut transform) in q.iter_mut() { - transform.scale = Vec3::new( - sprite_size.width / matrix.width as f32 * window.width(), - sprite_size.height / matrix.height as f32 * window.height(), - 1.0, - ); - } -} - -fn post_translate_tiles( - window: Single<&Window>, - matrix: Res, - mut q: Query<(&Position, &mut Transform), With>, -) { - // 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 - // our sprites bottom left corner to be at the bottom left of a tile, not the center. - fn convert(pos: f32, bound_window: f32, bound_game: f32) -> f32 { - let tile_size = bound_window / bound_game; - pos / bound_game * bound_window - (bound_window / 2.) + (tile_size / 2.) - } - - for (pos, mut transform) in q.iter_mut() { - transform.translation = Vec3::new( - 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 translate_tetrominos( - tetrominos: Query<(&Tetromino, &mut Children)>, - mut positions: Query<&mut Position, With>, -) { - for (t, children) in tetrominos.iter() { - for child in children.iter() { - let mut p = positions.get_mut(*child).unwrap(); - p.x += t.pos.x; - p.y += t.pos.y; - } - } -} - -#[derive(Component, Debug, Clone, Reflect)] -struct TetrominoKind([[u32; 2]; 4]); - -const BRICK_I: TetrominoKind = TetrominoKind([[0, 0], [1, 0], [2, 0], [3, 0]]); -const BRICK_J: TetrominoKind = TetrominoKind([[0, 0], [1, 0], [2, 0], [2, 1]]); -const BRICK_L: TetrominoKind = TetrominoKind([[0, 0], [1, 0], [2, 0], [0, 1]]); -const BRICK_O: TetrominoKind = TetrominoKind([[0, 0], [1, 0], [0, 1], [1, 1]]); -const BRICK_S: TetrominoKind = TetrominoKind([[0, 0], [1, 0], [1, 1], [2, 1]]); -const BRICK_T: TetrominoKind = TetrominoKind([[0, 0], [1, 0], [2, 0], [1, 1]]); -const BRICK_Z: TetrominoKind = TetrominoKind([[0, 1], [1, 1], [1, 0], [2, 0]]); - -enum RenderLayer { - Background = 0, - Brick = 1, -} - -#[derive(Component, Debug)] -struct Tile; - -#[derive(Bundle, Debug)] -struct TileBundle { - position: Position, - size: Size, - sprite: Sprite, - tile: Tile, -} - -fn spawn_tile(commands: &mut Commands, color: Color, size: f32, position: Position) -> Entity { - commands - .spawn(TileBundle { - position, - size: Size::square(size), - sprite: Sprite { - color, - ..Default::default() - }, - tile: Tile, - }) - .id() -} - -#[derive(Component, Reflect)] -struct Tetromino { - pos: Position, - kind: TetrominoKind, -} - -fn spawn_tetromino(commands: &mut Commands, kind: TetrominoKind, x: u32, y: u32) { - let tetromino = commands - .spawn(Tetromino { - pos: Position { x, y, z: 0 }, - kind: kind.clone(), - }) - .insert((Transform::default(), Visibility::default())) - .id(); - - for coord in kind.0 { - let e = spawn_tile( - commands, - Color::srgb(0.3, 0.3, 0.8), - 0.9, - Position { - x: x + coord[0], - y: y + coord[1], - z: RenderLayer::Brick as u32, - }, - ); - commands.entity(e).set_parent(tetromino); - } -} - fn main() { - let mut app = App::new(); - app.add_plugins(DefaultPlugins.set(WindowPlugin { - primary_window: Some(Window { - title: "Tetris".to_string(), - ..default() - }), - ..default() - })); - - app.add_systems( - Startup, - (init_singletons, init_window, init_tile_grid).chain(), - ) - .add_systems( - PostUpdate, - (translate_tetrominos, post_scale_tiles, post_translate_tiles).chain(), - ); - - app.add_plugins(debug_plugin::debug_plugin); - - app.register_type::(); - app.register_type::(); - app.register_type::(); - - // Run the app - app.run(); -} - -#[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 {}); -} - -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), - }; - 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); + todo!(); }