Skip to content

Commit c2e1479

Browse files
committed
update input system
1 parent bcda6b3 commit c2e1479

3 files changed

Lines changed: 66 additions & 81 deletions

File tree

solitaire-game/src/animation.rs

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use bevy::{
44
};
55

66
use crate::{
7-
PegMoved, Selected,
8-
board::{BoardPosition, PEG_POS, PEG_POS_RAISED},
7+
Selected,
8+
board::{BoardPosition, PEG_POS, PEG_POS_RAISED, Peg},
99
viewport_to_world,
1010
};
1111

@@ -16,27 +16,13 @@ pub struct PegAnimation;
1616
impl Plugin for PegAnimation {
1717
fn build(&self, app: &mut App) {
1818
app.add_systems(Update, snap_to_board_grid);
19-
app.add_systems(PreUpdate, follow_mouse);
20-
app.add_observer(on_peg_move);
19+
app.add_systems(Update, follow_mouse);
2120
}
2221
}
2322

24-
#[derive(Component)]
25-
struct SnapToBoardPosition;
26-
27-
fn on_peg_move(
28-
moved: On<PegMoved>,
29-
mut commands: Commands,
30-
mut request_redraw: MessageWriter<RequestRedraw>,
31-
) {
32-
commands.entity(moved.peg).insert(SnapToBoardPosition);
33-
request_redraw.write(RequestRedraw);
34-
}
35-
3623
fn snap_to_board_grid(
37-
mut commands: Commands,
38-
pegs: Query<Entity, With<SnapToBoardPosition>>,
39-
mut pos: Query<(&BoardPosition, &mut Transform), With<SnapToBoardPosition>>,
24+
pegs: Query<Entity, (With<Peg>, Without<Selected>)>,
25+
mut pos: Query<(&BoardPosition, &mut Transform)>,
4026
mut request_redraw: MessageWriter<RequestRedraw>,
4127
) {
4228
for peg in pegs {
@@ -46,10 +32,11 @@ fn snap_to_board_grid(
4632
let mut new_pos = current.lerp(target, 0.2);
4733
if new_pos.distance_squared(target) < 0.0001 {
4834
new_pos = target;
49-
commands.entity(peg).remove::<SnapToBoardPosition>();
5035
}
5136
transform.translation = new_pos;
52-
request_redraw.write(RequestRedraw);
37+
if current != new_pos {
38+
request_redraw.write(RequestRedraw);
39+
}
5340
}
5441
}
5542
}

solitaire-game/src/board.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use bevy::{ecs::entity_disabling::Disabled, prelude::*};
22
use bevy_vector_shapes::{prelude::ShapePainter, shapes::DiscPainter};
33
use solitaire_solver::{Board, Idx};
44

5-
use crate::{CurrentBoard, MoveEvent, PegMoved, input::RequestPegMove};
5+
use crate::{CurrentBoard, MoveEvent, input::RequestPegMove};
66

77
pub struct BoardPlugin;
88

@@ -226,5 +226,4 @@ fn on_move_peg(
226226
moved,
227227
skipped,
228228
});
229-
commands.trigger(PegMoved { peg: moved });
230229
}

solitaire-game/src/input.rs

Lines changed: 57 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
use bevy::{input::common_conditions::input_just_pressed, prelude::*, window::PrimaryWindow};
1+
use bevy::{
2+
input::common_conditions::{input_just_pressed, input_just_released},
3+
prelude::*,
4+
window::PrimaryWindow,
5+
};
6+
use solitaire_solver::Board;
27

38
use crate::{
4-
PegMoved, Selected,
9+
Selected,
510
board::{BoardPosition, Peg},
611
viewport_to_world,
712
};
@@ -13,10 +18,13 @@ impl Plugin for Input {
1318
fn build(&self, app: &mut App) {
1419
app.add_systems(
1520
PreUpdate,
16-
peg_selection_cursor.run_if(input_just_pressed(MouseButton::Left)),
21+
grab_peg.run_if(input_just_pressed(MouseButton::Left)),
22+
);
23+
app.add_systems(
24+
PreUpdate,
25+
release_peg.run_if(input_just_released(MouseButton::Left)),
1726
);
1827
app.add_systems(PreUpdate, peg_selection_touch);
19-
app.add_observer(on_board_clicked);
2028
}
2129
}
2230

@@ -26,83 +34,74 @@ pub struct RequestPegMove {
2634
pub dst: BoardPosition,
2735
}
2836

