Skip to main content

agb/
no_game.rs

1use alloc::vec::Vec;
2use alloc::{boxed::Box, vec};
3
4use crate::display::object::{DynamicSprite16, PaletteVramSingle, Size, SpriteVram};
5use crate::display::{Palette16, Rgb15};
6use crate::{
7    display::{HEIGHT, WIDTH, object::Object},
8    fixnum::{Num, Vector2D, num, vec2},
9    include_colours,
10};
11
12static PALETTE: &[Rgb15] = &include_colours!("gfx/pastel.png");
13
14fn letters() -> Vec<Vec<Vector2D<Num<i32, 8>>>> {
15    vec![
16        // N
17        vec![
18            (num!(0.), num!(0.)).into(),
19            (num!(1.), num!(1.)).into(),
20            (num!(2.), num!(2.)).into(),
21            (num!(3.), num!(3.)).into(),
22            (num!(0.), num!(1.)).into(),
23            (num!(0.), num!(2.)).into(),
24            (num!(0.), num!(3.)).into(),
25            (num!(3.), num!(0.)).into(),
26            (num!(3.), num!(1.)).into(),
27            (num!(3.), num!(2.)).into(),
28            (num!(3.), num!(3.)).into(),
29        ],
30        // O
31        vec![
32            (num!(0.), num!(0.)).into(),
33            (num!(0.), num!(1.)).into(),
34            (num!(0.), num!(2.)).into(),
35            (num!(0.), num!(3.)).into(),
36            (num!(1.), num!(3.)).into(),
37            (num!(2.), num!(3.)).into(),
38            (num!(3.), num!(3.)).into(),
39            (num!(3.), num!(2.)).into(),
40            (num!(3.), num!(1.)).into(),
41            (num!(3.), num!(0.)).into(),
42            (num!(2.), num!(0.)).into(),
43            (num!(1.), num!(0.)).into(),
44        ],
45        // G
46        vec![
47            (num!(3.), num!(0.)).into(),
48            (num!(2.), num!(0.)).into(),
49            (num!(1.), num!(0.)).into(),
50            (num!(0.), num!(0.)).into(),
51            (num!(0.), num!(1.)).into(),
52            (num!(0.), num!(2.)).into(),
53            (num!(0.), num!(3.)).into(),
54            (num!(1.), num!(3.)).into(),
55            (num!(2.), num!(3.)).into(),
56            (num!(3.), num!(3.)).into(),
57            (num!(3.), num!(2.25)).into(),
58            (num!(3.), num!(1.5)).into(),
59            (num!(2.), num!(1.5)).into(),
60        ],
61        // A
62        vec![
63            (num!(0.), num!(0.)).into(),
64            (num!(0.), num!(1.)).into(),
65            (num!(0.), num!(2.)).into(),
66            (num!(0.), num!(3.)).into(),
67            (num!(3.), num!(3.)).into(),
68            (num!(3.), num!(2.)).into(),
69            (num!(3.), num!(1.)).into(),
70            (num!(3.), num!(0.)).into(),
71            (num!(2.), num!(0.)).into(),
72            (num!(1.), num!(0.)).into(),
73            (num!(1.), num!(1.5)).into(),
74            (num!(2.), num!(1.5)).into(),
75        ],
76        // M
77        vec![
78            (num!(0.), num!(0.)).into(),
79            (num!(0.), num!(1.)).into(),
80            (num!(0.), num!(2.)).into(),
81            (num!(0.), num!(3.)).into(),
82            (num!(3.), num!(3.)).into(),
83            (num!(3.), num!(2.)).into(),
84            (num!(3.), num!(1.)).into(),
85            (num!(3.), num!(0.)).into(),
86            (num!(1.5), num!(1.5)).into(),
87            (num!(0.75), num!(0.75)).into(),
88            (num!(2.25), num!(0.75)).into(),
89        ],
90        // E
91        vec![
92            (num!(0.), num!(0.)).into(),
93            (num!(0.), num!(1.)).into(),
94            (num!(0.), num!(2.)).into(),
95            (num!(0.), num!(3.)).into(),
96            (num!(1.), num!(3.)).into(),
97            (num!(2.), num!(3.)).into(),
98            (num!(3.), num!(3.)).into(),
99            (num!(3.), num!(0.)).into(),
100            (num!(2.), num!(0.)).into(),
101            (num!(1.), num!(0.)).into(),
102            (num!(1.), num!(1.5)).into(),
103            (num!(2.), num!(1.5)).into(),
104        ],
105    ]
106}
107
108fn generate_sprites() -> Box<[SpriteVram]> {
109    let mut sprites = Vec::new();
110
111    // generate palettes
112
113    let palettes: Vec<PaletteVramSingle> = PALETTE
114        .chunks(15)
115        .map(|x| {
116            core::iter::once(Rgb15::BLACK)
117                .chain(x.iter().copied())
118                .chain(core::iter::repeat(Rgb15::BLACK))
119                .take(16)
120                .collect::<Vec<_>>()
121        })
122        .map(|palette| {
123            let palette = Palette16::new(palette.try_into().unwrap());
124            PaletteVramSingle::try_allocate_new(&palette).unwrap()
125        })
126        .collect();
127
128    // generate sprites
129
130    for (palette, colour) in (0..PALETTE.len()).map(|x| (x / 15, x % 15)) {
131        let mut sprite = DynamicSprite16::new(Size::S8x8);
132        sprite.clear(colour + 1);
133        sprites.push(sprite.to_vram(palettes[palette].clone()));
134    }
135
136    sprites.into_boxed_slice()
137}
138
139/// The no game screen is what is displayed if there isn't a game made yet.
140pub fn no_game(mut gba: crate::Gba) -> ! {
141    let mut gfx: crate::display::Graphics<'_> = gba.graphics.get();
142
143    let squares = generate_sprites();
144
145    let mut letter_positons = Vec::new();
146
147    let square_positions = {
148        let mut s = letters();
149        for letter in s.iter_mut() {
150            letter.sort_by_key(|a| a.magnitude_squared());
151        }
152        s
153    };
154    for (letter_idx, letter_parts) in square_positions.iter().enumerate() {
155        for part in letter_parts.iter() {
156            let position = part
157                .hadamard((8, 10).into())
158                .hadamard((num!(3.) / 2, num!(3.) / 2).into());
159
160            let letter_pos = vec2(
161                60 * (1 + letter_idx as i32 - ((letter_idx >= 2) as i32 * 3)),
162                70 * ((letter_idx >= 2) as i32),
163            );
164
165            letter_positons.push(position + letter_pos.change_base());
166        }
167    }
168
169    let bottom_right = letter_positons
170        .iter()
171        .copied()
172        .max_by_key(|x| x.manhattan_distance())
173        .unwrap();
174
175    let difference = (vec2(WIDTH - 8, HEIGHT - 8).change_base() - bottom_right) / 2;
176
177    for pos in letter_positons.iter_mut() {
178        *pos += difference;
179    }
180
181    let mut time: Num<i32, 8> = num!(0.);
182    let time_delta: Num<i32, 8> = num!(0.025);
183
184    loop {
185        time += time_delta;
186        time %= 1;
187        let letters: Vec<Object> = letter_positons
188            .iter()
189            .enumerate()
190            .map(|(idx, position)| {
191                let time = time + Num::<i32, 8>::new(idx as i32) / 128;
192                (idx, *position + vec2(time.sin(), time.cos()) * 10)
193            })
194            .map(|(idx, pos)| {
195                let mut obj = Object::new(squares[idx % squares.len()].clone());
196                obj.set_pos(pos.floor());
197                obj
198            })
199            .collect();
200
201        let mut frame = gfx.frame();
202
203        for obj in letters.iter() {
204            obj.show(&mut frame);
205        }
206
207        frame.commit();
208    }
209}