1use quaso::{
2 GameLauncher,
3 animation::frame::SpriteFrameAnimation,
4 assets::{anim_texture::AnimTextureAsset, make_directory_database, shader::ShaderAsset},
5 config::Config,
6 context::GameContext,
7 game::{GameInstance, GameState, GameStateChange},
8 third_party::{
9 raui_core::{
10 layout::CoordsMappingScaling,
11 widget::{
12 component::text_box::TextBoxProps,
13 unit::text::{TextBoxFont, TextBoxHorizontalAlign, TextBoxVerticalAlign},
14 utils::Color,
15 },
16 },
17 raui_immediate_widgets::core::text_box,
18 spitfire_draw::{
19 sprite::{Sprite, SpriteTexture},
20 utils::{Drawable, TextureRef},
21 },
22 spitfire_glow::{
23 graphics::{CameraScaling, Shader},
24 renderer::GlowTextureFiltering,
25 },
26 spitfire_input::{
27 CardinalInputCombinator, InputActionRef, InputConsume, InputMapping, VirtualAction,
28 },
29 vek::Vec2,
30 windowing::event::VirtualKeyCode,
31 },
32};
33use std::error::Error;
34
35const SPEED: f32 = 100.0;
36
37fn main() -> Result<(), Box<dyn Error>> {
38 GameLauncher::new(GameInstance::new(Preloader).setup_assets(|assets| {
39 *assets = make_directory_database("./resources/").unwrap();
40 }))
41 .title("Hello World!")
42 .config(Config::load_from_file("./resources/GameConfig.toml")?)
43 .run();
44 Ok(())
45}
46
47#[derive(Default)]
48struct Preloader;
49
50impl GameState for Preloader {
51 fn enter(&mut self, context: GameContext) {
52 context.graphics.state.color = [0.2, 0.2, 0.2, 1.0];
53 context.graphics.state.main_camera.screen_alignment = 0.5.into();
54 context.graphics.state.main_camera.scaling = CameraScaling::FitVertical(500.0);
55 context.gui.coords_map_scaling = CoordsMappingScaling::FitVertical(500.0);
56
57 context
58 .assets
59 .spawn(
60 "shader://color",
61 (ShaderAsset::new(
62 Shader::COLORED_VERTEX_2D,
63 Shader::PASS_FRAGMENT,
64 ),),
65 )
66 .unwrap();
67 context
68 .assets
69 .spawn(
70 "shader://image",
71 (ShaderAsset::new(
72 Shader::TEXTURED_VERTEX_2D,
73 Shader::TEXTURED_FRAGMENT,
74 ),),
75 )
76 .unwrap();
77 context
78 .assets
79 .spawn(
80 "shader://text",
81 (ShaderAsset::new(Shader::TEXT_VERTEX, Shader::TEXT_FRAGMENT),),
82 )
83 .unwrap();
84
85 context.assets.ensure("font://roboto.ttf").unwrap();
86
87 context
88 .assets
89 .ensure("animtexture://ferris-bongo.gif")
90 .unwrap();
91 }
92
93 fn update(&mut self, context: GameContext, _: f32) {
94 if !context.assets.is_busy() {
95 *context.state_change = GameStateChange::Swap(Box::new(State::default()));
96 }
97 }
98}
99
100#[derive(Default)]
101struct State {
102 ferris: Sprite,
103 ferris_anim: SpriteFrameAnimation,
104 movement: CardinalInputCombinator,
105 exit: InputActionRef,
106}
107
108impl GameState for State {
109 fn enter(&mut self, context: GameContext) {
110 self.ferris = Sprite::single(SpriteTexture {
111 sampler: "u_image".into(),
112 texture: TextureRef::name(""),
113 filtering: GlowTextureFiltering::Linear,
114 })
115 .pivot(0.5.into());
116
117 self.ferris_anim = context
118 .assets
119 .ensure("animtexture://ferris-bongo.gif")
120 .unwrap()
121 .access::<&AnimTextureAsset>(context.assets)
122 .build_animation(TextureRef::name("ferris-bongo.gif"));
123 self.ferris_anim.animation.speed = 0.5;
124 self.ferris_anim.animation.looping = true;
125 self.ferris_anim.animation.play();
126
127 let move_left = InputActionRef::default();
128 let move_right = InputActionRef::default();
129 let move_up = InputActionRef::default();
130 let move_down = InputActionRef::default();
131 self.movement = CardinalInputCombinator::new(
132 move_left.clone(),
133 move_right.clone(),
134 move_up.clone(),
135 move_down.clone(),
136 );
137 context.input.push_mapping(
138 InputMapping::default()
139 .consume(InputConsume::Hit)
140 .action(
141 VirtualAction::KeyButton(VirtualKeyCode::A),
142 move_left.clone(),
143 )
144 .action(
145 VirtualAction::KeyButton(VirtualKeyCode::D),
146 move_right.clone(),
147 )
148 .action(VirtualAction::KeyButton(VirtualKeyCode::W), move_up.clone())
149 .action(
150 VirtualAction::KeyButton(VirtualKeyCode::S),
151 move_down.clone(),
152 )
153 .action(VirtualAction::KeyButton(VirtualKeyCode::Left), move_left)
154 .action(VirtualAction::KeyButton(VirtualKeyCode::Right), move_right)
155 .action(VirtualAction::KeyButton(VirtualKeyCode::Up), move_up)
156 .action(VirtualAction::KeyButton(VirtualKeyCode::Down), move_down)
157 .action(
158 VirtualAction::KeyButton(VirtualKeyCode::Escape),
159 self.exit.clone(),
160 ),
161 );
162 }
163
164 fn exit(&mut self, context: GameContext) {
165 context.input.pop_mapping();
166 }
167
168 fn fixed_update(&mut self, context: GameContext, delta_time: f32) {
169 self.ferris_anim.animation.update(delta_time);
170 self.ferris_anim.apply_to_sprite(&mut self.ferris, 0);
171
172 let movement = Vec2::<f32>::from(self.movement.get());
173 self.ferris.transform.position += movement * SPEED * delta_time;
174
175 if self.exit.get().is_pressed() {
176 *context.state_change = GameStateChange::Pop;
177 }
178 }
179
180 fn draw(&mut self, context: GameContext) {
181 self.ferris.draw(context.draw, context.graphics);
182 }
183
184 fn draw_gui(&mut self, _: GameContext) {
185 text_box(TextBoxProps {
186 text: "Hello, World!".to_owned(),
187 horizontal_align: TextBoxHorizontalAlign::Center,
188 vertical_align: TextBoxVerticalAlign::Bottom,
189 font: TextBoxFont {
190 name: "roboto.ttf".to_owned(),
191 size: 50.0,
192 },
193 color: Color {
194 r: 1.0,
195 g: 1.0,
196 b: 0.0,
197 a: 1.0,
198 },
199 ..Default::default()
200 });
201 }
202}