From b73a2ac5bcbe56662faf334855d374be338cd5c9 Mon Sep 17 00:00:00 2001 From: Elijah Voigt Date: Tue, 3 Oct 2023 22:17:55 -0700 Subject: [PATCH] 2D Selecting indexes works! Also improved art a bit. Still programmer art, but it's at least on theme. Inspired by the colors of Mars. --- assets/sprites.png | Bin 1930 -> 5710 bytes assets/sprites.xcf | Bin 5128 -> 4084 bytes src/display2d.rs | 72 +++++++++++++++++++++++++++++++++++++++++---- src/game.rs | 47 ++++++++++++++++------------- src/main.rs | 19 +++++++++++- 5 files changed, 111 insertions(+), 27 deletions(-) diff --git a/assets/sprites.png b/assets/sprites.png index 3b876e0317eb880613d9cf570856bf75f79e2745..5e0d21c480b84ffa976758f742f626232a933f81 100644 GIT binary patch literal 5710 zcmeHKc~BHr9&TB_h7Fx)5A;;(`X`K z)bfa^7{m~xCL4&ZN(7UzhTsvQjPANb&1#~hc(W;8fn5a;*6iy65i6-mS+&`}=&Gsd z{vF@@{l53TSMRMhrz8#y8yf~e(9q;0!yE|mUjjjXtwVx=Wpe6-e}TV_#p&7n9MTIr zU7VG*F)&}~WMD>Mtq>%fUzhr7X<*clp6*fZz`)m?;~$mZ9@=$3ZK{KNrSACY+T~>{ zM;v|dAJ2*`P0e^^c_o^+Y}c;*H`CbjYOE|`e5TrxH}Q3?#5<;8K}F$$+s!E*9e+G_ z({%O3Yb!R79QOr3@spc9UDq|zukP*N@VgD#m(E<7E<}-8A1W^8rhYbWTh@i|*?aS+ zu5h2Ioos$**74v&a`s5vddc1M-_3kq8S+rSN2ro3JEx=$nfyUo)!j*_iD5AtzaH6n z5B4{nj*Po9CCcx_$#D-d9$`f-H@BUd*tLDp3QdN_Yp}mnI~NeKoYm{i$$I^h-a*G( z-`J>2IyxhAWovc$tXm|pr#eyX{r%Y< zXa3p0AITUVSTrLick8I!51ZP{64pkxYwuiXY=7gxqln>^8P$~~+8uw`yfNjsO*ThH z_(5bjbaG7i@xOl47BeNNrPDKPVr#o4?k^2@T256+w}f}BZpyD7_hM&o=iTZm_odj< zeRW%7r^Qat{9{?u`kbtsrPp#?*_Yq>RrIE9v8BV;R!K5H-%>ubTv(&6%u<~gT_#w`&ie6|r3N$LPK#SR?*#yPeB_z#R7>Qta0+B*c z+;qW7Qi~WKwlI0DLx;3C97150)*)Fc6J~PinT2f9Vi%LPI3=B0yokbSWcswQIDr5F zc7`Wm!EST72|26~ zvkwA%>5zpy?vho97EcbZK7@D6t$3xE%)Ksu!|2`07Mr2{kEys-d)^cD1z8SZqj zq@{BhH|KFtjIn@m@X-SyXsSQo>2cY7?a-8zu`zZK>IS3Ao*6PR*<|j|5GlxG?M`17 zAp4m}p0z$D>zUd_kFTA9g@E*a+-IVn^zI7=Q6>{%;3$t+Ua~=lh~pD9N3k^Fd&M;> zB_+3FC{AkRsFG1oC@zz!P%Vimt!gcflNdPwD%s)YNe9JKyrR0-6BS}016%5jV$wW1RGq|lG<=B&Jz zbTRRHfJeX;kf)C;c(QMzraW7VcOfIr0w4^PVd#$ullC<%759uM9mh$3#7UelV8A8= z@_KDx^8$OJw0|?~;|$dMOFn&b@kdM*Z@D|k>{ z|1-M6o?fRI2RH?J!DWd`53L3ltzgT`i3aEq)C3tb>r?juOQHDPk?C*Z_MWPoLxMXL%zczL&IK{UkHnb#jKKu(GV0=oot9t z7ta6lVx#>{^QhueFVksO$eR4_Z@!KCHyzTxLA_rne%t(oGR76-A35Rb6#S!j`SdR@ zezXKVux8b$V}J68igULj$iwco49)iKmk{LYjoSI1A8sXTJjCh*sMtPX*3ttt_74`l zi>^<~@3}q#nsIxb;e1)k=4tv4KgjZNO#R5lPtP=lZ;FSY+KRdJ3LSTdGdd7ezQ8ut z+rC_KjK+Fy4ugg-Da!nOZomuEfa}JPJ>loBX9om8s~UB)_vTd8Q0_e?eo)i=BY&&7 zwf@?BbIz$-yXW2Thb&yf-B)+63%pZ!0O;L$iN^2gADv1 b8R+T^EX>4Tx04R}tkv&MmP!xqvQ>9X>4t5Z6 z$WWc^q9Ts93Pq?8YK2xEOkVm2O&XFE7e~Rh;NZ_<)xpJCR|i)?5c~mgb#YR3krMAq z3N2!M@OU5Ry>q$mTtH}6nP&AQ08O{eOe!hn@~dL#6=4Vf27fUiGs~Ehq%?fj*F6IK zyo>W%{_p-={c6EtKtLo;FvGNoH;898ZG-bZag>#1mH3=^!lVX?AGxl0{KmQDGH)7D zGn<(wjuMNdE>^mjl}(L!nmDFvI@K3)9;=+UIBV59Yxl{27%Av0%Uq{DiWC;H1PLM( z)KNhdHsW;Zq<>h*(0$U!KjQi&aw+7hfRSSXHE57sKlluOXKNLwCcR3LB+&cfI3Hs` zXcuTT9OwJkaat!p@EN$$JN{Y|nEfQZ(a~Z@G}vw6;<}?Ld%)!mF#Kf5rtC^V+Cs4i zyr0pS^1#q75MJ|gYv1Ga0mxET=^NnS5Ew5}?RB4j_c(Ru_V1f^em?=Da(SkJr0f6y z010qNS#tmYE+YT{E+YYWr9XB6000McNliru=L!M<7BC%c)XS4=5Ga3jNklx1xmUJK z`|jM}{Y}j6o#*3CvNNfQ|aidgiH&OGlu=iEEz z%!lQQRcmV7#j>_FpUEhtMm|-__Y;JSFJV(KpAV;Nuq!KH^nVkBj==)3G1$x0Bj9zV z{BMBK3bsxa8?~BQw=q|;$xACO)3D8w_QbL`wD;CNSeM9@RV=2Otw!0ZnyI=`GsWqL zh1XVAGzKue>TGG%jEb46w5*b($*$kdw(X}?Q)@S>R_Rt~wp=MTs*RR5>mb#tJT|m> z=g8bb`0+X6jOH8?-flOIqE)YGnR(2fo|AEoU1QO>W#$;{LW(POr%=O21>-?RB&D(5N-5W+K0!;mFM)_2MPY!uQR3#okEd zvv(K&PWneyNwVL(eP>AagO-I?!LZR+BA*$O{Go}bxhc7iaIX{j+e7m8lLgp({%&?* zZgJQ(KK@5*);Ahga@C0EG;St4z6hukIi$bFYe zy{)2u_*C?h8)Q)Vdaso;>3r|QF|Qq#nFqC@6LO1g~Q`~<~ZQ;=AxH4dU4hb>Xu%n`_r&dO?fv@qLeXdx@4) zf680fiEg<89RbG>kVkqPh$G+_0&;)cz~^W#hoReTqYZKq8j@K^x z`opg0txfc>{L7BNsPErBlNa~zzrBA!d?WuWyNP;E4FB+#@YmvZ{=N7bd_w&Iyhl9) Hz9#xF$I{Qo literal 5128 zcmeI0PiS0K6vpqHKbd4^GMP+_h}7h%jiz8i0tz-sqgX);HWqZ@LW0xDWHL0F37M%) zQ8Tj;bRofoNEan^kwq6F6zQTu30-v2MGaka;XRW^RIGn?(^M zH=OyMd+xdC-Fx1-Z{{VJpP6;%Gn4MS1A~J~slam)(3JGnFmLjN;^EDO+~6zoi>>r?aftYR;V1f!da+ z_iH(pJ;q*2XHMnjil+;D+X1>Yfs$Ph^0??PRPl*B01>-PZJ`dRCoKJdrAIB@we*;! z$1T0p(%YcR_52orBG;DqJ=6hpP;?IseA3eW3i0=ZA!&gR47Ki;o5V#6d})~2Ab%o% zH*B+F)zXNe@G&#qGEHt9Mw#|#7yJF>C^<%slLc~tTqKvsRdS77CpXAVa@#PLAiKzZ za+Dk+$H@Y@KrWI?g~6Tp$<8C32NqBiG3da+BOP zY)z0|WIs7dj*;VJfm|RL$t7}?TqD=X4RVv*HcTYQF0!8-CCA8dvOq47i{uiyO0JRX zhDvp-ZXAGCFR8*_P<7VyEd@31IjV`K5OfC;g2<91TZ%Ok)=sIi6uK|WS3<}bgZ5J4(7G!7?D~G$BU_U#_RUF zRVD7?)8xoet;-U@&r`i$Pn5BRys(w1#vyTfl2U2K<$qx%X$gi+dZx zKJ2-TZ6+HgzGTGpLh3MN$O|avt0C{Mn!Hnq9no1z;y(Bp^7SoMt+JAgNmo+UuO#1w z+gLS~1otrRrbN~Pz);POtH51X5_m7Wt|ZLYl>`PEM^_By>q-Lu-Ts%H2^GP7 zsXDp7@z=%Qg04xaEZwBDotI(Ssz_TEX{$OvAZ^tz{?uvHi3=lCC(2A1$2n_)9zwh* z`r%!A5XIb#u@LNy^Z*LG34THNG}0XvLu})-TW`laDSMQ^syH9v@Qj!f4#l#uf8@}=l=Tk^S6IK>NTLOvun;r1n0Rf%F@ODAM|^0-J0OHnR5gmzwk$z z{D?b4{dI7d`qSWJMz6h8w7rp?&SuK_V!=J0E}fE5zN0Ar-K+wec{ek2_xf(;S}_yU z<-INm2}01Gg2?Nc-Tc=oakX08P3!HQV@bZgb$o3cJH97>CAaDUYCDH1b()) .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,