60fps/
60fps.rs

1extern crate easycurses;
2
3use easycurses::*;
4use std::cmp::{max, min};
5use std::iter::repeat;
6use std::thread::sleep;
7use std::time::Duration;
8use std::time::Instant;
9
10fn main() {
11  // Normal setup
12  let mut easy = EasyCurses::initialize_system().unwrap();
13  easy.set_cursor_visibility(CursorVisibility::Invisible);
14  easy.set_echo(false);
15  easy.set_keypad_enabled(true);
16  easy.set_input_mode(InputMode::Character);
17  easy.set_input_timeout(TimeoutMode::Immediate);
18  easy.set_scrolling(true);
19
20  // We need to know how wide our screen is.
21  let (_, mut col_count) = easy.get_row_col_count();
22
23  // Sadly we can't make this const since it has to unwrap and all that, but
24  // ideally this could be a const. You could use lazy_static I guess if you
25  // really cared, but it's not a huge deal.
26  let frame_target_duration = Duration::new(1, 0).checked_div(60).expect("failed when rhs!=0, what?");
27
28  // We start at an arbitrary position.
29  let mut position = 5;
30  loop {
31    let top_of_loop = Instant::now();
32    // Gather/process any pending input
33    while let Some(input) = easy.get_input() {
34      match input {
35        Input::KeyLeft => position = max(0, position - 1),
36        Input::KeyRight => position = min(col_count - 1, position + 1),
37        Input::KeyResize => {
38          col_count = easy.get_row_col_count().1;
39          position = min(col_count - 1, position);
40        }
41        other => println!("Unknown: {:?}", other),
42      }
43    }
44    // Compute what we'll display.
45    let output = repeat('#').take(position as usize).collect::<String>();
46
47    // Sleep a bit if we need to. This actually sleeps a little longer than
48    // just the right time because it doesn't account for the display time
49    // we'll use up after the sleep happens. However, curses doesn't really
50    // demand perfect animation anyway.
51    let elapsed_this_frame = top_of_loop.elapsed();
52    if let Some(frame_remaining) = frame_target_duration.checked_sub(elapsed_this_frame) {
53      sleep(frame_remaining);
54    }
55
56    // Display
57    easy.print("\n");
58    easy.print(&output);
59    easy.refresh();
60  }
61}