Skip to main content

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}