1#![warn(missing_docs)]
2#![warn(rustdoc::missing_doc_code_examples)]
3
4pub mod camera;
7pub mod collider;
8pub mod component;
9pub mod gl;
10pub mod input;
11pub mod math;
12pub mod mesh;
13pub mod particle;
14pub mod renderer;
15pub mod shader;
16pub mod texture;
17pub mod transform;
18pub mod ui;
19pub mod utils;
20pub mod web;
21
22use wasm_bindgen::prelude::*;
23
24use camera::Camera;
25use gl::GL;
26use input::InputManager;
27pub use math::*;
28use particle::ParticleSystem;
29use renderer::Renderer;
30use shader::Shader;
31use texture::Texture;
32use transform::Transform;
33use utils::set_panic_hook;
34use web::Canvas;
35
36#[cfg(feature = "wee_alloc")]
39#[global_allocator]
40static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
41
42#[wasm_bindgen]
44pub struct Application {
45 renderer: Renderer,
46 input: InputManager,
47}
48
49impl Default for Application {
50 fn default() -> Self {
51 set_panic_hook();
53 Self {
54 renderer: Renderer::default(),
55 input: InputManager::new(),
56 }
57 }
58}
59
60#[allow(clippy::unused_unit)]
61#[wasm_bindgen]
62impl Application {
63 #[wasm_bindgen(constructor)]
65 pub fn new() -> Self {
66 Self::default()
67 }
68
69 #[wasm_bindgen]
71 pub fn init(&mut self) {
72 let renderer = &mut self.renderer;
73
74 renderer
75 .gl
76 .blend_func(GL::SRC_ALPHA, GL::ONE_MINUS_SRC_ALPHA);
77 renderer.gl.enable(GL::BLEND);
78 renderer.init_shader();
80
81 let u_tex0 = renderer.program.get_uniform_location(&renderer.gl, "uTex0");
82 renderer.gl.uniform1i(u_tex0.as_ref(), 0);
83
84 renderer.add_texture("TILEMAP", Texture::new_with_texture_id(&renderer.gl, 0));
85 renderer.add_texture("SHREK", Texture::new_with_texture_id(&renderer.gl, 1));
86
87 renderer.use_texture("WHITE");
88
89 let simple = ParticleSystem::new_from_emission_and_position(
90 particle::ParticleProps::default(),
91 0.0,
92 0.0,
93 );
94 renderer.add_component("DEFAULT", Box::new(simple));
95
96 let fire = ParticleSystem::new_from_emission_and_position(
97 particle::ParticleProps::fire(),
98 -5.0,
99 0.0,
100 );
101 renderer.add_component("FIRE", Box::new(fire));
102
103 let smoke = ParticleSystem::new_from_emission_and_position(
104 particle::ParticleProps::smoke(),
105 5.0,
106 0.0,
107 );
108 renderer.add_component("SMOKE", Box::new(smoke));
109
110 renderer.init_components();
111 }
112
113 #[wasm_bindgen]
115 pub fn resize(&mut self, width: f32, height: f32) {
116 self.renderer.resize(width, height);
117 }
118
119 #[wasm_bindgen]
121 pub fn input(&mut self, key_code: u8, is_down: bool) {
122 if is_down {
123 self.input.key_down(key_code);
124 } else {
125 self.input.key_up(key_code);
126 }
127 }
128
129 #[wasm_bindgen]
131 pub fn mouse_move(&mut self, mouse_x: i32, mouse_y: i32) {
132 let (x, y) = self
133 .renderer
134 .camera
135 .screen_to_world_coordinates(mouse_x as f32, mouse_y as f32);
136 self.input.mouse_position = Vec2::new(x, y);
137 }
138
139 #[wasm_bindgen]
143 pub fn render(&mut self, delta_time: u32) {
144 let renderer = &mut self.renderer;
145 let delta_time = delta_time as f32 / 1000.0;
146
147 renderer.clear([0.5, 0.2, 0.3, 1.0]);
148
149 if self.input.get_key_state(b'R') {
150 renderer.init_components();
151 }
152 if self.input.get_key_state(b'1') {
153 renderer
154 .get_mut_component::<ParticleSystem>("FIRE")
155 .unwrap()
156 .toggle_alive();
157 }
158 if self.input.get_key_state(b'2') {
159 renderer
160 .get_mut_component::<ParticleSystem>("DEFAULT")
161 .unwrap()
162 .toggle_alive();
163 }
164 if self.input.get_key_state(b'3') {
165 renderer
166 .get_mut_component::<ParticleSystem>("SMOKE")
167 .unwrap()
168 .toggle_alive();
169 }
170 let horizontal =
171 self.input.get_key_state(b'D') as i32 - self.input.get_key_state(b'A') as i32;
172 let vertical =
173 self.input.get_key_state(b'S') as i32 - self.input.get_key_state(b'W') as i32;
174
175 let simple = renderer
176 .get_mut_component::<ParticleSystem>("DEFAULT")
177 .unwrap();
178
179 simple.transform.position = self.input.mouse_position;
180
181 let smoke = renderer
182 .get_mut_component::<ParticleSystem>("SMOKE")
183 .unwrap();
184
185 if smoke.alive {
186 smoke.transform.position +=
187 Vec2::new(horizontal as f32 * delta_time, vertical as f32 * delta_time);
188 }
189
190 renderer.update_components(delta_time);
191
192 renderer.draw_components();
193
194 }
200}