use crate::prelude::*; #[derive(Component)] pub struct FieldView; pub fn enter ( mut commands: Commands, asset_server: Res, mut field: ResMut, ) { let font = asset_server.load("proxima_thin.ttf"); let thread = &mut thread_rng(); 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); commands.spawn(( ScoreboardUi, TextBundle::from_sections([ TextSection::new( "score: ", TextStyle { font: font.clone(), font_size: SCOREBOARD_FONT_SIZE, color: TEXT_COLOR, }, ), TextSection::from_style(TextStyle { font, font_size: SCOREBOARD_FONT_SIZE, color: SCORE_COLOR, }), ]) .with_style(Style { position_type: PositionType::Absolute, top: SCOREBOARD_TEXT_PADDING, left: SCOREBOARD_TEXT_PADDING, ..default() }), )); // // 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))); } let mut start = vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1]; start.shuffle(thread); *field = Field(start); render_field(commands, asset_server, field.into()); } pub fn update_scoreboard (score: Res, mut query: Query<&mut Text, With>) { let mut text = query.single_mut(); text.sections[1].value = score.to_string(); } pub fn render_field ( mut commands: Commands, asset_server: Res, field: Res, ) { for (idx, &val) in field.iter().enumerate() { if val > 0 { spawn_square_at(&mut commands, val, idx, asset_server.clone()); } } } fn spawn_square_at (commands: &mut Commands, level: u32, position: usize, asset_server: AssetServer) { let font = asset_server.load("proxima_thin.ttf"); 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, font_size: 44., color: Color::WHITE, }), 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() }, FieldView)); commands.spawn((label, FieldView)); } pub fn process_inputs ( kb: Res>, gamepads: Res, button_inputs: Res>, _axes: Res>, field: ResMut, score: ResMut, ) { for key in kb.get_just_pressed() { match key { KeyCode::ArrowUp | KeyCode::KeyW => { return move_field(MoveDirection::Up, field, score); }, KeyCode::ArrowDown | KeyCode::KeyS => { return move_field(MoveDirection::Down, field, score); }, KeyCode::ArrowLeft | KeyCode::KeyA => { return move_field(MoveDirection::Left, field, score); }, KeyCode::ArrowRight | KeyCode::KeyD => { return move_field(MoveDirection::Right, field, score); }, _ => () } return; } for gamepad in gamepads.iter() { use GamepadButtonType as GBT; // is_current_gamepad_button_pressed (i ain't writing this) let icgbp = |gbt: GamepadButtonType| button_inputs.just_pressed(GamepadButton::new(gamepad, gbt)); // @TODO: think about throttling stick inputs; if this is possible, reintroduce stick // controls (with custom actuation point) // https://bevy-cheatbook.github.io/input/gamepad.html#gamepad-settings if icgbp(GBT::DPadLeft) { return move_field(MoveDirection::Left, field, score); } else if icgbp(GBT::DPadRight) { return move_field(MoveDirection::Right, field, score); } else if icgbp(GBT::DPadUp) { return move_field(MoveDirection::Up, field, score); } else if icgbp(GBT::DPadDown) { return move_field(MoveDirection::Down, field, score); } } } pub fn move_field ( direction: MoveDirection, field: ResMut, score: ResMut ) { println!("{:?} {:?}", direction, score); } pub fn redraw_field () { }