mirror of
https://github.com/italicsjenga/gba.git
synced 2025-01-10 02:51:31 +11:00
obj to obj intersection.
This commit is contained in:
parent
a90cfdab3b
commit
cb2be577b1
124
examples/game.rs
124
examples/game.rs
|
@ -1,8 +1,6 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use core::num::Wrapping;
|
|
||||||
|
|
||||||
use gba::prelude::*;
|
use gba::prelude::*;
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
|
@ -14,11 +12,43 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
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]
|
#[no_mangle]
|
||||||
extern "C" fn main() -> ! {
|
extern "C" fn main() -> ! {
|
||||||
// game simulation setup
|
// game simulation setup
|
||||||
let mut player_x = 13_u16;
|
let mut creatures = [Position::default(); 5];
|
||||||
let mut player_y = 37_u16;
|
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];
|
let mut world = [[0_u8; 32]; 32];
|
||||||
for i in 0..32 {
|
for i in 0..32 {
|
||||||
world[0][i] = b'z';
|
world[0][i] = b'z';
|
||||||
|
@ -26,9 +56,9 @@ extern "C" fn main() -> ! {
|
||||||
world[i][0] = b'z';
|
world[i][0] = b'z';
|
||||||
world[i][31] = b'z';
|
world[i][31] = b'z';
|
||||||
}
|
}
|
||||||
world[1][1] = b'B';
|
world[1][3] = b'B';
|
||||||
world[2][1] = b'G';
|
world[2][3] = b'G';
|
||||||
world[3][1] = b'0';
|
world[3][3] = b'0';
|
||||||
|
|
||||||
// hardware configuration
|
// hardware configuration
|
||||||
DISPSTAT.write(DisplayStatus::new().with_irq_vblank(true));
|
DISPSTAT.write(DisplayStatus::new().with_irq_vblank(true));
|
||||||
|
@ -39,6 +69,10 @@ extern "C" fn main() -> ! {
|
||||||
|
|
||||||
BG_PALETTE.index(1).write(Color::MAGENTA);
|
BG_PALETTE.index(1).write(Color::MAGENTA);
|
||||||
OBJ_PALETTE.index(1).write(Color::CYAN);
|
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(CHARBLOCK0_4BPP.as_region(), 0);
|
||||||
Cga8x8Thick.bitunpack_4bpp(OBJ_TILES.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);
|
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));
|
DISPCNT.write(DisplayControl::new().with_show_obj(true).with_show_bg0(true));
|
||||||
|
|
||||||
|
@ -68,7 +96,16 @@ extern "C" fn main() -> ! {
|
||||||
VBlankIntrWait();
|
VBlankIntrWait();
|
||||||
|
|
||||||
// update graphics MMIO
|
// 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
|
// handle input
|
||||||
let keys = KEYINPUT.read();
|
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
|
// 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
|
// will be halted by the wall. This makes the player slide along the wall
|
||||||
// when bumping into walls.
|
// when bumping into walls.
|
||||||
|
let (player, enemies) = match &mut creatures {
|
||||||
|
[player, enemies @ ..] => (player, enemies),
|
||||||
|
};
|
||||||
if keys.up() {
|
if keys.up() {
|
||||||
let new_y = player_y.saturating_sub(1);
|
let new_p = Position { x: player.x, y: player.y - 1 };
|
||||||
if iter_tiles_of_area((player_x, new_y), (8, 8))
|
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]))
|
.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() {
|
if keys.down() {
|
||||||
let new_y = player_y.saturating_add(1);
|
let new_p = Position { x: player.x, y: player.y + 1 };
|
||||||
if iter_tiles_of_area((player_x, new_y), (8, 8))
|
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]))
|
.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() {
|
if keys.left() {
|
||||||
let new_x = player_x.saturating_sub(1);
|
let new_p = Position { x: player.x - 1, y: player.y };
|
||||||
if iter_tiles_of_area((new_x, player_y), (8, 8))
|
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]))
|
.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() {
|
if keys.right() {
|
||||||
let new_x = player_x.saturating_add(1);
|
let new_p = Position { x: player.x + 1, y: player.y };
|
||||||
if iter_tiles_of_area((new_x, player_y), (8, 8))
|
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]))
|
.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(
|
fn iter_tiles_of_area(
|
||||||
(x, y): (u16, u16), (width, height): (u16, u16),
|
p: Position, (width, height): (u16, u16),
|
||||||
) -> impl Iterator<Item = (u16, u16)> {
|
) -> impl Iterator<Item = (u16, u16)> {
|
||||||
let y_range_incl = (y / 8)..=((y + height - 1) / 8);
|
let y_range_incl = (p.y / 8)..=((p.y + height - 1) / 8);
|
||||||
let x_range_incl = (x / 8)..=((x + width - 1) / 8);
|
let x_range_incl = (p.x / 8)..=((p.x + width - 1) / 8);
|
||||||
y_range_incl
|
y_range_incl
|
||||||
.map(move |y_index| {
|
.map(move |y_index| {
|
||||||
x_range_incl.clone().map(move |x_index| (x_index, y_index))
|
x_range_incl.clone().map(move |x_index| (x_index, y_index))
|
||||||
|
|
Loading…
Reference in a new issue