world/
world.rs

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    // Viewport
28    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    // Camera
33    let camera_pos = WorldPos::zero();
34    let mut camera = Camera::from_viewport(camera_pos, &viewport).with_limit(5, 5, 5, 5);
35
36    // Renderer
37    let stdout_renderer = StdoutTarget::new().expect("Failed to enter raw mode");
38    let mut renderer = Renderer::new(stdout_renderer);
39
40    // Player
41    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    // Mob
45    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    // "Grass"
52    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                // Move the mob to the right
71                mob.update();
72                let camera_border = Border::thin(Some(Color::Green), None);
73                viewport.draw_widget(&camera_border, ScreenPos::zero());
74
75                // Track the player
76                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                // Status
83                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                // Status border
95                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                // Render and swap the buffers so there is no 
103                // residual characters
104                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 pixel = Pixel::new(
133            //     '%', 
134            //     camera.to_screen(WorldPos::new(x as f32, y as f32)),
135            //     Some(Color::Green),
136            //     None
137            // );
138            let pos = WorldPos::new(x, y);
139            pixels.push(pos);
140        }
141    }
142
143    pixels
144}