use new affine stuff in map

This commit is contained in:
Corwin 2022-10-09 16:59:49 +01:00
parent c69fdd7bec
commit ed1e8bcbdc
5 changed files with 90 additions and 32 deletions

View file

@ -688,6 +688,17 @@ impl<I: FixedWidthUnsignedInteger, const N: usize> Vector2D<Num<I, N>> {
y: self.y.floor(),
}
}
#[must_use]
/// Attempts to change the base returning None if the numbers cannot be represented
pub fn try_change_base<J: FixedWidthUnsignedInteger + TryFrom<I>, const M: usize>(
self,
) -> Option<Vector2D<Num<J, M>>> {
Some(Vector2D::new(
self.x.try_change_base()?,
self.y.try_change_base()?,
))
}
}
impl<const N: usize> Vector2D<Num<i32, N>> {

View file

@ -3,6 +3,7 @@
use agb::{
display::{
affine::{AffineMatrix, AffineMatrixBackground},
tiled::{AffineBackgroundSize, TileFormat, TileSet, TiledMap},
Priority,
},
@ -32,8 +33,8 @@ fn main(mut gba: agb::Gba) -> ! {
bg.commit(&mut vram);
bg.show();
let mut rotation: Num<u16, 8> = num!(0.);
let rotation_increase = num!(1.);
let mut rotation = num!(0.);
let rotation_increase: Num<i32, 16> = num!(0.01);
let mut input = agb::input::ButtonController::new();
@ -45,14 +46,19 @@ fn main(mut gba: agb::Gba) -> ! {
scroll_x += input.x_tri() as i32;
scroll_y += input.y_tri() as i32;
let scroll_pos = (scroll_x as i16, scroll_y as i16);
bg.set_scroll_pos(scroll_pos.into());
bg.set_transform((0, 0), (1, 1), rotation);
let scroll_pos = (scroll_x, scroll_y).into();
rotation += rotation_increase;
if rotation >= num!(255.) {
rotation = 0.into();
}
rotation = rotation.rem_euclid(1.into());
let transformation = AffineMatrixBackground::from_scale_rotation_position(
(0, 0).into(),
(1, 1).into(),
rotation,
scroll_pos,
);
bg.set_transform(transformation);
vblank.wait_for_vblank();
bg.commit(&mut vram);

View file

@ -62,7 +62,7 @@ impl AffineMatrix {
#[must_use]
/// Generates the matrix that represents a rotation
pub fn from_rotation<const N: usize>(angle: Num<i32, N>) -> Self {
fn from_rotation(angle: Num<i32, 28>) -> AffineMatrix {
fn from_rotation(angle: Num<i32, 8>) -> AffineMatrix {
let cos = angle.cos().change_base();
let sin = angle.sin().change_base();
@ -71,8 +71,8 @@ impl AffineMatrix {
// space rather than how you might conventionally think of it.
AffineMatrix {
a: cos,
b: sin,
c: -sin,
b: -sin,
c: sin,
d: cos,
x: 0.into(),
y: 0.into(),
@ -90,15 +90,15 @@ impl AffineMatrix {
b: 0.into(),
c: 0.into(),
d: 1.into(),
x: position.x,
y: position.y,
x: -position.x,
y: -position.y,
}
}
#[must_use]
/// The position fields of the matrix
pub fn position(&self) -> Vector2D<Num<i32, 8>> {
(self.x, self.y).into()
(-self.x, -self.y).into()
}
/// Attempts to convert the matrix to one which can be used in affine
@ -150,6 +150,20 @@ impl AffineMatrix {
d: Num::from_raw(self.d.to_raw() as i16),
}
}
#[must_use]
/// Creates an affine matrix from a given (x, y) scaling. This will scale by
/// the inverse, ie (2, 2) will produce half the size.
pub fn from_scale(scale: Vector2D<Num<i32, 8>>) -> AffineMatrix {
AffineMatrix {
a: scale.x,
b: 0.into(),
c: 0.into(),
d: scale.y,
x: 0.into(),
y: 0.into(),
}
}
}
impl Default for AffineMatrix {
@ -198,6 +212,35 @@ impl AffineMatrixBackground {
y: self.y,
}
}
#[must_use]
/// Creates a transformation matrix using GBA specific syscalls.
/// This can be done using the standard transformation matricies like
///
/// ```rust,no_run
/// use agb::display::affine::AffineMatrix;
/// # #![no_std]
/// # #![no_main]
/// # fn something() {
/// let A = AffineMatrix::from_translation(-transform_origin)
/// * AffineMatrix::from_scale(scale)
/// * AffineMatrix::from_rotation(rotation)
/// * AffineMatrix::from_translation(position);
/// # }
/// ```
pub fn from_scale_rotation_position(
transform_origin: Vector2D<Num<i32, 8>>,
scale: Vector2D<Num<i32, 8>>,
rotation: Num<i32, 16>,
position: Vector2D<Num<i32, 8>>,
) -> Self {
crate::syscall::bg_affine_matrix(
transform_origin,
position.try_change_base::<i16, 8>().unwrap().floor(),
scale.try_change_base().unwrap(),
rotation.rem_euclid(1.into()).try_change_base().unwrap(),
)
}
}
impl From<AffineMatrixBackground> for AffineMatrix {

View file

@ -344,16 +344,8 @@ impl AffineMap {
*self.tiles_dirty() = true;
}
pub fn set_transform(
&mut self,
transform_origin: impl Into<Vector2D<Num<i32, 8>>>,
scale: impl Into<Vector2D<Num<i16, 8>>>,
rotation: impl Into<Num<u16, 8>>,
) {
let scale = scale.into();
let rotation = rotation.into();
self.transform =
crate::syscall::bg_affine_matrix(transform_origin.into(), self.scroll, scale, rotation);
pub fn set_transform(&mut self, transformation: impl Into<AffineMatrixBackground>) {
self.transform = transformation.into();
}
fn bg_affine_matrix(&self) -> MemoryMapped<AffineMatrixBackground> {

View file

@ -145,20 +145,26 @@ pub fn bg_affine_matrix(
bg_center: Vector2D<Num<i32, 8>>,
display_center: Vector2D<i16>,
scale: Vector2D<Num<i16, 8>>,
rotation: Num<u16, 8>,
rotation: Num<u16, 16>,
) -> AffineMatrixBackground {
#[repr(C, packed(4))]
struct Input {
bg_center: Vector2D<Num<i32, 8>>,
display_center: Vector2D<i16>,
scale: Vector2D<Num<i16, 8>>,
rotation: Num<u16, 8>,
bg_center_x: Num<i32, 8>,
bg_center_y: Num<i32, 8>,
display_center_x: i16,
display_center_y: i16,
scale_x: Num<i16, 8>,
scale_y: Num<i16, 8>,
rotation: Num<u16, 16>,
}
let input = Input {
bg_center,
display_center,
scale,
bg_center_x: bg_center.x,
bg_center_y: bg_center.y,
display_center_x: display_center.x,
display_center_y: display_center.y,
scale_x: scale.x,
scale_y: scale.y,
rotation,
};