1use tinybit::events::{events, Event, KeyCode, KeyEvent, EventModel};
2use tinybit::{
3 term_size, Camera, Renderer, ScreenPos, ScreenSize, StdoutTarget, Viewport,
4 WorldPos, Pixel, Color
5};
6use tinybit::widgets::{Text, Border};
7
8struct Mob {
9 pixel: Pixel,
10 world_pos: WorldPos,
11 tick: i64,
12}
13
14impl Mob {
15 fn update(&mut self) {
16 self.tick += 1;
17 if self.tick > 10 {
18 self.world_pos.x += 1;
19 self.tick = 0;
20 }
21 }
22}
23
24fn main() {
25 let (width, height) = term_size().expect("Can't get the term size? Can't play the game!");
26
27 let viewport_size = ScreenSize::new(width / 2, height / 2);
29 let mut viewport = Viewport::new(ScreenPos::new(0, 4), viewport_size);
30 let mut status_viewport = Viewport::new(ScreenPos::zero(), ScreenSize::new(width, 3));
31
32 let camera_pos = WorldPos::zero();
34 let mut camera = Camera::from_viewport(camera_pos, &viewport).with_limit(5, 5, 5, 5);
35
36 let stdout_renderer = StdoutTarget::new().expect("Failed to enter raw mode");
38 let mut renderer = Renderer::new(stdout_renderer);
39
40 let mut player = ('@', camera_pos);
42 let mut player_pixel = Pixel::new(player.0, camera.to_screen(player.1), Some(Color::Yellow), None);
43
44 let mut mob = Mob {
46 pixel: Pixel::new('&', camera.to_screen(player.1), Some(Color::Red), None),
47 world_pos: WorldPos::new(camera_pos.x - 2, camera_pos.y - 6),
48 tick: 0,
49 };
50
51 let grass_positions = field_of_grass(&camera);
53 let mut grass = grass_positions.iter().map(|_| Pixel::new(
54 'w',
55 camera.to_screen(camera.position),
56 Some(Color::Green),
57 None
58 )).collect::<Vec<_>>();
59
60 let (_, events) = events::<()>(EventModel::Fps(20));
61 for event in events {
62 match event {
63 Event::User(()) => {}
64 Event::Tick => {
65 viewport.draw_pixels(&grass);
66 viewport.draw_pixel(player_pixel);
67 mob.pixel.pos = camera.to_screen(mob.world_pos);
68 viewport.draw_pixel(mob.pixel);
69
70 mob.update();
72 let camera_border = Border::thin(Some(Color::Green), None);
73 viewport.draw_widget(&camera_border, ScreenPos::zero());
74
75 camera.track(player.1);
77 player_pixel.pos = camera.to_screen(player.1);
78 grass_positions.iter().zip(&mut grass).for_each(|(world_pos, grass)| {
79 grass.pos = camera.to_screen(*world_pos);
80 });
81
82 let status = Text::new(
84 format!("player x {} | y {} camera x {} | y {}",
85 player.1.x,
86 player.1.y,
87 camera.position.x,
88 camera.position.y,
89 ),
90 Some(Color::Red),
91 None,
92 );
93
94 let status_border = Border::new("╭─╮│╯─╰│", Some(Color::White), None);
96
97 status_viewport.swap_buffers();
98 status_viewport.draw_widget(&status_border, ScreenPos::zero());
99 status_viewport.draw_widget(&status, ScreenPos::new(1, 1));
100 let _ = renderer.render(&mut status_viewport);
101
102 let _ = renderer.render(&mut viewport);
105 viewport.swap_buffers();
106 }
107 Event::Key(KeyEvent { code: KeyCode::Esc, .. }) => break,
108 Event::Key(KeyEvent { code: kc, .. }) => {
109 match kc {
110 KeyCode::Left => { player.1.x -= 1; }
111 KeyCode::Right => { player.1.x += 1; }
112 KeyCode::Up => { player.1.y -= 1; }
113 KeyCode::Down => { player.1.y += 1; }
114 _ => {}
115 }
116 }
117 Event::Resize(_w, _h) => {}
118 }
119 }
120}
121
122fn field_of_grass<T>(camera: &Camera<T>) -> Vec<WorldPos> {
123 let pos = camera.position;
124 let field_size = 3;
125 let x_range = pos.x - field_size..pos.x + field_size;
126 let y_range = pos.y - field_size..pos.y + field_size;
127
128 let mut pixels = Vec::new();
129
130 for x in x_range {
131 for y in y_range.clone() {
132 let pos = WorldPos::new(x, y);
139 pixels.push(pos);
140 }
141 }
142
143 pixels
144}