Skip to main content

path/
path.rs

1use quaso::{
2    GameLauncher,
3    assets::{make_directory_database, shader::ShaderAsset},
4    config::Config,
5    context::GameContext,
6    game::{GameInstance, GameState},
7    third_party::{
8        anim8::{spline::Spline, utils::factor_iter},
9        spitfire_draw::{
10            primitives::PrimitivesEmitter,
11            utils::{Drawable, ShaderRef},
12        },
13        spitfire_glow::graphics::{CameraScaling, Shader},
14        spitfire_input::{
15            ArrayInputCombinator, InputAxisRef, InputConsume, InputMapping, VirtualAxis,
16        },
17        vek::{Rgba, Vec2},
18    },
19};
20use std::error::Error;
21
22fn main() -> Result<(), Box<dyn Error>> {
23    GameLauncher::new(GameInstance::new(State::default()).setup_assets(|assets| {
24        *assets = make_directory_database("./resources/").unwrap();
25    }))
26    .title("Path")
27    .config(Config::load_from_file("./resources/GameConfig.toml")?)
28    .run();
29    Ok(())
30}
31
32struct State {
33    spline: Spline<[f32; 2]>,
34    mouse_xy: Option<ArrayInputCombinator<2>>,
35}
36
37impl Default for State {
38    fn default() -> Self {
39        Self {
40            spline: Spline::smooth(
41                &[
42                    [-100.0, -100.0],
43                    [100.0, -100.0],
44                    [-100.0, 100.0],
45                    [100.0, 100.0],
46                ],
47                1.0,
48            )
49            .unwrap(),
50            mouse_xy: None,
51        }
52    }
53}
54
55impl GameState for State {
56    fn enter(&mut self, context: GameContext) {
57        context.graphics.state.color = [0.2, 0.2, 0.2, 1.0];
58        context.graphics.state.main_camera.screen_alignment = 0.5.into();
59        context.graphics.state.main_camera.scaling = CameraScaling::FitVertical(300.0);
60
61        let pointer_x = InputAxisRef::default();
62        let pointer_y = InputAxisRef::default();
63        self.mouse_xy = Some(ArrayInputCombinator::new([
64            pointer_x.clone(),
65            pointer_y.clone(),
66        ]));
67        context.input.push_mapping(
68            InputMapping::default()
69                .consume(InputConsume::Hit)
70                .axis(VirtualAxis::MousePositionX, pointer_x)
71                .axis(VirtualAxis::MousePositionY, pointer_y),
72        );
73
74        context
75            .assets
76            .spawn(
77                "shader://color",
78                (ShaderAsset::new(
79                    Shader::COLORED_VERTEX_2D,
80                    Shader::PASS_FRAGMENT,
81                ),),
82            )
83            .unwrap();
84    }
85
86    fn draw(&mut self, context: GameContext) {
87        let emitter = PrimitivesEmitter::default().shader(ShaderRef::name("color"));
88
89        let tint = Rgba::new(0.25, 0.25, 1.0, 1.0);
90        emitter
91            .emit_brush(factor_iter(50).map(|factor| {
92                (
93                    self.spline.sample(factor).into(),
94                    (1.0 - factor * factor) * 5.0,
95                    tint,
96                )
97            }))
98            .draw(context.draw, context.graphics);
99
100        for point in self.spline.points() {
101            emitter
102                .emit_circle(point.point.into(), 2.0, 0.1)
103                .tint(Rgba::new(1.0, 0.25, 0.25, 1.0))
104                .draw(context.draw, context.graphics);
105        }
106
107        if let Some(mouse_xy) = self.mouse_xy.as_ref() {
108            let source = context
109                .graphics
110                .state
111                .main_camera
112                .screen_to_world_point(mouse_xy.get().into());
113            let time = self
114                .spline
115                .find_time_closest_to_point(&source.into_array())
116                .0;
117            let target = Vec2::from(self.spline.sample(time));
118            emitter
119                .emit_circle(target, 3.0, 0.1)
120                .draw(context.draw, context.graphics);
121            emitter
122                .emit_lines([source, target])
123                .draw(context.draw, context.graphics);
124        }
125    }
126}