Skip to main content

map/
map.rs

1use rusterix::prelude::*;
2// use std::path::Path;
3use theframework::*;
4use vek::{Vec2, Vec3, Vec4};
5
6#[derive(Debug, Clone, PartialEq)]
7#[allow(dead_code)]
8enum Movement {
9    Off,
10    MoveForward,
11    MoveBackward,
12    TurnLeft,
13    TurnRight,
14}
15
16use Movement::*;
17
18fn main() {
19    let cube = Map::new();
20    let app = TheApp::new();
21
22    () = app.run(Box::new(cube));
23}
24
25// This example loads a .rxm map file (of the minigame) and draws it directly
26// It does not use the Rusterix game API.
27
28pub struct Map {
29    camera: Box<dyn D3Camera>,
30    scene: Scene,
31    entity: Entity,
32    movement: Movement,
33    assets: Assets,
34}
35
36impl TheTrait for Map {
37    fn new() -> Self
38    where
39        Self: Sized,
40    {
41        let camera = Box::new(D3FirstPCamera::new());
42        let mut scene = Scene::default();
43
44        // Collect the assets and compile the world map.
45        let mut assets = Assets::default();
46        assets.collect_from_directory("minigame".into());
47        // let _ = assets.compile_source_map("world".into());
48
49        if let Some(map) = assets.get_map("world") {
50            // Build 3D scene from the world map.
51            let mut builder = D3Builder::new();
52            scene = builder.build(
53                map,
54                &assets,
55                Vec2::zero(), // Only needed for 2D builders
56                &camera.id(),
57                &ValueContainer::default(),
58            );
59        }
60
61        // Create an entity with a default position / orientation which serves as the camera.
62        let entity = rusterix::Entity {
63            position: Vec3::new(6.0600824, 1.0, 4.5524735),
64            orientation: Vec2::new(0.03489969, 0.99939084),
65            ..Default::default()
66        };
67
68        // Add logo on top of the scene
69        scene.d2_static = vec![
70            Batch2D::from_rectangle(0.0, 0.0, 200.0, 200.0)
71                .receives_light(false)
72                .source(PixelSource::StaticTileIndex(0)),
73        ];
74        // scene
75        //     .textures
76        //     .push(Tile::from_texture(Texture::from_image(Path::new(
77        //         "images/logo.png",
78        //     ))));
79
80        Self {
81            camera,
82            scene,
83            entity,
84            movement: Off,
85            assets,
86        }
87    }
88
89    /// Draw a cube and a rectangle
90    fn draw(&mut self, pixels: &mut [u8], ctx: &mut TheContext) {
91        let _start = get_time();
92
93        match &self.movement {
94            MoveForward => {
95                self.entity.move_forward(0.05);
96            }
97            MoveBackward => {
98                self.entity.move_backward(0.05);
99            }
100            TurnLeft => {
101                self.entity.turn_left(1.0);
102            }
103            TurnRight => {
104                self.entity.turn_right(1.0);
105            }
106            Off => {}
107        }
108        // self.entity.apply_to_camera(&mut self.camera);
109
110        // Set it up
111        Rasterizer::setup(
112            None,
113            self.camera.view_matrix(),
114            self.camera
115                .projection_matrix(ctx.width as f32, ctx.height as f32),
116        )
117        .ambient(Vec4::one())
118        .rasterize(
119            &mut self.scene,
120            pixels,     // Destination buffer
121            ctx.width,  // Destination buffer width
122            ctx.height, // Destination buffer height
123            40,         // Tile size
124            &self.assets,
125        );
126
127        let _stop = get_time();
128        // println!("Execution time: {:?} ms.", _stop - _start);
129    }
130
131    // Query if the widget needs a redraw, we redraw at max speed (which is not necessary)
132    fn update(&mut self, _ctx: &mut TheContext) -> bool {
133        true
134    }
135
136    fn window_title(&self) -> String {
137        "Rusterix Map Demo".to_string()
138    }
139
140    fn hover(&mut self, x: f32, y: f32, ctx: &mut TheContext) -> bool {
141        if self.camera.id() == "orbit" {
142            self.camera.set_parameter_vec2(
143                "from_normalized",
144                Vec2::new(x / ctx.width as f32, y / ctx.height as f32),
145            );
146        } else if self.camera.id() == "firstp" {
147            self.entity
148                .set_tilt_from_screen_coordinate(1.0 - y / ctx.height as f32);
149        }
150        true
151    }
152
153    fn key_down(
154        &mut self,
155        char: Option<char>,
156        _key: Option<TheKeyCode>,
157        _ctx: &mut TheContext,
158    ) -> bool {
159        if let Some(char) = char {
160            match char {
161                'p' => {
162                    self.camera = Box::new(D3FirstPCamera::new());
163                }
164                'f' => {
165                    self.camera = Box::new(D3FirstPCamera::new());
166                }
167                'i' => {
168                    self.camera = Box::new(D3IsoCamera::new());
169                }
170                'o' => {
171                    self.camera = Box::new(D3OrbitCamera::new());
172                }
173                'w' => {
174                    self.movement = MoveForward;
175                }
176                's' => {
177                    self.movement = MoveBackward;
178                }
179                'a' => {
180                    self.movement = TurnLeft;
181                }
182                'd' => {
183                    self.movement = TurnRight;
184                }
185                _ => {}
186            }
187        }
188        true
189    }
190
191    fn key_up(
192        &mut self,
193        char: Option<char>,
194        _key: Option<TheKeyCode>,
195        _ctx: &mut TheContext,
196    ) -> bool {
197        if let Some(char) = char {
198            match char {
199                // 'p' => {
200                //     self.camera = Box::new(D3FirstPCamera::new());
201                // }
202                // 'f' => {
203                //     self.camera = Box::new(D3FirstPCamera::new());
204                // }
205                // 'i' => {
206                //     self.camera = Box::new(D3IsoCamera::new());
207                // }
208                // 'o' => {
209                //     self.camera = Box::new(D3OrbitCamera::new());
210                // }
211                'w' => {
212                    if self.movement == MoveForward {
213                        self.movement = Off;
214                    }
215                }
216                's' => {
217                    if self.movement == MoveBackward {
218                        self.movement = Off;
219                    }
220                }
221                'a' => {
222                    if self.movement == TurnLeft {
223                        self.movement = Off;
224                    }
225                }
226                'd' => {
227                    if self.movement == TurnRight {
228                        self.movement = Off;
229                    }
230                }
231                _ => {}
232            }
233        }
234        true
235    }
236}
237
238fn get_time() -> u128 {
239    #[cfg(target_arch = "wasm32")]
240    {
241        web_sys::window().unwrap().performance().unwrap().now() as u128
242    }
243    #[cfg(not(target_arch = "wasm32"))]
244    {
245        let stop = std::time::SystemTime::now()
246            .duration_since(std::time::UNIX_EPOCH)
247            .expect("Time went backwards");
248        stop.as_millis()
249    }
250}