mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 08:11:33 +11:00
add a no game
This commit is contained in:
parent
a0ead37eb5
commit
0271da6d43
BIN
agb/gfx/square.aseprite
Normal file
BIN
agb/gfx/square.aseprite
Normal file
Binary file not shown.
|
@ -94,6 +94,7 @@ macro_rules! align_bytes {
|
|||
#[macro_export]
|
||||
macro_rules! include_aseprite {
|
||||
($($aseprite_path: expr),*) => {{
|
||||
#[allow(unused_imports)]
|
||||
use $crate::display::object::{Size, Sprite, Tag, TagMap, Graphics};
|
||||
use $crate::display::palette16::Palette16;
|
||||
use $crate::align_bytes;
|
||||
|
|
|
@ -165,6 +165,11 @@ pub mod syscall;
|
|||
/// Interactions with the internal timers
|
||||
pub mod timer;
|
||||
|
||||
mod no_game;
|
||||
|
||||
/// Default game
|
||||
pub use no_game::no_game;
|
||||
|
||||
pub(crate) mod arena;
|
||||
|
||||
pub use {agb_alloc::ExternalAllocator, agb_alloc::InternalAllocator};
|
||||
|
|
208
agb/src/no_game.rs
Normal file
208
agb/src/no_game.rs
Normal file
|
@ -0,0 +1,208 @@
|
|||
//! The no game screen is what is displayed if there isn't a game made yet.
|
||||
|
||||
use agb_fixnum::{num, Num, Vector2D};
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::{
|
||||
display::{
|
||||
object::{OamIterator, ObjectUnmanaged, Sprite},
|
||||
palette16::Palette16,
|
||||
HEIGHT, WIDTH,
|
||||
},
|
||||
include_aseprite,
|
||||
interrupt::VBlank,
|
||||
};
|
||||
|
||||
const SQUARE: &Sprite = &include_aseprite!("gfx/square.aseprite").sprites()[0];
|
||||
|
||||
fn letters() -> Vec<Vec<Vector2D<Num<i32, 8>>>> {
|
||||
vec![
|
||||
// N
|
||||
vec![
|
||||
(num!(0.), num!(0.)).into(),
|
||||
(num!(1.), num!(1.)).into(),
|
||||
(num!(2.), num!(2.)).into(),
|
||||
(num!(3.), num!(3.)).into(),
|
||||
(num!(0.), num!(1.)).into(),
|
||||
(num!(0.), num!(2.)).into(),
|
||||
(num!(0.), num!(3.)).into(),
|
||||
(num!(3.), num!(0.)).into(),
|
||||
(num!(3.), num!(1.)).into(),
|
||||
(num!(3.), num!(2.)).into(),
|
||||
(num!(3.), num!(3.)).into(),
|
||||
],
|
||||
// O
|
||||
vec![
|
||||
(num!(0.), num!(0.)).into(),
|
||||
(num!(0.), num!(1.)).into(),
|
||||
(num!(0.), num!(2.)).into(),
|
||||
(num!(0.), num!(3.)).into(),
|
||||
(num!(1.), num!(3.)).into(),
|
||||
(num!(2.), num!(3.)).into(),
|
||||
(num!(3.), num!(3.)).into(),
|
||||
(num!(3.), num!(2.)).into(),
|
||||
(num!(3.), num!(1.)).into(),
|
||||
(num!(3.), num!(0.)).into(),
|
||||
(num!(2.), num!(0.)).into(),
|
||||
(num!(1.), num!(0.)).into(),
|
||||
],
|
||||
// G
|
||||
vec![
|
||||
(num!(3.), num!(0.)).into(),
|
||||
(num!(2.), num!(0.)).into(),
|
||||
(num!(1.), num!(0.)).into(),
|
||||
(num!(0.), num!(0.)).into(),
|
||||
(num!(0.), num!(1.)).into(),
|
||||
(num!(0.), num!(2.)).into(),
|
||||
(num!(0.), num!(3.)).into(),
|
||||
(num!(1.), num!(3.)).into(),
|
||||
(num!(2.), num!(3.)).into(),
|
||||
(num!(3.), num!(3.)).into(),
|
||||
(num!(3.), num!(2.25)).into(),
|
||||
(num!(3.), num!(1.5)).into(),
|
||||
(num!(2.), num!(1.5)).into(),
|
||||
],
|
||||
// A
|
||||
vec![
|
||||
(num!(0.), num!(0.)).into(),
|
||||
(num!(0.), num!(1.)).into(),
|
||||
(num!(0.), num!(2.)).into(),
|
||||
(num!(0.), num!(3.)).into(),
|
||||
(num!(3.), num!(3.)).into(),
|
||||
(num!(3.), num!(2.)).into(),
|
||||
(num!(3.), num!(1.)).into(),
|
||||
(num!(3.), num!(0.)).into(),
|
||||
(num!(2.), num!(0.)).into(),
|
||||
(num!(1.), num!(0.)).into(),
|
||||
(num!(1.), num!(1.5)).into(),
|
||||
(num!(2.), num!(1.5)).into(),
|
||||
],
|
||||
// M
|
||||
vec![
|
||||
(num!(0.), num!(0.)).into(),
|
||||
(num!(0.), num!(1.)).into(),
|
||||
(num!(0.), num!(2.)).into(),
|
||||
(num!(0.), num!(3.)).into(),
|
||||
(num!(3.), num!(3.)).into(),
|
||||
(num!(3.), num!(2.)).into(),
|
||||
(num!(3.), num!(1.)).into(),
|
||||
(num!(3.), num!(0.)).into(),
|
||||
(num!(1.5), num!(1.5)).into(),
|
||||
(num!(0.5), num!(0.5)).into(),
|
||||
(num!(2.5), num!(0.5)).into(),
|
||||
(num!(1.), num!(1.)).into(),
|
||||
(num!(2.), num!(1.)).into(),
|
||||
],
|
||||
// E
|
||||
vec![
|
||||
(num!(0.), num!(0.)).into(),
|
||||
(num!(0.), num!(1.)).into(),
|
||||
(num!(0.), num!(2.)).into(),
|
||||
(num!(0.), num!(3.)).into(),
|
||||
(num!(1.), num!(3.)).into(),
|
||||
(num!(2.), num!(3.)).into(),
|
||||
(num!(3.), num!(3.)).into(),
|
||||
(num!(3.), num!(0.)).into(),
|
||||
(num!(2.), num!(0.)).into(),
|
||||
(num!(1.), num!(0.)).into(),
|
||||
(num!(1.), num!(1.5)).into(),
|
||||
(num!(2.), num!(1.5)).into(),
|
||||
],
|
||||
]
|
||||
}
|
||||
|
||||
trait Renderable {
|
||||
fn render(&self, slots: &mut OamIterator) -> Option<()>;
|
||||
}
|
||||
|
||||
impl Renderable for ObjectUnmanaged {
|
||||
fn render(&self, slots: &mut OamIterator) -> Option<()> {
|
||||
slots.next()?.set(self);
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Renderable> Renderable for &[T] {
|
||||
fn render(&self, slots: &mut OamIterator) -> Option<()> {
|
||||
for r in self.iter() {
|
||||
r.render(slots)?;
|
||||
}
|
||||
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn no_game(mut gba: crate::Gba) -> ! {
|
||||
let (mut oam, mut loader) = gba.display.object.get_unmanaged();
|
||||
|
||||
let square = loader.get_vram_sprite(SQUARE);
|
||||
|
||||
let mut letter_positons = Vec::new();
|
||||
|
||||
let square_positions = {
|
||||
let mut s = letters();
|
||||
for letter in s.iter_mut() {
|
||||
letter.sort_by_key(|a| a.manhattan_distance());
|
||||
}
|
||||
s
|
||||
};
|
||||
for (letter_idx, letter_parts) in square_positions.iter().enumerate() {
|
||||
for part in letter_parts.iter() {
|
||||
let position = part
|
||||
.hadamard((8, 10).into())
|
||||
.hadamard((num!(3.) / 2, num!(3.) / 2).into());
|
||||
|
||||
let letter_pos = Vector2D::new(
|
||||
60 * (1 + letter_idx as i32 - ((letter_idx >= 2) as i32 * 3)),
|
||||
70 * ((letter_idx >= 2) as i32),
|
||||
);
|
||||
|
||||
letter_positons.push(position + letter_pos.change_base());
|
||||
}
|
||||
}
|
||||
|
||||
let bottom_right = letter_positons
|
||||
.iter()
|
||||
.copied()
|
||||
.max_by_key(|x| x.manhattan_distance())
|
||||
.unwrap();
|
||||
|
||||
let difference = (Vector2D::new(WIDTH - 8, HEIGHT - 8).change_base() - bottom_right) / 2;
|
||||
|
||||
for pos in letter_positons.iter_mut() {
|
||||
*pos += difference;
|
||||
}
|
||||
|
||||
let mut time: Num<i32, 8> = num!(0.);
|
||||
let time_delta: Num<i32, 8> = num!(0.025);
|
||||
|
||||
let (_background, mut vram) = gba.display.video.tiled0();
|
||||
|
||||
vram.set_background_palettes(&[Palette16::new([u16::MAX; 16])]);
|
||||
|
||||
let vblank = VBlank::get();
|
||||
|
||||
loop {
|
||||
time += time_delta;
|
||||
time %= 1;
|
||||
let letters: Vec<ObjectUnmanaged> = letter_positons
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, position)| {
|
||||
let time = time + Num::<i32, 8>::new(idx as i32) / 128;
|
||||
*position + Vector2D::new(time.sin(), time.cos()) * 10
|
||||
})
|
||||
.map(|pos| {
|
||||
let mut obj = ObjectUnmanaged::new(square.clone());
|
||||
obj.show().set_position(pos.floor());
|
||||
obj
|
||||
})
|
||||
.collect();
|
||||
|
||||
vblank.wait_for_vblank();
|
||||
for (obj, slot) in letters.iter().zip(oam.iter()) {
|
||||
slot.set(obj);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,22 +14,10 @@
|
|||
#![cfg_attr(test, reexport_test_harness_main = "test_main")]
|
||||
#![cfg_attr(test, test_runner(agb::test_runner::test_runner))]
|
||||
|
||||
use agb::{display, syscall};
|
||||
|
||||
// The main function must take 1 arguments and never return. The agb::entry decorator
|
||||
// ensures that everything is in order. `agb` will call this after setting up the stack
|
||||
// and interrupt handlers correctly. It will also handle creating the `Gba` struct for you.
|
||||
#[agb::entry]
|
||||
fn main(mut gba: agb::Gba) -> ! {
|
||||
let mut bitmap = gba.display.video.bitmap3();
|
||||
|
||||
for x in 0..display::WIDTH {
|
||||
let y = syscall::sqrt(x << 6);
|
||||
let y = (display::HEIGHT - y).clamp(0, display::HEIGHT - 1);
|
||||
bitmap.draw_point(x, y, 0x001F);
|
||||
}
|
||||
|
||||
loop {
|
||||
syscall::halt();
|
||||
}
|
||||
agb::no_game(gba);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue