Skip to content

Commit ff25b47

Browse files
authored
Merge pull request #55 from just-do-halee/main
Making easy to use some features
2 parents 2ba6435 + f047be1 commit ff25b47

File tree

7 files changed

+196
-22
lines changed

7 files changed

+196
-22
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
<!-- next-header -->
22
## [Unreleased] - ReleaseDate
33

4+
## Added
5+
6+
- Added `KeyboardStateChain` and `MouseStateChain` to provide a functional interface for dealing with user input. Call `.chain()` on `KeyboardState` or `MouseState` to access them. These new structs have methods with the same names as in their `Chain`-less variants which accept closures to perform the logic, and can be chained. Contributed by [@just-do-halee](https://github.com/just-do-halee) in [#55].
7+
8+
## Improved
9+
10+
- `CollisionPair` now implements `IntoIterator`, so you can do, for example: `for label in event.pair { ... }`. Contributed by [@just-do-halee](https://github.com/just-do-halee) in [#55].
11+
12+
[#55]: https://github.com/CleanCut/rusty_engine/pull/55
13+
414
## [5.1.1] - 2022-08-01
515

616
## Improved

examples/keyboard_state.rs

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,31 +33,35 @@ fn logic(game_state: &mut Engine, _: &mut ()) {
3333

3434
// Handle keyboard input
3535
let ks = &mut game_state.keyboard_state;
36-
if ks.pressed_any(&[KeyCode::A, KeyCode::Left]) {
37-
race_car.translation.x -= move_amount;
38-
}
39-
if ks.pressed_any(&[KeyCode::D, KeyCode::Right, KeyCode::E]) {
40-
race_car.translation.x += move_amount;
41-
}
42-
if ks.pressed_any(&[KeyCode::O, KeyCode::Down, KeyCode::S]) {
43-
race_car.translation.y -= move_amount;
44-
}
4536
if ks.pressed_any(&[KeyCode::W, KeyCode::Up, KeyCode::Comma]) {
4637
race_car.translation.y += move_amount;
4738
}
48-
if ks.pressed_any(&[KeyCode::Z, KeyCode::Semicolon]) {
49-
race_car.rotation += rotation_amount;
50-
}
51-
if ks.pressed_any(&[KeyCode::C, KeyCode::J]) {
52-
race_car.rotation -= rotation_amount;
39+
if ks.pressed_any(&[KeyCode::A, KeyCode::Left]) {
40+
race_car.translation.x -= move_amount;
5341
}
54-
if ks.pressed_any(&[KeyCode::Plus, KeyCode::Equals]) {
55-
race_car.scale *= 1.0 + scale_amount;
42+
if ks.pressed_any(&[KeyCode::S, KeyCode::Down, KeyCode::O]) {
43+
race_car.translation.y -= move_amount;
5644
}
57-
if ks.pressed_any(&[KeyCode::Minus, KeyCode::Underline]) {
58-
race_car.scale *= 1.0 - scale_amount;
45+
if ks.pressed_any(&[KeyCode::D, KeyCode::Right, KeyCode::E]) {
46+
race_car.translation.x += move_amount;
5947
}
6048

49+
// If you prefer a more functional style that is equivalent to the kind of logic above,
50+
// but takes closures to run if the buttons are pressed, you can call `.chain()`
51+
ks.chain()
52+
.pressed_any(&[KeyCode::Z, KeyCode::Semicolon], |_| {
53+
race_car.rotation += rotation_amount;
54+
})
55+
.pressed_any(&[KeyCode::C, KeyCode::J], |_| {
56+
race_car.rotation -= rotation_amount;
57+
})
58+
.pressed_any(&[KeyCode::Plus, KeyCode::Equals], |_| {
59+
race_car.scale *= 1.0 + scale_amount;
60+
})
61+
.pressed_any(&[KeyCode::Minus, KeyCode::Underline], |_| {
62+
race_car.scale *= 1.0 - scale_amount;
63+
});
64+
6165
// Clamp the scale to a certain range so the scaling is reasonable
6266
race_car.scale = race_car.scale.clamp(0.1, 3.0);
6367

examples/scenarios/car_shoot.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ fn game_logic(engine: &mut Engine, game_state: &mut GameState) {
132132
if !event.pair.one_starts_with("marble") {
133133
continue;
134134
}
135-
for label in [event.pair.0, event.pair.1] {
135+
136+
for label in event.pair {
136137
engine.sprites.remove(&label);
137138
if label.starts_with("marble") {
138139
game_state.marble_labels.push(label);

src/keyboard.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,71 @@ fn sync_keyboard_events(
3030
}
3131
}
3232

33+
pub struct KeyboardStateChain(KeyboardState);
34+
35+
impl KeyboardStateChain {
36+
/// Calls the closure if a key is currently pressed
37+
#[inline]
38+
pub fn pressed(&self, key: KeyCode, mut then: impl FnMut(&KeyboardState)) -> &Self {
39+
if self.0.pressed(key) {
40+
then(&self.0);
41+
}
42+
self
43+
}
44+
/// Calls the closure if any of the keys are currently pressed
45+
#[inline]
46+
pub fn pressed_any(
47+
&self,
48+
key_codes: &[KeyCode],
49+
mut then: impl FnMut(&KeyboardState),
50+
) -> &Self {
51+
if self.0.pressed_any(key_codes) {
52+
then(&self.0);
53+
}
54+
self
55+
}
56+
/// Calls the closure if a key started being pressed this frame
57+
#[inline]
58+
pub fn just_pressed(&self, key: KeyCode, mut then: impl FnMut(&KeyboardState)) -> &Self {
59+
if self.0.just_pressed(key) {
60+
then(&self.0);
61+
}
62+
self
63+
}
64+
/// Calls the closure if any of the indicated keys started being pressed this frame
65+
#[inline]
66+
pub fn just_pressed_any(
67+
&self,
68+
key_codes: &[KeyCode],
69+
mut then: impl FnMut(&KeyboardState),
70+
) -> &Self {
71+
if self.0.just_pressed_any(key_codes) {
72+
then(&self.0);
73+
}
74+
self
75+
}
76+
/// Calls the closure if a key started being released this frame
77+
#[inline]
78+
pub fn just_released(&self, key: KeyCode, mut then: impl FnMut(&KeyboardState)) -> &Self {
79+
if self.0.just_released(key) {
80+
then(&self.0);
81+
}
82+
self
83+
}
84+
/// Calls the closure if any of the indicated keys started being released this frame
85+
#[inline]
86+
pub fn just_released_any(
87+
&self,
88+
key_codes: &[KeyCode],
89+
mut then: impl FnMut(&KeyboardState),
90+
) -> &Self {
91+
if self.0.just_released_any(key_codes) {
92+
then(&self.0);
93+
}
94+
self
95+
}
96+
}
97+
3398
/// Represents the end-state of all keys during the last frame. Access it through
3499
/// [`Engine.keyboard_state`](crate::prelude::Engine) in your game logic function.
35100
#[derive(Clone, Debug, Default)]
@@ -65,6 +130,9 @@ impl KeyboardState {
65130
pub fn just_released_any(&self, key_codes: &[KeyCode]) -> bool {
66131
key_codes.iter().any(|k| self.just_released(*k))
67132
}
133+
pub fn chain(&self) -> KeyboardStateChain {
134+
KeyboardStateChain(self.clone())
135+
}
68136
}
69137

70138
/// store bevy's keyboard state for our own use

src/mouse.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,79 @@ impl Plugin for MousePlugin {
2222
}
2323
}
2424

25+
pub struct MouseStateChain(MouseState);
26+
27+
impl MouseStateChain {
28+
/// Calls the closure if the mouse button was pressed
29+
#[inline]
30+
pub fn pressed(&self, mouse_button: MouseButton, mut then: impl FnMut(&MouseState)) -> &Self {
31+
if self.0.pressed(mouse_button) {
32+
then(&self.0);
33+
}
34+
self
35+
}
36+
/// Calls the closure if any of the indicated mouse buttons were pressed
37+
#[inline]
38+
pub fn pressed_any(
39+
&self,
40+
mouse_buttons: &[MouseButton],
41+
mut then: impl FnMut(&MouseState),
42+
) -> &Self {
43+
if self.0.pressed_any(mouse_buttons) {
44+
then(&self.0);
45+
}
46+
self
47+
}
48+
/// Calls the closure if the mouse button started being pressed during the last frame
49+
#[inline]
50+
pub fn just_pressed(
51+
&self,
52+
mouse_button: MouseButton,
53+
mut then: impl FnMut(&MouseState),
54+
) -> &Self {
55+
if self.0.just_pressed(mouse_button) {
56+
then(&self.0);
57+
}
58+
self
59+
}
60+
/// Calls the closure if any of the indicated mouse buttons were just pressed this frame
61+
#[inline]
62+
pub fn just_pressed_any(
63+
&self,
64+
mouse_buttons: &[MouseButton],
65+
mut then: impl FnMut(&MouseState),
66+
) -> &Self {
67+
if self.0.just_pressed_any(mouse_buttons) {
68+
then(&self.0);
69+
}
70+
self
71+
}
72+
/// Calls the closure if the mouse button started being released during the last frame
73+
#[inline]
74+
pub fn just_released(
75+
&self,
76+
mouse_button: MouseButton,
77+
mut then: impl FnMut(&MouseState),
78+
) -> &Self {
79+
if self.0.just_released(mouse_button) {
80+
then(&self.0);
81+
}
82+
self
83+
}
84+
/// Calls the closure if any of the indicated mouse buttons were just released this frame
85+
#[inline]
86+
pub fn just_released_any(
87+
&self,
88+
mouse_buttons: &[MouseButton],
89+
mut then: impl FnMut(&MouseState),
90+
) -> &Self {
91+
if self.0.just_released_any(mouse_buttons) {
92+
then(&self.0);
93+
}
94+
self
95+
}
96+
}
97+
2598
/// `MouseState` represents the end-state of the mouse during the last frame. This should be used
2699
/// for "real time" processing of most input (except mousewheel scrolling), where you only care
27100
/// about the final state of buttons or mouse position for your logic.
@@ -99,6 +172,9 @@ impl MouseState {
99172
pub fn just_released_any(&self, mouse_buttons: &[MouseButton]) -> bool {
100173
mouse_buttons.iter().any(|k| self.just_released(*k))
101174
}
175+
pub fn chain(&self) -> MouseStateChain {
176+
MouseStateChain(self.clone())
177+
}
102178
}
103179

104180
/// Gather the mouse events from bevy and store them for our own use

src/physics.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ impl Plugin for PhysicsPlugin {
2525
/// [Sprite]s which:
2626
/// - have colliders (you can use the `collider` example to create your own colliders)
2727
/// - have their `collision` flags set to `true`.
28-
#[derive(Clone, Debug, PartialEq)]
28+
#[derive(Clone, Debug, PartialEq, Eq)]
2929
pub struct CollisionEvent {
3030
pub state: CollisionState,
3131
pub pair: CollisionPair,
3232
}
3333

3434
/// Indicates whether a [`CollisionEvent`] is at the beginning or ending of a collision.
35-
#[derive(Clone, Copy, Debug, PartialEq)]
35+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3636
pub enum CollisionState {
3737
Begin,
3838
End,
@@ -83,6 +83,21 @@ impl CollisionPair {
8383
let b_matches = self.1.starts_with(&text);
8484
(a_matches && !b_matches) || (!a_matches && b_matches)
8585
}
86+
87+
pub fn array(&self) -> [&str; 2] {
88+
[self.0.as_str(), self.1.as_str()]
89+
}
90+
pub fn array_mut(&mut self) -> [&mut String; 2] {
91+
[&mut self.0, &mut self.1]
92+
}
93+
}
94+
95+
impl IntoIterator for CollisionPair {
96+
type Item = String;
97+
type IntoIter = std::array::IntoIter<Self::Item, 2>;
98+
fn into_iter(self) -> Self::IntoIter {
99+
[self.0, self.1].into_iter()
100+
}
86101
}
87102

88103
impl PartialEq for CollisionPair {

src/sprite.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ use std::{
190190
};
191191

192192
/// Sprite presets using the asset pack all have colliders
193-
#[derive(Copy, Clone, Debug, PartialEq)]
193+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
194194
pub enum SpritePreset {
195195
RacingBarrelBlue,
196196
RacingBarrelRed,

0 commit comments

Comments
 (0)