From 9bc33ae74b4b63c6c29765457747b0e3086957c3 Mon Sep 17 00:00:00 2001 From: Christian Nieves Date: Mon, 9 Dec 2024 21:34:34 -0600 Subject: [PATCH] background grid --- src/bin/snake.rs | 3 +- src/bin/tetris.rs | 144 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 src/bin/tetris.rs diff --git a/src/bin/snake.rs b/src/bin/snake.rs index ea36aae..fc2d603 100644 --- a/src/bin/snake.rs +++ b/src/bin/snake.rs @@ -196,6 +196,7 @@ fn spawn_segment(commands: &mut Commands, pos: Position) -> Entity { }) .insert(SnakeSegment) .insert(Name::new(String::from("SnakeSegment"))) + .insert(Name::new(String::from("SnakeSegmentTest"))) .insert(pos) .insert(Size::square(0.77)) .id() @@ -287,7 +288,7 @@ impl Plugin for SnakePlugin { FixedUpdate, (snake_movement, snake_eating, snake_growth, game_over) .chain() - .run_if(on_timer(Duration::from_millis(500))), + .run_if(on_timer(Duration::from_millis(1500))), ) .add_systems(PostUpdate, (scale_translation, position_translation)); diff --git a/src/bin/tetris.rs b/src/bin/tetris.rs new file mode 100644 index 0000000..9d05383 --- /dev/null +++ b/src/bin/tetris.rs @@ -0,0 +1,144 @@ +use bevy::window::PrimaryWindow; +use bevy::{prelude::*, window::WindowResolution}; +use std::fmt::{self, Display, Formatter}; +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, +} + +impl Add for Position { + type Output = Self; + fn add(self, other: Self) -> Self { + Self { + x: self.x + other.x, + y: self.y + other.y, + } + } +} + +impl Sub for Position { + type Output = Self; + fn sub(self, other: Self) -> Self { + Self { + x: self.x.saturating_sub(other.x), + y: self.y.saturating_sub(other.y), + } + } +} + +impl Display for Position { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "({}, {})", self.x, self.y) + } +} + +#[derive(Component)] +struct Size { + width: f32, + height: f32, +} + +impl Size { + pub fn square(x: f32) -> Self { + Self { + width: x, + height: x, + } + } +} + +fn spawn_tile(commands: &mut Commands, color: Color, size: f32, position: Position) { + commands + .spawn(Sprite { + color, + ..Default::default() + }) + .insert(position) + .insert(Size::square(size)); +} + +fn scale_translation( + mut windows: Query<&mut Window, With>, + mut q: Query<(&Size, &mut Transform)>, +) { + 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(), + 1.0, + ); + } +} + +fn position_translation( + mut windows: Query<&mut Window, With>, + mut q: Query<(&Position, &mut Transform)>, +) { + // 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.) + } + + 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, + ); + } +} + +fn test_update() {} + +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_plugins(debug_plugin::debug_plugin); + + // Run the app + app.run(); +} + +fn setup_scene(mut commands: Commands) { + 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 { + 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 }); + } + } +}