diff --git a/assets/sprites.png b/assets/sprites.png index 3b876e0..5e0d21c 100644 Binary files a/assets/sprites.png and b/assets/sprites.png differ diff --git a/assets/sprites.xcf b/assets/sprites.xcf index cfe4dbd..c714c30 100644 Binary files a/assets/sprites.xcf and b/assets/sprites.xcf differ diff --git a/src/display2d.rs b/src/display2d.rs index aa64324..1813fc5 100644 --- a/src/display2d.rs +++ b/src/display2d.rs @@ -1,9 +1,10 @@ use crate::{ - game::{Board, BoardIndex, Piece}, + game::{Board, BoardIndex, Piece, SelectedTile}, prelude::*, }; -const SCALE: f32 = 80.0; +const SCALE: f32 = 4.0; +const TILE_SIZE: f32 = 16.0; pub struct Display2dPlugin; @@ -21,6 +22,8 @@ impl Plugin for Display2dPlugin { .run_if(resource_exists::()) .run_if(resource_changed::()) // TODO: run_if(in_state(Display2d)) .run_if(any_with_component::()), + cursor_position.run_if(in_state(GameState::Display2d)), + selected.run_if(resource_changed::()), ), ) .add_systems(OnEnter(GameState::Display2d), (activate, draw_board)); @@ -60,7 +63,7 @@ fn load_spritesheet( ) { let atlas = TextureAtlas::from_grid( server.load("sprites.png"), - Vec2::new(16.0, 16.0), + Vec2::new(TILE_SIZE, TILE_SIZE), 5, 1, None, @@ -77,7 +80,11 @@ fn initialize_board(sprite_sheet: Option>, mut commands: Comman commands .spawn(( SpatialBundle { - transform: Transform::from_xyz(-SCALE * 3.5, -SCALE * 1.5, 0.0), + transform: Transform::from_xyz( + -SCALE * TILE_SIZE * 7.0 / 2.0, // TODO: WHY??? + -SCALE * TILE_SIZE * 3.0 / 2.0, // Why 7 and 3?? + 0.0, + ), ..default() }, Board2d, @@ -88,8 +95,9 @@ fn initialize_board(sprite_sheet: Option>, mut commands: Comman let y = i / 8; let s = (x % 2) ^ (y % 2); - let transform = Transform::from_scale(Vec3::splat(5.0)) - .with_translation(Vec3::new(SCALE * x as f32, SCALE * y as f32, 0.0)); + let transform = Transform::from_scale(Vec3::splat(SCALE)).with_translation( + Vec3::new(SCALE * 16.0 * x as f32, SCALE * 16.0 * y as f32, 0.0), + ); let sprite = TextureAtlasSprite::new(s); @@ -168,3 +176,55 @@ fn activate( *visibility = Visibility::Visible; }); } + +fn cursor_position( + mut events: EventReader, + sprite_q: Query<( + &TextureAtlasSprite, + &Handle, + &GlobalTransform, + &BoardIndex, + )>, + camera_q: Query<(&Camera, &GlobalTransform), With>, + atlases: Res>, + mut selected: ResMut, +) { + events.iter().for_each(|CursorMoved { position, .. }| { + if let Some(position) = camera_q + .iter() + .find_map(|(camera, transform)| camera.viewport_to_world_2d(transform, *position)) + { + let idx = sprite_q.iter().find_map( + |(TextureAtlasSprite { index, anchor, .. }, handle, transform, board_index)| { + // Implementation credit goes to the sprite bevy_mod_picking backend + // TODO: Upstream changes + let pos = transform.translation(); + + let size = { + let sprite_size = atlases + .get(handle) + .map(|atlas| atlas.textures.get(*index).expect("Get this rect")) + .expect("get this rect") + .size(); + let (transform_scale, _, _) = transform.to_scale_rotation_translation(); + sprite_size * transform_scale.truncate() + }; + + let center = pos.truncate() - (anchor.as_vec() * size); + let rect = Rect::from_center_half_size(center, size / 2.0); + + rect.contains(position).then_some(board_index) + }, + ); + if selected.idx != idx.cloned() { + selected.idx = idx.cloned(); + } + } + }); +} + +fn selected(selected: Res) { + if selected.idx.is_some() { + info!("Selected Tile: {:?}", selected.idx); + } +} diff --git a/src/game.rs b/src/game.rs index 3faf1a7..f937082 100644 --- a/src/game.rs +++ b/src/game.rs @@ -4,7 +4,8 @@ pub struct GamePlugin; impl Plugin for GamePlugin { fn build(&self, app: &mut App) { - app.add_systems(Startup, setup_board); + app.init_resource::() + .add_systems(Startup, setup_board); } } @@ -44,12 +45,17 @@ pub(crate) struct Board { inner: Vec>>, } -#[derive(Debug, Component, PartialEq)] +#[derive(Debug, Component, PartialEq, Clone)] pub(crate) struct BoardIndex { pub x: usize, pub y: usize, } +#[derive(Debug, Default, Resource)] +pub(crate) struct SelectedTile { + pub idx: Option, +} + impl Board { /// Returns the piece at the given location pub(crate) fn _at(&self, (_x, _y): (usize, usize)) -> Option { @@ -90,47 +96,48 @@ impl std::fmt::Display for Board { } fn setup_board(mut commands: Commands) { + use Piece::*; commands.insert_resource(Board { inner: vec![ vec![ + Some(Queen), + Some(Queen), + Some(Drone), None, None, None, None, None, - Some(Piece::Drone), - Some(Piece::Queen), - Some(Piece::Queen), ], vec![ - Some(Piece::Drone), - Some(Piece::Pawn), - Some(Piece::Pawn), + Some(Queen), + Some(Drone), + Some(Pawn), None, None, - Some(Piece::Pawn), - Some(Piece::Drone), - Some(Piece::Queen), + Some(Pawn), + Some(Pawn), + Some(Drone), ], vec![ - Some(Piece::Queen), - Some(Piece::Drone), - Some(Piece::Pawn), + Some(Drone), + Some(Pawn), + Some(Pawn), None, None, - Some(Piece::Pawn), - Some(Piece::Pawn), - Some(Piece::Drone), + Some(Pawn), + Some(Drone), + Some(Queen), ], vec![ - Some(Piece::Queen), - Some(Piece::Queen), - Some(Piece::Drone), None, None, None, None, None, + Some(Drone), + Some(Queen), + Some(Queen), ], ], }); diff --git a/src/main.rs b/src/main.rs index 300fbeb..bd95db4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,10 @@ mod display3d; mod game; mod prelude; +use std::time::Duration; + +use bevy::asset::ChangeWatcher; + use crate::prelude::*; fn main() { @@ -13,7 +17,20 @@ fn main() { .add_systems(Update, state) .add_systems(Update, loading.run_if(in_state(GameState::Loading))) .add_plugins(( - DefaultPlugins.set(ImagePlugin::default_nearest()), + DefaultPlugins + .set(ImagePlugin::default_nearest()) + .set(WindowPlugin { + primary_window: Some(Window { + title: "Martian Chess".into(), + resolution: (640., 480.).into(), + ..default() + }), + ..default() + }) + .set(AssetPlugin { + watch_for_changes: ChangeWatcher::with_delay(Duration::from_millis(200)), + ..default() + }), audio::AudioPlugin, debug::DebugPlugin, display2d::Display2dPlugin,