From cb2be577b1370d57ad81e42138603495e7446ff8 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Thu, 22 Dec 2022 21:10:52 -0700 Subject: [PATCH] obj to obj intersection. --- examples/game.rs | 124 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 90 insertions(+), 34 deletions(-) diff --git a/examples/game.rs b/examples/game.rs index 00d2154..96ae41f 100644 --- a/examples/game.rs +++ b/examples/game.rs @@ -1,8 +1,6 @@ #![no_std] #![no_main] -use core::num::Wrapping; - use gba::prelude::*; #[panic_handler] @@ -14,11 +12,43 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! { loop {} } +#[derive(Debug, Clone, Copy, Default)] +struct Position { + x: u16, + y: u16, +} +#[derive(Debug, Clone, Copy, Default)] +struct Rect { + x: u16, + y: u16, + w: u16, + h: u16, +} +impl Rect { + pub fn intersect(self, other: Self) -> bool { + self.x < other.x + other.w + && self.x + self.w > other.x + && self.y < other.y + other.h + && self.h + self.y > other.y + } +} + #[no_mangle] extern "C" fn main() -> ! { // game simulation setup - let mut player_x = 13_u16; - let mut player_y = 37_u16; + let mut creatures = [Position::default(); 5]; + creatures[0].x = 13; + creatures[0].y = 37; + // + creatures[1].x = 41; + creatures[1].y = 38; + creatures[2].x = 100; + creatures[2].y = 23; + creatures[3].x = 14; + creatures[3].y = 101; + creatures[4].x = 72; + creatures[4].y = 59; + let mut world = [[0_u8; 32]; 32]; for i in 0..32 { world[0][i] = b'z'; @@ -26,9 +56,9 @@ extern "C" fn main() -> ! { world[i][0] = b'z'; world[i][31] = b'z'; } - world[1][1] = b'B'; - world[2][1] = b'G'; - world[3][1] = b'0'; + world[1][3] = b'B'; + world[2][3] = b'G'; + world[3][3] = b'0'; // hardware configuration DISPSTAT.write(DisplayStatus::new().with_irq_vblank(true)); @@ -39,6 +69,10 @@ extern "C" fn main() -> ! { BG_PALETTE.index(1).write(Color::MAGENTA); OBJ_PALETTE.index(1).write(Color::CYAN); + OBJ_PALETTE.index(16 * 1 + 1).write(Color::GREEN); + OBJ_PALETTE.index(16 * 2 + 1).write(Color::RED); + OBJ_PALETTE.index(16 * 3 + 1).write(Color::BLUE); + OBJ_PALETTE.index(16 * 4 + 1).write(Color::YELLOW); Cga8x8Thick.bitunpack_4bpp(CHARBLOCK0_4BPP.as_region(), 0); Cga8x8Thick.bitunpack_4bpp(OBJ_TILES.as_region(), 0); @@ -52,14 +86,8 @@ extern "C" fn main() -> ! { } } - let mut obj = ObjAttr::new(); - obj.set_x(player_x); - obj.set_y(player_y); - obj.set_tile_id(1); - OBJ_ATTR_ALL.index(0).write(obj); - let no_display = ObjAttr0::new().with_style(ObjDisplayStyle::NotDisplayed); - OBJ_ATTR0.iter().skip(1).for_each(|va| va.write(no_display)); + OBJ_ATTR0.iter().skip(creatures.len()).for_each(|va| va.write(no_display)); DISPCNT.write(DisplayControl::new().with_show_obj(true).with_show_bg0(true)); @@ -68,7 +96,16 @@ extern "C" fn main() -> ! { VBlankIntrWait(); // update graphics MMIO - OBJ_ATTR_ALL.index(0).write(obj); + for (i, (creature_pos, attr_addr)) in + creatures.iter().zip(OBJ_ATTR_ALL.iter()).enumerate() + { + let mut obj = ObjAttr::new(); + obj.set_x(creature_pos.x); + obj.set_y(creature_pos.y); + obj.set_tile_id(1); + obj.set_palbank(i as u16); + attr_addr.write(obj); + } // handle input let keys = KEYINPUT.read(); @@ -76,42 +113,61 @@ extern "C" fn main() -> ! { // wall and you press a diagonal then one axis will progress while the other // will be halted by the wall. This makes the player slide along the wall // when bumping into walls. + let (player, enemies) = match &mut creatures { + [player, enemies @ ..] => (player, enemies), + }; if keys.up() { - let new_y = player_y.saturating_sub(1); - if iter_tiles_of_area((player_x, new_y), (8, 8)) + let new_p = Position { x: player.x, y: player.y - 1 }; + let new_r = Rect { x: new_p.x, y: new_p.y, w: 8, h: 8 }; + if iter_tiles_of_area(new_p, (8, 8)) .all(|(tx, ty)| allows_movement(world[ty as usize][tx as usize])) + && enemies.iter().all(|enemy| { + let enemy_r = Rect { x: enemy.x, y: enemy.y, w: 8, h: 8 }; + !new_r.intersect(enemy_r) + }) { - player_y = new_y; + *player = new_p; } } if keys.down() { - let new_y = player_y.saturating_add(1); - if iter_tiles_of_area((player_x, new_y), (8, 8)) + let new_p = Position { x: player.x, y: player.y + 1 }; + let new_r = Rect { x: new_p.x, y: new_p.y, w: 8, h: 8 }; + if iter_tiles_of_area(new_p, (8, 8)) .all(|(tx, ty)| allows_movement(world[ty as usize][tx as usize])) + && enemies.iter().all(|enemy| { + let enemy_r = Rect { x: enemy.x, y: enemy.y, w: 8, h: 8 }; + !new_r.intersect(enemy_r) + }) { - player_y = new_y; + *player = new_p; } } if keys.left() { - let new_x = player_x.saturating_sub(1); - if iter_tiles_of_area((new_x, player_y), (8, 8)) + let new_p = Position { x: player.x - 1, y: player.y }; + let new_r = Rect { x: new_p.x, y: new_p.y, w: 8, h: 8 }; + if iter_tiles_of_area(new_p, (8, 8)) .all(|(tx, ty)| allows_movement(world[ty as usize][tx as usize])) + && enemies.iter().all(|enemy| { + let enemy_r = Rect { x: enemy.x, y: enemy.y, w: 8, h: 8 }; + !new_r.intersect(enemy_r) + }) { - player_x = new_x; + *player = new_p; } } if keys.right() { - let new_x = player_x.saturating_add(1); - if iter_tiles_of_area((new_x, player_y), (8, 8)) + let new_p = Position { x: player.x + 1, y: player.y }; + let new_r = Rect { x: new_p.x, y: new_p.y, w: 8, h: 8 }; + if iter_tiles_of_area(new_p, (8, 8)) .all(|(tx, ty)| allows_movement(world[ty as usize][tx as usize])) + && enemies.iter().all(|enemy| { + let enemy_r = Rect { x: enemy.x, y: enemy.y, w: 8, h: 8 }; + !new_r.intersect(enemy_r) + }) { - player_x = new_x; + *player = new_p; } } - - // ready our graphics for next frame - obj.set_x(player_x); - obj.set_y(player_y); } } @@ -120,10 +176,10 @@ const fn allows_movement(u: u8) -> bool { } fn iter_tiles_of_area( - (x, y): (u16, u16), (width, height): (u16, u16), + p: Position, (width, height): (u16, u16), ) -> impl Iterator { - let y_range_incl = (y / 8)..=((y + height - 1) / 8); - let x_range_incl = (x / 8)..=((x + width - 1) / 8); + let y_range_incl = (p.y / 8)..=((p.y + height - 1) / 8); + let x_range_incl = (p.x / 8)..=((p.x + width - 1) / 8); y_range_incl .map(move |y_index| { x_range_incl.clone().map(move |x_index| (x_index, y_index))