mirror of
https://github.com/italicsjenga/agb.git
synced 2025-01-24 16:16:34 +11:00
add a no game
This commit is contained in:
parent
a0ead37eb5
commit
0271da6d43
5 changed files with 215 additions and 13 deletions
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_export]
|
||||||
macro_rules! include_aseprite {
|
macro_rules! include_aseprite {
|
||||||
($($aseprite_path: expr),*) => {{
|
($($aseprite_path: expr),*) => {{
|
||||||
|
#[allow(unused_imports)]
|
||||||
use $crate::display::object::{Size, Sprite, Tag, TagMap, Graphics};
|
use $crate::display::object::{Size, Sprite, Tag, TagMap, Graphics};
|
||||||
use $crate::display::palette16::Palette16;
|
use $crate::display::palette16::Palette16;
|
||||||
use $crate::align_bytes;
|
use $crate::align_bytes;
|
||||||
|
|
|
@ -165,6 +165,11 @@ pub mod syscall;
|
||||||
/// Interactions with the internal timers
|
/// Interactions with the internal timers
|
||||||
pub mod timer;
|
pub mod timer;
|
||||||
|
|
||||||
|
mod no_game;
|
||||||
|
|
||||||
|
/// Default game
|
||||||
|
pub use no_game::no_game;
|
||||||
|
|
||||||
pub(crate) mod arena;
|
pub(crate) mod arena;
|
||||||
|
|
||||||
pub use {agb_alloc::ExternalAllocator, agb_alloc::InternalAllocator};
|
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, reexport_test_harness_main = "test_main")]
|
||||||
#![cfg_attr(test, test_runner(agb::test_runner::test_runner))]
|
#![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
|
// 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
|
// 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.
|
// and interrupt handlers correctly. It will also handle creating the `Gba` struct for you.
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main(mut gba: agb::Gba) -> ! {
|
fn main(mut gba: agb::Gba) -> ! {
|
||||||
let mut bitmap = gba.display.video.bitmap3();
|
agb::no_game(gba);
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue