mirror of
https://github.com/italicsjenga/agb.git
synced 2025-01-11 09:31:34 +11:00
chicken object added
This commit is contained in:
parent
0bd99e71bd
commit
432c7f12f0
|
@ -2,19 +2,33 @@
|
|||
#![feature(start)]
|
||||
|
||||
extern crate gba;
|
||||
use core::convert::{Into, TryInto};
|
||||
use gba::{
|
||||
display::{object::ObjectStandard, tiled0, HEIGHT, WIDTH},
|
||||
number::Num,
|
||||
};
|
||||
|
||||
use gba::display::tiled0;
|
||||
struct Character {
|
||||
object: ObjectStandard,
|
||||
position: Vector2D,
|
||||
velocity: Vector2D,
|
||||
}
|
||||
|
||||
struct Vector2D {
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
fn frame_ranger(count: u32, start: u32, end: u32, delay: u32) -> u32 {
|
||||
((count / delay) % (end + 1 - start)) + start
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
let mut gba = gba::Gba::new();
|
||||
let mut gfx = gba.display.video.tiled0();
|
||||
let vblank = gba.display.vblank.get();
|
||||
let mut input = gba::input::ButtonController::new();
|
||||
|
||||
gfx.set_sprite_palette(&CHICKEN_PALETTE);
|
||||
gfx.set_sprite_tilemap(&CHICKEN_TILES);
|
||||
|
@ -33,8 +47,75 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
|||
gfx.background_0.set_screen_base_block(1);
|
||||
gfx.copy_to_map(1, &MAP_MAP);
|
||||
|
||||
let mut object = gfx.object;
|
||||
|
||||
object.enable();
|
||||
unsafe { object.clear_objects() };
|
||||
let mut chicken = Character {
|
||||
object: object.get_object(0),
|
||||
position: Vector2D {
|
||||
x: 20 << 8,
|
||||
y: 20 << 8,
|
||||
},
|
||||
velocity: Vector2D { x: 0, y: 0 },
|
||||
};
|
||||
|
||||
chicken.object.set_tile_id(0);
|
||||
chicken
|
||||
.object
|
||||
.set_x((chicken.position.x >> 8).try_into().unwrap());
|
||||
chicken
|
||||
.object
|
||||
.set_y((chicken.position.y >> 8).try_into().unwrap());
|
||||
chicken.object.commit();
|
||||
|
||||
let acceleration = 1 << 8;
|
||||
let mut frame_count = 0;
|
||||
|
||||
loop {
|
||||
vblank.wait_for_VBlank();
|
||||
frame_count += 1;
|
||||
|
||||
input.update();
|
||||
|
||||
// Horizontal movement
|
||||
chicken.velocity.x += (input.x_tri() as i32) * acceleration;
|
||||
chicken.velocity.x = 10 * chicken.velocity.x / 16;
|
||||
|
||||
// Update position based on velocity
|
||||
chicken.position.x += chicken.velocity.x;
|
||||
chicken.position.y += chicken.velocity.y;
|
||||
|
||||
// Ensure the chicken remains within bounds
|
||||
chicken.position.x = chicken.position.x.clamp(0, (WIDTH - 8) << 8);
|
||||
chicken.position.y = chicken.position.y.clamp(0, (HEIGHT - 8) << 8);
|
||||
|
||||
// Update direction the chicken is facing
|
||||
if chicken.velocity.x > 1 {
|
||||
chicken.object.set_hflip(false);
|
||||
} else if chicken.velocity.x < -1 {
|
||||
chicken.object.set_hflip(true);
|
||||
}
|
||||
|
||||
// Update the frame of the chicken
|
||||
if (chicken.velocity.x != 0) {
|
||||
chicken
|
||||
.object
|
||||
.set_tile_id(frame_ranger(frame_count, 1, 3, 10));
|
||||
} else {
|
||||
chicken.object.set_tile_id(0);
|
||||
}
|
||||
|
||||
// Update the position of the chicken
|
||||
chicken
|
||||
.object
|
||||
.set_x((chicken.position.x >> 8).try_into().unwrap());
|
||||
chicken
|
||||
.object
|
||||
.set_y((chicken.position.y >> 8).try_into().unwrap());
|
||||
|
||||
// Commit the chicken to vram
|
||||
chicken.object.commit();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,134 @@
|
|||
#[non_exhaustive]
|
||||
pub struct Object {}
|
||||
use super::DISPLAY_CONTROL;
|
||||
|
||||
impl Object {
|
||||
pub(crate) fn new() -> Self {
|
||||
Object {}
|
||||
const OBJECT_MEMORY_STANDARD: *mut [ObjectAttributeStandard; 128] = 0x0700_0000 as *mut [_; 128];
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct ObjectControl {}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct ObjectStandard {
|
||||
attributes: ObjectAttributeStandard,
|
||||
id: usize,
|
||||
}
|
||||
|
||||
pub enum Mode {
|
||||
Normal = 0,
|
||||
Affline = 1,
|
||||
Hidden = 2,
|
||||
AfflineDouble = 3,
|
||||
}
|
||||
|
||||
impl ObjectStandard {
|
||||
pub fn commit(&self) {
|
||||
unsafe {
|
||||
(&mut (*OBJECT_MEMORY_STANDARD)[self.id] as *mut ObjectAttributeStandard)
|
||||
.write_volatile(self.attributes)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enable(&mut self) {}
|
||||
|
||||
pub fn disable(&mut self) {}
|
||||
pub fn set_x(&mut self, x: u8) {
|
||||
self.attributes.set_x(x)
|
||||
}
|
||||
pub fn set_y(&mut self, y: u8) {
|
||||
self.attributes.set_y(y)
|
||||
}
|
||||
pub fn set_tile_id(&mut self, id: u32) {
|
||||
self.attributes.set_tile_id(id)
|
||||
}
|
||||
pub fn set_hflip(&mut self, hflip: bool) {
|
||||
self.attributes.set_hflip(hflip)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct ObjectAttributeStandard {
|
||||
low: u32,
|
||||
high: u32,
|
||||
}
|
||||
|
||||
impl ObjectAttributeStandard {
|
||||
pub fn set_hflip(&mut self, hflip: bool) {
|
||||
let mask = (1 << 0xC) << 16;
|
||||
let attr = self.low;
|
||||
let attr = attr & !mask;
|
||||
if hflip {
|
||||
self.low = attr | mask
|
||||
} else {
|
||||
self.low = attr
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_x(&mut self, x: u8) {
|
||||
let mask = ((1 << 8) - 1) << 16;
|
||||
let attr1 = self.low;
|
||||
let attr_without_x = attr1 & !mask;
|
||||
let attr_with_new_x = attr_without_x | ((x as u32) << 16);
|
||||
self.low = attr_with_new_x;
|
||||
}
|
||||
|
||||
pub fn set_y(&mut self, y: u8) {
|
||||
let mask = (1 << 8) - 1;
|
||||
let attr0 = self.low;
|
||||
let attr_without_y = attr0 & !mask;
|
||||
let attr_with_new_y = attr_without_y | y as u32;
|
||||
self.low = attr_with_new_y;
|
||||
}
|
||||
|
||||
pub fn set_tile_id(&mut self, id: u32) {
|
||||
let mask = (1 << 9) - 1;
|
||||
assert!(id <= mask, "tile id is greater than 9 bits");
|
||||
let attr = self.high;
|
||||
let attr = attr & !mask;
|
||||
let attr = attr | id;
|
||||
self.high = attr;
|
||||
}
|
||||
|
||||
pub fn set_mode(&mut self, mode: Mode) {
|
||||
let mask = 0b11 << 0x8;
|
||||
self.low = (self.low & !mask) | ((mode as u32) << 0x8);
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectAttributeStandard {
|
||||
fn new() -> Self {
|
||||
ObjectAttributeStandard { low: 0, high: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectControl {
|
||||
pub(crate) fn new() -> Self {
|
||||
ObjectControl {}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// Temporary
|
||||
pub unsafe fn clear_objects(&mut self) {
|
||||
let mut o = ObjectAttributeStandard::new();
|
||||
o.set_mode(Mode::Hidden);
|
||||
for index in 0..(*OBJECT_MEMORY_STANDARD).len() {
|
||||
(&mut (*OBJECT_MEMORY_STANDARD)[index] as *mut ObjectAttributeStandard)
|
||||
.write_volatile(o);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enable(&mut self) {
|
||||
let disp = DISPLAY_CONTROL.get();
|
||||
let disp = disp | (1 << 0x0C);
|
||||
DISPLAY_CONTROL.set(disp);
|
||||
}
|
||||
|
||||
pub fn disable(&mut self) {
|
||||
let disp = DISPLAY_CONTROL.get();
|
||||
let disp = disp & !(1 << 0x0C);
|
||||
DISPLAY_CONTROL.set(disp);
|
||||
}
|
||||
|
||||
pub fn get_object(&self, id: usize) -> ObjectStandard {
|
||||
assert!(id < 128, "object id must be less than 128");
|
||||
ObjectStandard {
|
||||
attributes: ObjectAttributeStandard::new(),
|
||||
id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use core::convert::TryInto;
|
|||
use crate::memory_mapped::MemoryMapped1DArray;
|
||||
|
||||
use super::{
|
||||
object::Object, set_graphics_mode, set_graphics_settings, DisplayMode, GraphicsSettings,
|
||||
object::ObjectControl, set_graphics_mode, set_graphics_settings, DisplayMode, GraphicsSettings,
|
||||
DISPLAY_CONTROL,
|
||||
};
|
||||
|
||||
|
@ -102,7 +102,7 @@ pub struct Tiled0 {
|
|||
pub background_1: Background,
|
||||
pub background_2: Background,
|
||||
pub background_3: Background,
|
||||
pub object: Object,
|
||||
pub object: ObjectControl,
|
||||
}
|
||||
|
||||
impl Tiled0 {
|
||||
|
@ -114,7 +114,7 @@ impl Tiled0 {
|
|||
background_1: Background { layer: 1 },
|
||||
background_2: Background { layer: 2 },
|
||||
background_3: Background { layer: 3 },
|
||||
object: Object::new(),
|
||||
object: ObjectControl::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue