-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathsimple.rs
162 lines (136 loc) · 4.93 KB
/
simple.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
extern crate easycurses;
extern crate yarn_spool;
use easycurses::*;
use yarn_spool::{YarnEngine, YarnHandler, NodeName};
use std::cell::{RefCell, Cell};
use std::fs;
use std::iter::repeat;
use std::rc::Rc;
use std::thread::sleep;
use std::time::Duration;
use std::time::Instant;
#[derive(PartialEq)]
enum Phase {
Dialogue(String),
Game,
}
struct GameState {
phase: RefCell<Phase>,
draw_button: (Cell<Instant>, Cell<bool>),
}
struct Handler {
state: Rc<GameState>,
}
impl YarnHandler for Handler {
fn say(&mut self, text: String) {
*self.state.phase.borrow_mut() = Phase::Dialogue(text);
}
fn choose(&mut self, _text: String, _choices: Vec<String>) {
}
fn command(&mut self, _action: String) -> Result<(), ()> {
Ok(())
}
fn end_conversation(&mut self) {
*self.state.phase.borrow_mut() = Phase::Game;
}
}
fn main() {
// Normal setup
let mut easy = EasyCurses::initialize_system().unwrap();
easy.set_cursor_visibility(CursorVisibility::Invisible);
easy.set_echo(false);
easy.set_keypad_enabled(true);
easy.set_input_mode(InputMode::Character);
easy.set_scrolling(false);
easy.set_input_timeout(TimeoutMode::Immediate);
let state = Rc::new(GameState {
phase: RefCell::new(Phase::Game),
draw_button: (Cell::new(Instant::now()), Cell::new(false)),
});
let handler = Handler { state: state.clone() };
let mut engine = YarnEngine::new(Box::new(handler));
let buffer = fs::read_to_string("examples/simple.yarn").unwrap();
engine.load_from_string(&buffer).unwrap();
// We need to know how wide our screen is.
let (row_count, col_count) = easy.get_row_col_count();
let frame_target_duration = Duration::new(1, 0).checked_div(60).expect("failed when rhs!=0, what?");
let (mut x, mut y) = (col_count / 2, row_count / 2);
let (dwarf_x, dwarf_y): (i32, i32) = (x - 5, y - 3);
loop {
let top_of_loop = Instant::now();
// Gather/process any pending input
while let Some(input) = easy.get_input() {
let is_game = &*state.phase.borrow() == &Phase::Game;
if is_game {
let (xdiff, ydiff) = match input {
Input::KeyLeft => (-1, 0),
Input::KeyRight => (1, 0),
Input::KeyDown => (0, -1),
Input::KeyUp => (0, 1),
_ => (0, 0)
};
if xdiff != 0 || ydiff != 0 {
if x + xdiff == dwarf_x && y + ydiff == dwarf_y {
engine.activate(NodeName("dwarf".to_string()));
} else {
x = (x + xdiff).max(0).min(col_count - 1);
y = (y + ydiff).max(0).min(row_count - 1);
}
}
} else {
if input == Input::Character('x') {
engine.proceed();
}
}
}
// Sleep a bit if we need to. This actually sleeps a little longer than
// just the right time because it doesn't account for the display time
// we'll use up after the sleep happens. However, curses doesn't really
// demand perfect animation anyway.
let elapsed_this_frame = top_of_loop.elapsed();
if let Some(frame_remaining) = frame_target_duration.checked_sub(elapsed_this_frame) {
sleep(frame_remaining);
}
// Display
easy.bulk_insert_delete_line(row_count);
// Dwarf
easy.move_xy(dwarf_x, dwarf_y);
easy.print_char('!');
// Player
easy.move_xy(x, y);
easy.print_char('@');
if let &Phase::Dialogue(ref s) = &*state.phase.borrow() {
let mut draw_y = 4;
let mut draw_x = col_count / 3;
easy.move_xy(draw_x, draw_y);
let border: String = repeat('#').take(col_count as usize / 3).collect();
easy.print(&border);
draw_y -= 1;
easy.move_xy(draw_x, draw_y);
easy.print_char('#');
easy.move_xy(draw_x + 2, draw_y);
easy.print(s);
easy.move_xy(draw_x * 2 - 1, draw_y);
easy.print_char('#');
draw_y -= 1;
easy.move_xy(draw_x, draw_y);
easy.print_char('#');
easy.move_xy(draw_x * 2 - 5, draw_y);
if state.draw_button.1.get() {
easy.print("(x)");
} else {
easy.print(" ");
}
easy.move_xy(draw_x * 2 - 1, draw_y);
easy.print_char('#');
draw_y -= 1;
easy.move_xy(draw_x, draw_y);
easy.print(&border);
if state.draw_button.0.get().elapsed() > Duration::from_millis(500) {
state.draw_button.0.set(Instant::now());
state.draw_button.1.set(!state.draw_button.1.get());
}
}
easy.refresh();
}
}