I have an async select macro loop that handles user inputs and event intervals within a CLI game that I am writing. I would like to be able to conditionally set a sleep countdown within it as well. I have tried declaring an Option<Sleep>
that's value gets set every iteration of the loop checking if the condition is met.
async fn run(game: &mut Game) {
let mut reader = EventStream::new();
draw().unwrap();
let mut render_interval = interval(Duration::from_nanos(1_000_000_000 / TARGET_FRAME_RATE));
let mut drop_interval = interval(Duration::from_millis(1_000 / game.level as u64));
let mut lock_delay: Option<Sleep>;
loop {
lock_delay = if game.locking { Some(sleep(Duration::from_millis(500))) } else { None }; // check if condition has been met yet
select! {
maybe_event = reader.next().fuse() => {
match maybe_event {
Some(Ok(event)) => {
if let Event::Key(key) = event {
match key.code {
KeyCode::Char('w') | KeyCode::Char('W') | KeyCode::Up => {
game.rotate(RotationDirection::Clockwise)
},
KeyCode::Char('a') | KeyCode::Char('A') | KeyCode::Left => {
game.shift(ShiftDirection::Left)
},
KeyCode::Char('s') | KeyCode::Char('S') | KeyCode::Down => {
game.soft_drop()
},
KeyCode::Char('d') | KeyCode::Char('D') | KeyCode::Right => {
game.shift(ShiftDirection::Right)
},
KeyCode::Char(' ') => {
game.hard_drop()
},
KeyCode::Char('z') | KeyCode::Char('Z') => {
game.rotate(RotationDirection::CounterClockwise)
},
KeyCode::Char('c') | KeyCode::Char('C') => {
game.hold()
},
KeyCode::Char('q') | KeyCode::Char('Q') | KeyCode::Esc => {
break
},
_ => (),
}
}
},
Some(Err(error)) => panic!("{}", error),
None => (),
}
},
_ = drop_interval.tick() => {
game.shift(ShiftDirection::Down)
},
_ = lock_delay => {
debug_println!("PLACING");
game.place();
},
_ = render_interval.tick() => {
render(game).unwrap()
},
};
}
}
This of course does not work as lock_interval is not a Future
type and cannot be used as a branch within the select.
`Option<Sleep>` is not a future
the trait `futures::Future` is not implemented for `Option<Sleep>`
Option<Sleep> must be a future or must implement `IntoFuture` to be awaitedrustcClick for full compiler diagnostic
I have tried quite a few other approaches such as using Duration::from_secs(u64::MAX)
instead of None
when the condition returns false
, avoiding the need for an Option
but it did not seem to work.
I have also attempted to use some advice from an older reddit thread: https://www.reddit.com/r/learnrust/comments/zh4deb/tokioselect_on_an_option_using_if/, but it was to no success.
In short, I need some way that I can conditionally set a sleep countdown within a select macro.
Any help or ideas would be much appreciated, I have limited asynchronous programming experience, and I'm sure there is a completely different approach to the problem.