29-
#[derive(Resource)]
30-
struct SelectedPos(BoardPosition);
31-
32-
#[derive(Event)]
33-
struct PosClicked(BoardPosition);
34-
35-
fn on_board_clicked(
36-
clicked_pos: On<PosClicked>,
37+
fn grab_peg(
3738
mut commands: Commands,
38-
selected_pos: Option<ResMut<SelectedPos>>,
39+
window: Single<&Window, With<PrimaryWindow>>,
40+
camera_query: Single<(&Camera, &GlobalTransform)>,
3941
pegs: Query<(Entity, &BoardPosition), With<Peg>>,
4042
) {
41-
let clicked = pegs.iter().find(|(_, p)| **p == clicked_pos.0);
42-
let selected =
43-
selected_pos.map(|selected_pos| pegs.iter().find(|(_, p)| **p == selected_pos.0).unwrap());
44-
45-
match (selected, clicked) {
46-
(None, Some((clicked, clicked_pos))) => {
47-
commands.insert_resource(SelectedPos(*clicked_pos));
48-
commands.entity(clicked).insert(Selected);
49-
}
50-
(Some((selected, selected_pos)), clicked) => {
51-
commands.entity(selected).remove::<Selected>();
52-
commands.remove_resource::<SelectedPos>();
53-
commands.trigger(PegMoved { peg: selected }); // snap back
54-
if let Some((clicked, clicked_pos)) = clicked {
55-
if selected != clicked {
56-
commands.insert_resource(SelectedPos(*clicked_pos));
57-
commands.entity(clicked).insert(Selected);
43+
let (camera, camera_transform) = *camera_query;
44+
if let Some(cursor_pos) = window.cursor_position() {
45+
if let Some(world_pos_cursor) = viewport_to_world(cursor_pos, camera, camera_transform) {
46+
let board_pos = BoardPosition::from_world_space(world_pos_cursor.xy());
47+
if Board::inbounds(board_pos.into()) {
48+
if let Some(peg) = pegs.iter().find(|(_, p)| **p == board_pos).map(|(p, _)| p) {
49+
commands.entity(peg).insert(Selected);
5850
}
59-
} else {
60-
commands.trigger(RequestPegMove {
61-
src: *selected_pos,
62-
dst: clicked_pos.0,
63-
});
6451
}
65-
}
66-
_ => {}
52+
};
6753
}
6854
}
6955

70-
fn peg_selection_cursor(
56+
fn release_peg(
7157
mut commands: Commands,
7258
window: Single<&Window, With<PrimaryWindow>>,
7359
camera_query: Single<(&Camera, &GlobalTransform)>,
60+
selected_pegs: Query<(Entity, &BoardPosition), (With<Peg>, With<Selected>)>,
7461
) {
62+
let (camera, camera_transform) = *camera_query;
7563
if let Some(cursor_pos) = window.cursor_position() {
76-
let (camera, camera_transform) = *camera_query;
77-
let Some(world_pos_cursor) = viewport_to_world(cursor_pos, camera, camera_transform) else {
78-
return;
64+
if let Some(world_pos_cursor) = viewport_to_world(cursor_pos, camera, camera_transform) {
65+
let board_pos = BoardPosition::from_world_space(world_pos_cursor.xy());
66+
for (selected_peg, &current_pos) in selected_pegs {
67+
commands.entity(selected_peg).remove::<Selected>();
68+
commands.trigger(RequestPegMove {
69+
src: current_pos,
70+
dst: board_pos,
71+
});
72+
}
7973
};
80-
let board_pos = BoardPosition::from_world_space(world_pos_cursor.xy());
81-
commands.trigger(PosClicked(board_pos));
8274
}
8375
}
8476

85-
#[derive(Resource, PartialEq, Eq)]
86-
struct CurrentTouchId(u64);
87-
8877
fn peg_selection_touch(
8978
mut commands: Commands,
9079
touches: Res<Touches>,
9180
camera_query: Single<(&Camera, &GlobalTransform)>,
92-
current_touch_id: Option<Res<CurrentTouchId>>,
81+
pegs: Query<(Entity, &BoardPosition), With<Peg>>,
82+
selected_pegs: Query<(Entity, &BoardPosition), (With<Peg>, With<Selected>)>,
9383
) {
94-
for touch in touches.iter() {
95-
if touches.just_pressed(touch.id())
96-
|| Some(touch.id()) != current_touch_id.as_ref().map(|id| id.0)
97-
{
98-
let (camera, camera_transform) = *camera_query;
99-
let Some(world_pos) = viewport_to_world(touch.position(), camera, camera_transform)
100-
else {
101-
return;
102-
};
84+
let (camera, camera_transform) = *camera_query;
85+
for touch in touches.iter_just_pressed() {
86+
if let Some(world_pos) = viewport_to_world(touch.position(), camera, camera_transform) {
87+
let board_pos = BoardPosition::from_world_space(world_pos.xy());
88+
if Board::inbounds(board_pos.into()) {
89+
if let Some(peg) = pegs.iter().find(|(_, p)| **p == board_pos).map(|(p, _)| p) {
90+
commands.entity(peg).insert(Selected);
91+
}
92+
}
93+
}
94+
}
95+
for touch in touches.iter_just_released() {
96+
if let Some(world_pos) = viewport_to_world(touch.position(), camera, camera_transform) {
10397
let board_pos = BoardPosition::from_world_space(world_pos.xy());
104-
commands.trigger(PosClicked(board_pos));
98+
for (selected_peg, &current_pos) in selected_pegs {
99+
commands.entity(selected_peg).remove::<Selected>();
100+
commands.trigger(RequestPegMove {
101+
src: current_pos,
102+
dst: board_pos,
103+
});
104+
}
105105
}
106-
commands.insert_resource(CurrentTouchId(touch.id()));
107106
}
108107
}

0 commit comments

Comments
 (0)