musi_lili/api.rs
1// SPDX-FileCopyrightText: 2024 jan Wiwi <vivi-ui@tuta.io>
2// SPDX-License-Identifier: LGPL-3.0-only
3
4pub use tan_lili::{
5 specs::{
6 rgb, Color, Palette, CHAR_HEIGHT, CHAR_WIDTH, DISPLAY_HEIGHT, DISPLAY_WIDTH, MAP_HEIGHT,
7 MAP_WIDTH, SPRITE_HEIGHT, SPRITE_WIDTH,
8 },
9 Button, GameData, Key, Point,
10};
11
12#[cfg(feature = "private_api")]
13pub use tan_lili::Lili;
14
15#[cfg(feature = "private_api")]
16pub use tan_lili::Game;
17
18/// This struct give access to the main api of the musi lili engine.
19///
20/// It can be used to check current states of buttons, keys and the mouse.
21///
22/// It can be used to draw on the screen.
23///
24/// ### Example
25///
26/// ```rust
27/// use musi_lili::{Game, Lili};
28///
29/// struct MyGame;
30///
31/// impl Game for MyGame {
32/// fn init(_lili: &Lili) -> Self {
33/// Self
34/// }
35///
36/// fn update(&mut self, _lili: &Lili) {
37/// // the code to update your game
38/// }
39///
40/// fn draw(&mut self, lili: &Lili) {
41/// // draw your game
42/// lili.clear(0);
43/// lili.txt("toki", 5, 5, 3);
44/// }
45///# }
46///
47/// fn main() {
48/// # return; // Don't run a window in an example
49/// musi_lili::run::<MyGame>(musi_lili::load!("my-game"));
50///}
51/// ```
52#[cfg(not(feature = "private_api"))]
53pub struct Lili {
54 lili: tan_lili::Lili,
55}
56
57// public api
58#[cfg(not(feature = "private_api"))]
59impl Lili {
60 /// Sets all pixel of the screen to the given color.
61 ///
62 /// * `color`: the color to fill the screen with (needs to be a value between 0 and 3).
63 ///
64 /// ### Example
65 ///
66 /// ```rust
67 /// # use musi_lili::{Game, Lili};
68 /// # struct MyGame;
69 /// # impl Game for MyGame {
70 /// # fn init(_lili: &Lili) -> Self {Self}
71 /// # fn update(&mut self, _lili: &Lili) {}
72 /// fn draw(&mut self, lili: &Lili) {
73 /// // clears the screen with color 0
74 /// lili.clear(0);
75 /// }
76 ///# }
77 ///
78 /// # fn main() {
79 /// # return; // Don't run a window in an example
80 /// # musi_lili::run::<MyGame>(musi_lili::load!("my-game"));
81 /// # }
82 /// ```
83 pub fn clear(&self, color: u8) {
84 self.lili.clear(color);
85 }
86
87 /// Sets the position of the camera.
88 ///
89 /// * `x`: the x offset of the camera.
90 /// * `y`: the y offset of the camera.
91 ///
92 /// ### Example
93 ///
94 /// ```rust
95 /// # use musi_lili::{Game, Lili};
96 /// # struct MyGame;
97 /// # impl Game for MyGame {
98 /// # fn init(_lili: &Lili) -> Self {Self}
99 /// # fn update(&mut self, _lili: &Lili) {}
100 /// fn draw(&mut self, lili: &Lili) {
101 /// lili.clear(0);
102 /// lili.cam(5, 5);
103 /// // the rect starts now at (6/6) instead of (5/5)
104 /// lili.rect(1, 1, 5, 5, 3);
105 /// }
106 ///# }
107 ///
108 /// # fn main() {
109 /// # return; // Don't run a window in an example
110 /// # musi_lili::run::<MyGame>(musi_lili::load!("my-game"));
111 /// # }
112 /// ```
113 pub fn cam(&self, x: i32, y: i32) {
114 self.lili.cam(x, y);
115 }
116
117 /// Defines a color that is ignored during drawing operations.
118 ///
119 /// * `color`: the color that should be ignored. Set it to `None` to reset the ignored color.
120 ///
121 /// ### Example
122 ///
123 /// ```rust
124 /// # use musi_lili::{Game, Lili};
125 /// # struct MyGame;
126 /// # impl Game for MyGame {
127 /// # fn init(_lili: &Lili) -> Self {Self}
128 /// # fn update(&mut self, _lili: &Lili) {}
129 /// fn draw(&mut self, lili: &Lili) {
130 /// // clears the screen with color 0
131 /// lili.clear(0);
132 /// lili.tra(Some(1));
133 /// // now only the second rect with color 2 is visible
134 /// lili.rect(0, 0, 5, 5, 1);
135 /// lili.rect(1, 1, 4, 4, 2);
136 /// }
137 ///# }
138 ///
139 /// # fn main() {
140 /// # return; // Don't run a window in an example
141 /// # musi_lili::run::<MyGame>(musi_lili::load!("my-game"));
142 /// # }
143 /// ```
144 pub fn tra(&self, color: Option<u8>) {
145 self.lili.tra(color);
146 }
147
148 /// Defines a clipping region. It will be drawn only the stuff that is inside of the defined area.
149 ///
150 /// * `x`: the x coordinate of the clipping area.
151 /// * `y`: the y coordinate of the clipping area.
152 ///
153 /// ### Example
154 ///
155 /// ```rust
156 /// # use musi_lili::{Game, Lili};
157 /// # struct MyGame;
158 /// # impl Game for MyGame {
159 /// # fn init(_lili: &Lili) -> Self {Self}
160 /// # fn update(&mut self, _lili: &Lili) {}
161 /// fn draw(&mut self, lili: &Lili) {
162 /// lili.clear(0);
163 /// lili.clip(2, 2, 10, 10);
164 /// // on the screen only the part of the rect is visible that is inside the clipping area.
165 /// lili.fill_rect(0, 0, 14, 14, 3);
166 /// }
167 ///# }
168 ///
169 /// # fn main() {
170 /// # return; // Don't run a window in an example
171 /// # musi_lili::run::<MyGame>(musi_lili::load!("my-game"));
172 /// # }
173 /// ```
174 pub fn clip(&self, x: i32, y: i32, width: u32, height: u32) {
175 self.lili.clip(x, y, width, height);
176 }
177
178 /// Resets the current clipping region. Check `clip`.
179 ///
180 /// ### Example
181 ///
182 /// ```rust
183 /// # use musi_lili::{Game, Lili};
184 /// # struct MyGame;
185 /// # impl Game for MyGame {
186 /// # fn init(_lili: &Lili) -> Self {Self}
187 /// # fn update(&mut self, _lili: &Lili) {}
188 /// fn draw(&mut self, lili: &Lili) {
189 /// lili.clear(0);
190 /// lili.clip(2, 2, 10, 10);
191 /// // on the screen only the part of the rect is visible that is inside the clipping area.
192 /// lili.fill_rect(0, 0, 14, 14, 3);
193 /// lili.res_clip();
194 /// // this rect is now full visible
195 /// lili.fill_rect(0, 0, 12, 12, 2);
196 /// }
197 ///# }
198 ///
199 /// # fn main() {
200 /// # return; // Don't run a window in an example
201 /// # musi_lili::run::<MyGame>(musi_lili::load!("my-game"));
202 /// # }
203 /// ```
204 pub fn res_clip(&self) {
205 self.lili.res_clip();
206 }
207
208 /// Draws a single pixel on the given coordinate.
209 ///
210 /// * `x`: the x coordinate of the pixel.
211 /// * `y`: the y coordinate of the pixel.
212 /// * `color`: the color of the pixel (needs to be a value between 0 and 3).
213 ///
214 /// ### Example
215 ///
216 /// ```rust
217 /// # use musi_lili::{Game, Lili};
218 /// # struct MyGame;
219 /// # impl Game for MyGame {
220 /// # fn init(_lili: &Lili) -> Self {Self}
221 /// # fn update(&mut self, _lili: &Lili) {}
222 /// fn draw(&mut self, lili: &Lili) {
223 /// lili.clear(0);
224 /// // draws a pixel on (2/3) with color 3.
225 /// lili.pix(0, 0, 3);
226 /// }
227 ///# }
228 ///
229 /// # fn main() {
230 /// # return; // Don't run a window in an example
231 /// # musi_lili::run::<MyGame>(musi_lili::load!("my-game"));
232 /// # }
233 /// ```
234 pub fn pix(&self, x: i32, y: i32, color: u8) {
235 self.lili.pix(x, y, color);
236 }
237
238 /// Draws a bordered rectangle.
239 ///
240 /// * `x0`: the start x coordinate (top-left).
241 /// * `y0`: the start y coordinate (top-left).
242 /// * `x1`: the end x coordinate (bottom-right).
243 /// * `y1`: the end y coordinate (bottom-right).
244 /// * `color`: the color of the rectangles border (needs to be a value between 0 and 3).
245 ///
246 /// ### Example
247 ///
248 /// ```rust
249 /// # use musi_lili::{Game, Lili};
250 /// # struct MyGame;
251 /// # impl Game for MyGame {
252 /// # fn init(_lili: &Lili) -> Self {Self}
253 /// # fn update(&mut self, _lili: &Lili) {}
254 /// fn draw(&mut self, lili: &Lili) {
255 /// lili.clear(0);
256 /// // draws a rect with width of 2 and height of 5
257 /// lili.rect(1, 1, 3, 6, 3);
258 /// }
259 ///# }
260 ///
261 /// # fn main() {
262 /// # return; // Don't run a window in an example
263 /// # musi_lili::run::<MyGame>(musi_lili::load!("my-game"));
264 /// # }
265 /// ```
266 pub fn rect(&self, x0: i32, y0: i32, x1: i32, y1: i32, color: u8) {
267 self.lili.rect(x0, y0, x1, y1, color);
268 }
269
270 /// Draws a filled rectangle.
271 ///
272 /// * `x0`: the start x coordinate (top-left).
273 /// * `y0`: the start y coordinate (top-left).
274 /// * `x1`: the end x coordinate (bottom-right).
275 /// * `y1`: the end y coordinate (bottom-right).
276 /// * `color`: the color of the rect (needs to be a value between 0 and 3).
277 ///
278 /// ### Example
279 ///
280 /// ```rust
281 /// # use musi_lili::{Game, Lili};
282 /// # struct MyGame;
283 /// # impl Game for MyGame {
284 /// # fn init(_lili: &Lili) -> Self {Self}
285 /// # fn update(&mut self, _lili: &Lili) {}
286 /// fn draw(&mut self, lili: &Lili) {
287 /// lili.clear(0);
288 /// // draws a rect with width of 2 and height of 5
289 /// lili.fill_rect(1, 1, 3, 6, 3);
290 /// }
291 ///# }
292 ///
293 /// # fn main() {
294 /// # return; // Don't run a window in an example
295 /// # musi_lili::run::<MyGame>(musi_lili::load!("my-game"));
296 /// # }
297 /// ```
298 pub fn fill_rect(&self, x0: i32, y0: i32, x1: i32, y1: i32, color: u8) {
299 self.lili.fill_rect(x0, y0, x1, y1, color);
300 }
301
302 /// Draws a bordered circle.
303 ///
304 /// * `x`: the x coordinate of the center of the circle.
305 /// * `y`: the y coordinate of the center of the circle.
306 /// * `radius`: the radius of the circle.
307 /// * `color`: the color of the circles border (needs to be a value between 0 and 3).
308 ///
309 /// ### Example
310 ///
311 /// ```rust
312 /// # use musi_lili::{Game, Lili};
313 /// # struct MyGame;
314 /// # impl Game for MyGame {
315 /// # fn init(_lili: &Lili) -> Self {Self}
316 /// # fn update(&mut self, _lili: &Lili) {}
317 /// fn draw(&mut self, lili: &Lili) {
318 /// lili.clear(0);
319 /// // draws bordered circle with center (x: 5, y: 5)
320 /// lili.circ(5, 5, 5, 3);
321 /// }
322 ///# }
323 ///
324 /// # fn main() {
325 /// # return; // Don't run a window in an example
326 /// # musi_lili::run::<MyGame>(musi_lili::load!("my-game"));
327 /// # }
328 /// ```
329 pub fn circ(&self, x: i32, y: i32, radius: u32, color: u8) {
330 self.lili.circ(x, y, radius, color)
331 }
332
333 /// Draws a filled circle.
334 ///
335 /// * `x`: the x coordinate of the center of the circle.
336 /// * `y`: the y coordinate of the center of the circle.
337 /// * `radius`: the radius of the circle.
338 /// * `color`: the fill color of the circle (needs to be a value between 0 and 3).
339 ///
340 /// ### Example
341 ///
342 /// ```rust
343 /// # use musi_lili::{Game, Lili};
344 /// # struct MyGame;
345 /// # impl Game for MyGame {
346 /// # fn init(_lili: &Lili) -> Self {Self}
347 /// # fn update(&mut self, _lili: &Lili) {}
348 /// fn draw(&mut self, lili: &Lili) {
349 /// lili.clear(0);
350 /// // draws bordered circle with center (x: 5, y: 5)
351 /// lili.fill_circ(5, 5, 5, 3);
352 /// }
353 ///# }
354 ///
355 /// # fn main() {
356 /// # return; // Don't run a window in an example
357 /// # musi_lili::run::<MyGame>(musi_lili::load!("my-game"));
358 /// # }
359 /// ```
360 pub fn fill_circ(&self, x: i32, y: i32, radius: u32, color: u8) {
361 self.lili.fill_circ(x, y, radius, color)
362 }
363
364 /// Draws a line form x0/y0 to x1/y1
365 ///
366 /// * `x0`: the start x coordinate (top-left).
367 /// * `y0`: the start y coordinate (top-left).
368 /// * `x1`: the end x coordinate (bottom-right).
369 /// * `y1`: the end y coordinate (bottom-right).
370 /// * `color`: the color of the line (needs to be a value between 0 and 3).
371 ///
372 /// ### Example
373 ///
374 /// ```rust
375 /// # use musi_lili::{Game, Lili};
376 /// # struct MyGame;
377 /// # impl Game for MyGame {
378 /// # fn init(_lili: &Lili) -> Self {Self}
379 /// # fn update(&mut self, _lili: &Lili) {}
380 /// fn draw(&mut self, lili: &Lili) {
381 /// lili.clear(0);
382 /// // draws a line from (1/1) to (3/6)
383 /// lili.line(1, 1, 3, 6, 3);
384 /// }
385 ///# }
386 ///
387 /// # fn main() {
388 /// # return; // Don't run a window in an example
389 /// # musi_lili::run::<MyGame>(musi_lili::load!("my-game"));
390 /// # }
391 /// ```
392 pub fn line(&self, x0: i32, y0: i32, x1: i32, y1: i32, color: u8) {
393 self.lili.line(x0, y0, x1, y1, color);
394 }
395
396 /// Prints a text.
397 ///
398 /// * `text`: the text to display.
399 /// * `x`: the x coordinate of the text.
400 /// * `y`: the y coordinate of the text.
401 /// * `color`: the color of the text (needs to be a value between 0 and 3).
402 ///
403 /// ### Example
404 ///
405 /// ```rust
406 /// # use musi_lili::{Game, Lili};
407 /// # struct MyGame;
408 /// # impl Game for MyGame {
409 /// # fn init(_lili: &Lili) -> Self {Self}
410 /// # fn update(&mut self, _lili: &Lili) {}
411 /// fn draw(&mut self, lili: &Lili) {
412 /// lili.clear(0);
413 /// // draws the word "toki" on the screen
414 /// lili.txt("toki", 1, 1, 3);
415 /// }
416 ///# }
417 ///
418 /// # fn main() {
419 /// # return; // Don't run a window in an example
420 /// # musi_lili::run::<MyGame>(musi_lili::load!("my-game"));
421 /// # }
422 /// ```
423 pub fn txt(&self, text: &str, x: i32, y: i32, color: u8) -> i32 {
424 self.lili.txt(text, x, y, color)
425 }
426
427 /// Draws a sprite from the sprite sheet to the screen
428 ///
429 /// * `sprite`: the sprite to draw (need to be a value between 0 and 244).
430 /// * `x`: the x coordinate of the sprite on the screen.
431 /// * `y`: the y coordinate of the sprite on the screen.
432 /// * `flip_x`: if set to true the sprite is flipped horizontal.
433 /// * `flip_y`: if set to true the sprite is flipped vertical.
434 ///
435 /// ### Example
436 ///
437 /// ```rust
438 /// # use musi_lili::{Game, Lili};
439 /// # struct MyGame;
440 /// # impl Game for MyGame {
441 /// # fn init(_lili: &Lili) -> Self {Self}
442 /// # fn update(&mut self, _lili: &Lili) {}
443 /// fn draw(&mut self, lili: &Lili) {
444 /// lili.clear(0);
445 /// // draws sprite 0
446 /// lili.spr(0, 1, 1, false, false);
447 /// }
448 ///# }
449 ///
450 /// # fn main() {
451 /// # return; // Don't run a window in an example
452 /// # musi_lili::run::<MyGame>(musi_lili::load!("my-game"));
453 /// # }
454 /// ```
455 pub fn spr(&self, sprite: u8, x: i32, y: i32, flip_x: bool, flip_y: bool) {
456 self.lili.spr(sprite, x, y, flip_x, flip_y);
457 }
458
459 /// Draws a sprite with fractional dimensions or a range of sprites.
460 ///
461 /// Supports two modes:
462 /// 1. Fractional mode: spr(sprite, x, y, width_ratio, height_ratio) - draws a portion of a single sprite
463 /// - width_ratio: horizontal portion to draw (0.0 to 1.0)
464 /// - height_ratio: vertical portion to draw (0.0 to 1.0)
465 /// 2. Range mode: spr(sprite, x, y, width_count, height_count) - draws multiple sprites in a grid
466 /// - width_count: number of sprites horizontally (must be > 1.0)
467 /// - height_count: number of sprites vertically (must be > 1.0)
468 ///
469 /// * `sprite`: The starting sprite index
470 /// * `x`: The x coordinate to draw at
471 /// * `y`: The y coordinate to draw at
472 /// * `width`: Width ratio (fractional) or count (range)
473 /// * `height`: Height ratio (fractional) or count (range)
474 /// * `flip_x`: Whether to flip the sprite horizontally
475 /// * `flip_y`: Whether to flip the sprite vertically
476 #[allow(clippy::too_many_arguments)]
477 pub fn spr_ext(
478 &self,
479 sprite: u8,
480 x: i32,
481 y: i32,
482 width: f32,
483 height: f32,
484 flip_x: bool,
485 flip_y: bool,
486 ) {
487 self.lili
488 .spr_ext(sprite, x, y, width, height, flip_x, flip_y);
489 }
490
491 /// Draws the map.
492 ///
493 /// * `cell_x`: cell x coordinate on the map..
494 /// * `cell_y`: cell y coordinate on the map.
495 /// * `screen_x`: x coordinate on the screen in pixel.
496 /// * `screen_y`: y coordinate on the screen in pixel.
497 /// * `cell_width`: horizontal number of cells to draw.
498 /// * `cell_height`: vertical number of cells to draw.
499 ///
500 /// ### Example
501 ///
502 /// ```rust
503 /// # use musi_lili::{Game, Lili, MAP_WIDTH, MAP_HEIGHT};
504 /// # struct MyGame;
505 /// # impl Game for MyGame {
506 /// # fn init(_lili: &Lili) -> Self {Self}
507 /// # fn update(&mut self, _lili: &Lili) {}
508 /// fn draw(&mut self, lili: &Lili) {
509 /// lili.clear(0);
510 /// // draws the whole map
511 /// lili.map(0, 0, 0, 0, MAP_WIDTH, MAP_HEIGHT);
512 /// }
513 ///# }
514 ///
515 /// # fn main() {
516 /// # return; // Don't run a window in an example
517 /// # musi_lili::run::<MyGame>(musi_lili::load!("my-game"));
518 /// # }
519 /// ```
520 pub fn map(
521 &self,
522 cell_x: u32,
523 cell_y: u32,
524 screen_x: i32,
525 screen_y: i32,
526 cell_width: u32,
527 cell_height: u32,
528 ) {
529 self.lili
530 .map(cell_x, cell_y, screen_x, screen_y, cell_width, cell_height);
531 }
532
533 /// Sets the sprite number on the given map position.
534 pub fn set_tile(&self, x: u32, y: u32, tile: u8) {
535 self.lili.set_tile(x, y, tile);
536 }
537
538 /// Returns the
539 pub fn get_tile(&self, x: u32, y: u32) -> Option<u8> {
540 self.lili.get_tile(x, y)
541 }
542
543 /// Sets the flag for the given sprite
544 pub fn set_flag(&self, sprite: u8, flag: u8, value: bool) {
545 self.lili.set_flag(sprite, flag, value);
546 }
547
548 /// Returns if the given flag on the sprite is set.
549 pub fn get_flag(&self, sprite: u8, flag: u8) -> bool {
550 self.lili.get_flag(sprite, flag)
551 }
552
553 /// Returns `true` if the given button is pressed.
554 pub fn btn(&self, button: impl Into<Button>) -> bool {
555 self.lili.btn(button)
556 }
557
558 #[cfg(feature = "experimental")]
559 /// If set to `true` on screen buttons are displayed.
560 ///
561 /// * On mobile devices web and native it defaults to `true`.
562 /// * On desktop devices it defaults to `false`.
563 pub fn set_os_btn(&self, os_btn: bool) {
564 self.lili.set_os_btn(os_btn);
565 }
566
567 /// Returns the current mouse position.
568 pub fn get_mouse(&self) -> Point {
569 self.lili.get_mouse()
570 }
571
572 /// Returns the current scroll wheel delta.
573 pub fn get_scroll(&self) -> Point {
574 self.lili.get_scroll()
575 }
576 /// Returns `true` if the given key is pressed.
577 pub fn key(&self, key: &Key) -> bool {
578 self.lili.key(key)
579 }
580
581 /// Returns the list of all pressed keys.
582 pub fn get_keys(&self) -> Vec<Key> {
583 self.lili.get_keys()
584 }
585
586 /// Sets the current used color palette.
587 pub fn set_pal(&self, palette: Palette) {
588 self.lili.set_pal(palette);
589 }
590
591 /// Return the current used color palette.
592 pub fn get_pal(&self) -> Palette {
593 self.lili.get_pal()
594 }
595
596 /// Creates a new sound and stores it with the given name.
597 ///
598 /// This function generates sound data based on the provided parameters.
599 ///
600 /// # Arguments
601 ///
602 /// * `name` - A string slice that holds the name of the sound.
603 /// * `samples` - The raw audio samples.
604 /// * `rate` - The sample rate in Hz.
605 #[cfg(feature = "std")]
606 pub fn sound(&self, name: &str, samples: Vec<f32>, rate: u32) {
607 self.lili.sound(name, samples, rate);
608 }
609
610 /// Plays the sound associated with the given name.
611 ///
612 /// This function retrieves the sound data associated with the given name and plays it using the `sound` function.
613 ///
614 /// # Arguments
615 ///
616 /// * `sound` - A string slice that holds the name of the sound to play
617 /// * `volume` - The volume of the sound. 1.0 is the `normal` volume.
618 #[cfg(feature = "std")]
619 pub fn play(&self, sound: &str, volume: f32) {
620 self.lili.play(sound, volume);
621 }
622
623 /// Stops the sound associated with the given name.
624 ///
625 /// This function stops the sound with the given name that was started with `play`.
626 ///
627 /// # Arguments
628 ///
629 /// * `sound` - A string slice that holds the name of the sound to stop.
630 #[cfg(feature = "std")]
631 pub fn stop(&self, sound: &str) {
632 self.lili.stop(sound);
633 }
634
635 /// Stops all active sounds.
636 #[cfg(feature = "std")]
637 pub fn stop_all(&self) {
638 self.lili.stop_all();
639 }
640
641 /// Saves a game state with the given name and content. Save games will be created per game in the settings directory of the user.
642 ///
643 /// ### Paths
644 ///
645 /// Linux: `/home/alice/.config/{game_name}/{save_name}.save`
646 /// macOS: `/Users/Alice/Library/Application Support/{game_name}/{save_name}.save`
647 /// Windows: `C:\Users\Alice\AppData\Roaming\{game_name}\{save_name}.save`
648 /// Android: `/data/data/{game_name}/{save_name}.save`
649 /// Web: Save games are stored and load using the [Web Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API)
650 #[cfg(feature = "std")]
651 pub fn save(&self, name: &str, content: &[u8]) {
652 self.lili.save(name, content);
653 }
654
655 /// Loads a save game by a name as identifier. Save games will be created per game in the settings directory of the user.
656 ///
657 /// If there is no save game with the given name this method returns `None`.
658 ///
659 /// ### Paths
660 ///
661 /// Linux: `/home/alice/.config/{game_name}/{save_name}.save`
662 /// macOS: `/Users/Alice/Library/Application Support/{game_name}/{save_name}.save`
663 /// Windows: `C:\Users\Alice\AppData\Roaming\{game_name}\{save_name}.save`
664 /// Android: `/data/data/{game_name}/{save_name}.save`
665 /// Web: Save games are stored and load using the [Web Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API)
666 #[cfg(feature = "std")]
667 pub fn load(&self, name: &str) -> Option<Vec<u8>> {
668 self.lili.load(name)
669 }
670
671 /// Removes the save game with the given name
672 pub fn rm_save(&self, name: &str) {
673 // FIXME: display result
674 let _ = self.lili.rm_sav(name);
675 }
676
677 /// Returns all names of the save games.
678 #[cfg(feature = "std")]
679 pub fn save_games(&self) -> Option<Vec<String>> {
680 self.lili.save_games()
681 }
682
683 /// Quit the game before the next frame is executed.
684 pub fn quit(&self) {
685 self.lili.quit();
686 }
687
688 /// Set or unset the window to display fullscreen.
689 pub fn fullscreen(&self, fullscreen: bool) {
690 self.lili.fullscreen(fullscreen);
691 }
692}
693
694/// Implement this trait for your game.
695///
696/// It provides methods to init, update and draw your game.
697///
698/// ### Example
699///
700/// ```rust
701/// use musi_lili::{Game, Lili};
702///
703/// struct MyGame;
704///
705/// impl Game for MyGame {
706/// fn init(_lili: &Lili) -> Self {
707/// Self
708/// }
709///
710/// fn update(&mut self, _lili: &Lili) {
711/// // the code to update your game
712/// }
713///
714/// fn draw(&mut self, lili: &Lili) {
715/// // draw your game
716/// lili.clear(0);
717/// lili.txt("toki", 5, 5, 3);
718/// }
719/// }
720///
721/// fn main() {
722/// # return; // Don't run a window in an example
723/// musi_lili::run::<MyGame>(musi_lili::load!("my-game"));
724///}
725/// ```
726#[cfg(not(feature = "private_api"))]
727pub trait Game {
728 /// Use this to initialize your game.
729 ///
730 /// This method is only called one time before the game start or after a rest of the game.
731 fn init(lili: &Lili) -> Self;
732
733 /// Use this to update your game.
734 ///
735 /// This method is called once per game loop iteration, before draw is called.
736 fn update(&mut self, lili: &Lili);
737
738 /// Use this to draw your game.
739 ///
740 /// This method is called once per game loop iteration, after update is called..
741 fn draw(&mut self, lili: &Lili);
742}
743
744// internal api
745#[cfg(not(feature = "private_api"))]
746impl Lili {
747 pub(crate) fn new(lili: tan_lili::Lili) -> Self {
748 Self { lili }
749 }
750
751 pub(crate) fn quit_game(&self) -> bool {
752 self.lili.quit_game()
753 }
754}