mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 00:01:34 +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.
|
||||
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};
|
||||
|
||||
|
@ -266,4 +266,14 @@ impl MovableWindow {
|
|||
);
|
||||
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