mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 08:11:33 +11:00
Add an example of doing circular windows
This commit is contained in:
parent
a0700b3a51
commit
4ef08a1273
97
agb/examples/dma_effect_circular_window.rs
Normal file
97
agb/examples/dma_effect_circular_window.rs
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![feature(isqrt)]
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
use agb::{
|
||||||
|
display::{
|
||||||
|
example_logo,
|
||||||
|
tiled::{RegularBackgroundSize, TileFormat},
|
||||||
|
window::WinIn,
|
||||||
|
HEIGHT, WIDTH,
|
||||||
|
},
|
||||||
|
fixnum::{Num, Rect, Vector2D},
|
||||||
|
interrupt::VBlank,
|
||||||
|
};
|
||||||
|
use alloc::{boxed::Box, vec};
|
||||||
|
|
||||||
|
type FNum = Num<i32, 8>;
|
||||||
|
|
||||||
|
#[agb::entry]
|
||||||
|
fn entry(mut gba: agb::Gba) -> ! {
|
||||||
|
main(gba)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main(mut gba: agb::Gba) -> ! {
|
||||||
|
let (gfx, mut vram) = gba.display.video.tiled0();
|
||||||
|
|
||||||
|
let mut map = gfx.background(
|
||||||
|
agb::display::Priority::P0,
|
||||||
|
RegularBackgroundSize::Background32x32,
|
||||||
|
TileFormat::FourBpp,
|
||||||
|
);
|
||||||
|
let mut window = gba.display.window.get();
|
||||||
|
window
|
||||||
|
.win_in(WinIn::Win0)
|
||||||
|
.set_background_enable(map.background(), true)
|
||||||
|
.set_position(&Rect::new((10, 10).into(), (64, 64).into()))
|
||||||
|
.enable();
|
||||||
|
|
||||||
|
let dmas = gba.dma.dma();
|
||||||
|
|
||||||
|
example_logo::display_logo(&mut map, &mut vram);
|
||||||
|
|
||||||
|
let mut pos: Vector2D<FNum> = (10, 10).into();
|
||||||
|
let mut velocity: Vector2D<FNum> = Vector2D::new(1.into(), 1.into());
|
||||||
|
|
||||||
|
let vblank = VBlank::get();
|
||||||
|
|
||||||
|
let circle: Box<[_]> = (1..64i32)
|
||||||
|
.map(|i| {
|
||||||
|
let y = 32 - i;
|
||||||
|
let x = (32 * 32 - y * y).isqrt();
|
||||||
|
let x1 = 32 - x;
|
||||||
|
let x2 = 32 + x;
|
||||||
|
|
||||||
|
((x1 as u16) << 8) | (x2 as u16)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut circle_poses = vec![0; 160];
|
||||||
|
|
||||||
|
loop {
|
||||||
|
pos += velocity;
|
||||||
|
|
||||||
|
if pos.x.floor() > WIDTH - 64 || pos.x.floor() < 0 {
|
||||||
|
velocity.x *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if pos.y.floor() > HEIGHT - 64 || pos.y.floor() < 0 {
|
||||||
|
velocity.y *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let x_pos = pos.x.floor().max(0) as u16;
|
||||||
|
let y_pos = pos.y.floor().max(0);
|
||||||
|
let x_adjustment = x_pos << 8 | x_pos;
|
||||||
|
for (i, value) in circle_poses.iter_mut().enumerate() {
|
||||||
|
let i = i as i32;
|
||||||
|
if i <= y_pos || i >= y_pos + 64 {
|
||||||
|
*value = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = circle[(i - y_pos) as usize - 1] + x_adjustment;
|
||||||
|
}
|
||||||
|
|
||||||
|
window
|
||||||
|
.win_in(WinIn::Win0)
|
||||||
|
.set_position(&Rect::new(pos.floor(), (64, 65).into()));
|
||||||
|
window.commit();
|
||||||
|
|
||||||
|
let dma_controllable = window.win_in(WinIn::Win0).horizontal_position_dma();
|
||||||
|
let _transfer = unsafe { dmas.dma0.hblank_transfer(&dma_controllable, &circle_poses) };
|
||||||
|
|
||||||
|
vblank.wait_for_vblank();
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
//! The window feature of the GBA.
|
//! The window feature of the GBA.
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::{fixnum::Rect, memory_mapped::MemoryMapped};
|
use crate::{dma, fixnum::Rect, memory_mapped::MemoryMapped};
|
||||||
|
|
||||||
use super::{tiled::BackgroundID, DISPLAY_CONTROL, HEIGHT, WIDTH};
|
use super::{tiled::BackgroundID, DISPLAY_CONTROL, HEIGHT, WIDTH};
|
||||||
|
|
||||||
|
@ -266,4 +266,14 @@ impl MovableWindow {
|
||||||
);
|
);
|
||||||
self.set_position_u8(new_rect)
|
self.set_position_u8(new_rect)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// DMA to control the horizontal position of the window. The lower 8 bits are
|
||||||
|
/// the left hand side, and the upper 8 bits are the right hand side.
|
||||||
|
///
|
||||||
|
/// When you use this, you should also set the height of the window approprately using
|
||||||
|
/// [`set_position`](Self::set_position).
|
||||||
|
#[must_use]
|
||||||
|
pub fn horizontal_position_dma(&self) -> dma::DmaControllable<u16> {
|
||||||
|
dma::DmaControllable::new(unsafe { REG_HORIZONTAL_BASE.add(self.id) })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue