diff --git a/Cargo.lock b/Cargo.lock index 1a27e1a..7dd2b06 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1804,6 +1804,7 @@ dependencies = [ "bevy", "itertools 0.13.0", "log", + "rand", ] [[package]] @@ -2984,6 +2985,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "presser" version = "0.3.1" @@ -3035,6 +3042,18 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", "rand_core", ] @@ -3043,6 +3062,9 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] [[package]] name = "range-alloc" diff --git a/Cargo.toml b/Cargo.toml index b99906e..d1fb95a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ anyhow = "1.0.86" bevy = { version = "0.14.0", features = ["dynamic_linking"] } itertools = "0.13.0" log = { version = "*", features = ["max_level_debug", "release_max_level_warn"] } +rand = "0.8.5" # Enable a small amount of optimization in debug mode. [profile.dev] diff --git a/src/main.rs b/src/main.rs index 9d35c97..5a72398 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,64 +1,64 @@ -use bevy::prelude::*; +mod setup; +mod prelude; -// This resource tracks the game's score -#[derive(Resource, Deref, DerefMut)] -struct Score (usize); +use prelude::*; -#[derive(Component)] -struct ScoreboardUi; - -const BG_COLOR: Color = Color::srgb(0.949, 0.937, 0.769); -const SCOREBOARD_FONT_SIZE: f32 = 44.0; -const TEXT_COLOR: Color = Color::BLACK; -const SCORE_COLOR: Color = Color::srgb(0.4, 0.05, 0.04); -const SCOREBOARD_TEXT_PADDING: Val = Val::Px(22.0); - -pub struct SqPlugin; impl Plugin for SqPlugin { fn build (&self, app: &mut App) { + + let thread = &mut thread_rng(); + + let mut start = vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1]; + + start.shuffle(thread); + // add things to your app here app .insert_resource(Score(0)) .insert_resource(ClearColor(BG_COLOR)) + .insert_resource(Field(start)) ; } } -fn setup ( - mut commands: Commands, - mut meshes: ResMut>, - mut materials: ResMut>, - asset_server: Res, -) { - commands.spawn(Camera2dBundle::default()); - commands.spawn(( - ScoreboardUi, - TextBundle::from_sections([ - TextSection::new( - "Score: ", - TextStyle { - font_size: SCOREBOARD_FONT_SIZE, - color: TEXT_COLOR, - ..default() - }, - ), - TextSection::from_style(TextStyle { - font_size: SCOREBOARD_FONT_SIZE, - color: SCORE_COLOR, - ..default() - }), - ]) - .with_style(Style { - position_type: PositionType::Absolute, - top: SCOREBOARD_TEXT_PADDING, - left: SCOREBOARD_TEXT_PADDING, - ..default() +fn spawn_square_at (commands: &mut Commands, level: u32, position: usize) { + let Some(&(x, y)) = sq_origins.get(position) else { + return; + }; + + let text = 2i32.pow(level); + let label = Text2dBundle { + text: Text::from_section(text.to_string(), TextStyle { + font_size: 48., + color: Color::WHITE, + ..Default::default() }), - )); + transform: Transform { + translation: Vec3::new(x, y, 0.0), + ..Default::default() + }, + ..Default::default() + } + ; + + commands.spawn(SpriteBundle { + sprite: Sprite { + color: sq_colors[level as usize % sq_colors.len()], + ..Default::default() + }, + transform: Transform { + translation: Vec3::new(x, y, 0.0), + scale: Vec3::new(148.0, 148.0, 1.0), + ..Default::default() + }, + ..Default::default() + }); + + commands.spawn(label); } fn update_scoreboard (score: Res, mut query: Query<&mut Text, With>) { @@ -66,6 +66,18 @@ fn update_scoreboard (score: Res, mut query: Query<&mut Text, With, + field: Res, +) { + for (idx, &val) in field.iter().enumerate() { + if val > 0 { + spawn_square_at(&mut commands, val, idx); + } + } +} + fn main () { App::new() @@ -76,7 +88,8 @@ fn main () { }), ..Default::default() }), SqPlugin)) - .add_systems(Startup, setup) + .add_systems(Startup, setup::setup) .add_systems(Update, update_scoreboard) + .add_systems(Update, render_field) .run(); } diff --git a/src/prelude.rs b/src/prelude.rs new file mode 100644 index 0000000..5d65f66 --- /dev/null +++ b/src/prelude.rs @@ -0,0 +1,47 @@ +pub use bevy::prelude::*; +pub use rand::{ seq::SliceRandom, thread_rng, Rng }; + +#[derive(Resource, Deref, DerefMut)] +pub struct Score (pub usize); + +#[derive(Component)] +pub struct ScoreboardUi; + + +#[derive(Resource, Deref, DerefMut)] +pub struct Field (pub Vec); + + +pub const BG_COLOR: Color = Color::srgb(0.949, 0.937, 0.769); +pub const SCOREBOARD_FONT_SIZE: f32 = 44.0; +pub const TEXT_COLOR: Color = Color::BLACK; +pub const SCORE_COLOR: Color = Color::srgb(0.4, 0.05, 0.04); +pub const SCOREBOARD_TEXT_PADDING: Val = Val::Px(22.0); + +pub struct SqPlugin; + +pub const sq_origins: [(f32, f32); 16] = [ + (-225., 225.), (-75., 225.), (75., 225.), (225., 225.,), + (-225., 75.), (-75., 75.), (75., 75.), (225., 75.,), + (-225., -75.), (-75., -75.), (75., -75.), (225., -75.,), + (-225., -225.), (-75., -225.), (75., -225.), (225., -225.,), +]; + +pub const sq_colors: [Color; 16] = [ + Color::srgb(0.373, 0.851, 0.91), + Color::srgb(0.373, 0.643, 0.91), + Color::srgb(0.247, 0.161, 0.761), + Color::srgb(0.451, 0.161, 0.761), + Color::srgb(0.502, 0.047, 0.98), + Color::srgb(0.663, 0.137, 0.91), + Color::srgb(0.443, 0.102, 0.6), + Color::srgb(0.851, 0.094, 0.773), + Color::srgb(0.89, 0.086, 0.412), + Color::srgb(0.91, 0.102, 0.102), + Color::srgb(0.671, 0.039, 0.039), + Color::srgb(0.82, 0.251, 0.059), + Color::srgb(0.851, 0.71, 0.039), + Color::srgb(0.569, 0.184, 0.051), + Color::srgb(0.016, 0.055, 0.231), + Color::srgb(0.02, 0.02, 0.02), +]; diff --git a/src/setup.rs b/src/setup.rs new file mode 100644 index 0000000..036f503 --- /dev/null +++ b/src/setup.rs @@ -0,0 +1,79 @@ +use crate::prelude::*; + +pub fn setup ( + mut commands: Commands, + mut _meshes: ResMut>, + mut _materials: ResMut>, + _asset_server: Res, +) { + commands.spawn(Camera2dBundle::default()); + + commands.spawn(( + ScoreboardUi, + TextBundle::from_sections([ + TextSection::new( + "Score: ", + TextStyle { + font_size: SCOREBOARD_FONT_SIZE, + color: TEXT_COLOR, + ..default() + }, + ), + TextSection::from_style(TextStyle { + font_size: SCOREBOARD_FONT_SIZE, + color: SCORE_COLOR, + ..default() + }), + ]) + .with_style(Style { + position_type: PositionType::Absolute, + top: SCOREBOARD_TEXT_PADDING, + left: SCOREBOARD_TEXT_PADDING, + ..default() + }), + )); + + draw_board(&mut commands); +} + + +fn draw_board (commands: &mut Commands) { + + let borders = [-305., 305.]; + let lines = [-150., 0., 150.]; + + let border_width = 10.; + let line_width = 1.; + let length = 620.; + + let border_color = Color::BLACK; + let line_color = Color::srgba(0., 0., 0., 0.667); + let bg_color = Color::srgba(0.2, 0.01, 0.5, 0.632); + + // bg + commands.spawn(SpriteBundle { + sprite: Sprite { color: bg_color, ..Default::default() }, + transform: Transform { + scale: Vec3::new(length, length, 1.0), + ..Default::default() + }, + ..Default::default() + }); + + let line = |color: Color, translation: Vec3, scale: Vec3| SpriteBundle { + sprite: Sprite { color, ..Default::default() }, + transform: Transform { translation, scale, ..Default::default() }, + ..Default::default() + }; + + // @TODO variable grid size + for border in 0..2 { + commands.spawn(line(border_color, Vec3::new(borders[border], 0.0, 0.0), Vec3::new(border_width, length, 1.0))); + commands.spawn(line(border_color, Vec3::new(0.0, borders[border], 0.0), Vec3::new(length, border_width, 1.0))); + } + + for mesh in 0..3 { + commands.spawn(line(line_color, Vec3::new(lines[mesh], 0.0, 0.0), Vec3::new(line_width, length, 1.0))); + commands.spawn(line(line_color, Vec3::new(0.0, lines[mesh], 0.0), Vec3::new(length, line_width, 1.0))); + } +}