Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convenience slot set #460

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8c86262
provide a handy trait for setting objects in oam
corwinkuiper Jul 19, 2023
504e799
use OamDisplay in amplitude to set oam slots
corwinkuiper Jul 19, 2023
b220d94
finish early if oam slots are full
corwinkuiper Jul 19, 2023
d51f170
replace with our own type
corwinkuiper Jul 19, 2023
1eef7f8
remove options
corwinkuiper Jul 19, 2023
86e6a71
take by value, remove managed
corwinkuiper Jul 19, 2023
c981587
remove unused
corwinkuiper Jul 19, 2023
5d997de
add must use
corwinkuiper Jul 19, 2023
1a2c060
remove unused method
corwinkuiper Jul 19, 2023
df13211
opportunistic garbage collect
corwinkuiper Jul 19, 2023
0d107ea
inline pointless functions
corwinkuiper Jul 19, 2023
5d81b15
use statics instead of consts
corwinkuiper Jul 19, 2023
1821abe
double check the location of the sprite
corwinkuiper Jul 19, 2023
51d95c5
use link section of the sprite's bytes
corwinkuiper Jul 19, 2023
6e6db92
emit link sections for sprite constituents
corwinkuiper Jul 19, 2023
bdd3487
remove untrue asserttions in multiboot
corwinkuiper Jul 19, 2023
111527f
use new api in examples
corwinkuiper Jul 19, 2023
fc0fa2c
remove unused imports
corwinkuiper Jul 19, 2023
63a8a71
Fix amplitude
corwinkuiper Jul 19, 2023
d73aadf
update linker scripts
corwinkuiper Jul 20, 2023
241e7d1
completely "modernise" the code
corwinkuiper Jul 20, 2023
4ed141c
add set_at for more composability
corwinkuiper Jul 21, 2023
052d98b
fix doc examples
corwinkuiper Jul 25, 2023
a4fa688
don't display sprites that cannot be seen
corwinkuiper Jul 25, 2023
979cb56
update hat chooses wizard
corwinkuiper Jul 25, 2023
aedd133
fix lints
corwinkuiper Jul 25, 2023
44ea85e
clean up when objects are made
corwinkuiper Jul 25, 2023
e4541fb
use oamdisplay trait for text
corwinkuiper Jul 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions agb-image-converter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,15 +377,18 @@ pub fn include_aseprite_inner(input: TokenStream) -> TokenStream {
#(#include_paths)*


const PALETTES: &[Palette16] = &[
#[link_section = ".sprites.palettes"]
static PALETTES: &[Palette16] = &[
#(#palette_data),*
];

pub const SPRITES: &[Sprite] = &[
#[link_section = ".sprites.sprites"]
static SPRITES: &[Sprite] = &[
#(#sprites),*
];

const TAGS: &TagMap = &TagMap::new(
#[link_section = ".sprites.tags"]
static TAGS: &TagMap = &TagMap::new(
&[
#(#tags),*
]
Expand Down
195 changes: 98 additions & 97 deletions agb/examples/chicken.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
use agb::{
display::tiled::{TileFormat, TileSet, TileSetting, TiledMap},
display::{
object::{OamManaged, Object, Size, Sprite},
object::{OamDisplay, ObjectUnmanaged, Size, Sprite, SpriteLoader, SpriteVram},
palette16::Palette16,
tiled::RegularBackgroundSize,
HEIGHT, WIDTH,
},
input::Button,
};
use core::convert::TryInto;
use agb_fixnum::{num, Num, Vector2D};

#[derive(PartialEq, Eq)]
enum State {
Expand All @@ -20,27 +20,50 @@ enum State {
Flapping,
}

struct Character<'a> {
object: Object<'a>,
position: Vector2D,
velocity: Vector2D,
struct Character {
sprite: SpriteVram,
position: Vector2D<Num<i32, 8>>,
velocity: Vector2D<Num<i32, 8>>,
flipped: bool,
}

struct Vector2D {
x: i32,
y: i32,
impl OamDisplay for &Character {
fn set_in(
self,
oam: &mut agb::display::object::OamIterator,
) -> agb::display::object::OamDisplayResult {
ObjectUnmanaged::new(self.sprite.clone())
.set_position((self.position + (num!(0.5), num!(0.5)).into()).floor() - (4, 4).into())
.set_hflip(self.flipped)
.set_in(oam)
}
}

fn tile_is_collidable(tile: u16) -> bool {
let masked = tile & 0b0000001111111111;
masked == 0 || masked == 4
}

fn position_is_colliding(tiles: &[[u16; 32]; 32], position: Vector2D<Num<i32, 8>>) -> bool {
fn inner_check(tiles: &[[u16; 32]; 32], position: Vector2D<Num<i32, 8>>) -> Option<bool> {
let position = position.floor() / 8;
Some(tile_is_collidable(
*tiles.get(position.y as usize)?.get(position.x as usize)?,
))
}

inner_check(tiles, position).unwrap_or(true)
}

fn frame_ranger(count: u32, start: u32, end: u32, delay: u32) -> usize {
(((count / delay) % (end + 1 - start)) + start) as usize
}

#[agb::entry]
fn entry(gba: agb::Gba) -> ! {
main(gba);
}

fn main(mut gba: agb::Gba) -> ! {
let map_as_grid: &[[u16; 32]; 32] = unsafe {
(&MAP_MAP as *const [u16; 1024] as *const [[u16; 32]; 32])
Expand Down Expand Up @@ -74,46 +97,39 @@ fn main(mut gba: agb::Gba) -> ! {
background.show();
background.commit(&mut vram);

let object = gba.display.object.get_managed();
let (mut oam, mut sprite_loader) = gba.display.object.get();

let sprite = object.sprite(&CHICKEN_SPRITES[0]);
let sprite = sprite_loader.get_vram_sprite(&CHICKEN_SPRITES[0]);
let mut chicken = Character {
object: object.object(sprite),
sprite,
position: Vector2D {
x: (6 * 8) << 8,
y: ((7 * 8) - 4) << 8,
x: (6 * 8).into(),
y: ((7 * 8) - 4).into(),
},
velocity: Vector2D { x: 0, y: 0 },
velocity: Vector2D {
x: 0.into(),
y: 0.into(),
},
flipped: false,
};

chicken
.object
.set_x((chicken.position.x >> 8).try_into().unwrap());
chicken
.object
.set_y((chicken.position.y >> 8).try_into().unwrap());
chicken.object.show();

object.commit();

let acceleration = 1 << 4;
let gravity = 1 << 4;
let acceleration = num!(0.0625);
let gravity = num!(0.0625);
let flapping_gravity = gravity / 3;
let jump_velocity = 1 << 9;
let jump_velocity = num!(2.);
let mut frame_count = 0;
let mut frames_off_ground = 0;

let terminal_velocity = (1 << 8) / 2;
let terminal_velocity = num!(0.5);

loop {
vblank.wait_for_vblank();
frame_count += 1;

input.update();

// Horizontal movement
chicken.velocity.x += (input.x_tri() as i32) * acceleration;
chicken.velocity.x = 61 * chicken.velocity.x / 64;
chicken.velocity.x += acceleration * (input.x_tri() as i32);
chicken.velocity.x = (chicken.velocity.x * 61) / 64;

// Update position based on collision detection
let state = handle_collision(
Expand All @@ -137,103 +153,89 @@ fn main(mut gba: agb::Gba) -> ! {
}

restrict_to_screen(&mut chicken);
update_chicken_object(&mut chicken, &object, state, frame_count);

object.commit();
update_chicken_object(&mut chicken, &mut sprite_loader, state, frame_count);
vblank.wait_for_vblank();
chicken.set_in(&mut oam.iter());
}
}

fn update_chicken_object(
chicken: &'_ mut Character<'_>,
gfx: &OamManaged,
chicken: &mut Character,
sprite_loader: &mut SpriteLoader,
state: State,
frame_count: u32,
) {
if chicken.velocity.x > 1 {
chicken.object.set_hflip(false);
} else if chicken.velocity.x < -1 {
chicken.object.set_hflip(true);
match chicken.velocity.x.to_raw().signum() {
1 => chicken.flipped = false,
-1 => chicken.flipped = true,
_ => {}
}

match state {
State::Ground => {
if chicken.velocity.x.abs() > 1 << 4 {
chicken
.object
.set_sprite(gfx.sprite(&CHICKEN_SPRITES[frame_ranger(frame_count, 1, 3, 10)]));
if chicken.velocity.x.abs() > num!(0.0625) {
chicken.sprite = sprite_loader
.get_vram_sprite(&CHICKEN_SPRITES[frame_ranger(frame_count, 1, 3, 10)]);
} else {
chicken.object.set_sprite(gfx.sprite(&CHICKEN_SPRITES[0]));
chicken.sprite = sprite_loader.get_vram_sprite(&CHICKEN_SPRITES[0]);
}
}
State::Upwards => {}
State::Flapping => {
chicken
.object
.set_sprite(gfx.sprite(&CHICKEN_SPRITES[frame_ranger(frame_count, 4, 5, 5)]));
chicken.sprite =
sprite_loader.get_vram_sprite(&CHICKEN_SPRITES[frame_ranger(frame_count, 4, 5, 5)]);
}
}

let x: u16 = (chicken.position.x >> 8).try_into().unwrap();
let y: u16 = (chicken.position.y >> 8).try_into().unwrap();

chicken.object.set_x(x - 4);
chicken.object.set_y(y - 4);
}

fn restrict_to_screen(chicken: &mut Character) {
if chicken.position.x > (WIDTH - 8 + 4) << 8 {
chicken.velocity.x = 0;
chicken.position.x = (WIDTH - 8 + 4) << 8;
} else if chicken.position.x < 4 << 8 {
chicken.velocity.x = 0;
chicken.position.x = 4 << 8;
if chicken.position.x > (WIDTH - 8 + 4).into() {
chicken.velocity.x = 0.into();
chicken.position.x = (WIDTH - 8 + 4).into();
} else if chicken.position.x < 4.into() {
chicken.velocity.x = 0.into();
chicken.position.x = 4.into();
}
if chicken.position.y > (HEIGHT - 8 + 4) << 8 {
chicken.velocity.y = 0;
chicken.position.y = (HEIGHT - 8 + 4) << 8;
} else if chicken.position.y < 4 << 8 {
chicken.velocity.y = 0;
chicken.position.y = 4 << 8;
if chicken.position.y > (HEIGHT - 8 + 4).into() {
chicken.velocity.y = 0.into();
chicken.position.y = (HEIGHT - 8 + 4).into();
} else if chicken.position.y < 4.into() {
chicken.velocity.y = 0.into();
chicken.position.y = 4.into();
}
}

fn handle_collision(
chicken: &mut Character,
map_as_grid: &[[u16; 32]; 32],
gravity: i32,
flapping_gravity: i32,
terminal_velocity: i32,
gravity: Num<i32, 8>,
flapping_gravity: Num<i32, 8>,
terminal_velocity: Num<i32, 8>,
) -> State {
let mut new_chicken_x = chicken.position.x + chicken.velocity.x;
let mut new_chicken_y = chicken.position.y + chicken.velocity.y;

let tile_x = ((new_chicken_x >> 8) / 8) as usize;
let tile_y = ((new_chicken_y >> 8) / 8) as usize;

let left = (((new_chicken_x >> 8) - 4) / 8) as usize;
let right = (((new_chicken_x >> 8) + 4) / 8) as usize;
let top = (((new_chicken_y >> 8) - 4) / 8) as usize;
let bottom = (((new_chicken_y >> 8) + 4) / 8) as usize;

if chicken.velocity.x < 0 && tile_is_collidable(map_as_grid[tile_y][left]) {
new_chicken_x = (((left + 1) * 8 + 4) << 8) as i32;
chicken.velocity.x = 0;
} else if chicken.velocity.x > 0 && tile_is_collidable(map_as_grid[tile_y][right]) {
new_chicken_x = ((right * 8 - 4) << 8) as i32;
chicken.velocity.x = 0;
let mut new_chicken_positon = chicken.position + chicken.velocity;

if (chicken.velocity.x < 0.into()
&& position_is_colliding(map_as_grid, new_chicken_positon - (4, 0).into()))
|| (chicken.velocity.x > 0.into()
&& position_is_colliding(map_as_grid, new_chicken_positon + (4, 0).into()))
{
new_chicken_positon.x = (new_chicken_positon.x.floor() / 8 * 8 + 4).into();
chicken.velocity.x = 0.into();
}

if chicken.velocity.y < 0 && tile_is_collidable(map_as_grid[top][tile_x]) {
new_chicken_y = ((((top + 1) * 8 + 4) << 8) + 4) as i32;
chicken.velocity.y = 0;
} else if chicken.velocity.y > 0 && tile_is_collidable(map_as_grid[bottom][tile_x]) {
new_chicken_y = ((bottom * 8 - 4) << 8) as i32;
chicken.velocity.y = 0;
if (chicken.velocity.y < 0.into()
&& position_is_colliding(map_as_grid, new_chicken_positon - (0, 4).into()))
|| (chicken.velocity.y > 0.into()
&& position_is_colliding(map_as_grid, new_chicken_positon + (0, 4).into()))
{
new_chicken_positon.y = (new_chicken_positon.y.floor() / 8 * 8 + 4).into();
chicken.velocity.y = 0.into();
}

let mut air_animation = State::Ground;

if !tile_is_collidable(map_as_grid[bottom][tile_x]) {
if chicken.velocity.y < 0 {
if !position_is_colliding(map_as_grid, new_chicken_positon + (0, 4).into()) {
if chicken.velocity.y < 0.into() {
air_animation = State::Upwards;
chicken.velocity.y += gravity;
} else {
Expand All @@ -245,8 +247,7 @@ fn handle_collision(
}
}

chicken.position.x = new_chicken_x;
chicken.position.y = new_chicken_y;
chicken.position = new_chicken_positon;

air_animation
}
Expand Down
8 changes: 4 additions & 4 deletions agb/examples/object_text_render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use agb::{
display::{
object::{ChangeColour, ObjectTextRender, PaletteVram, Size, TextAlignment},
object::{ChangeColour, OamDisplay, ObjectTextRender, PaletteVram, Size, TextAlignment},
palette16::Palette16,
Font, HEIGHT, WIDTH,
},
Expand All @@ -22,7 +22,7 @@ fn entry(gba: agb::Gba) -> ! {
}

fn main(mut gba: agb::Gba) -> ! {
let (mut unmanaged, _sprites) = gba.display.object.get_unmanaged();
let (mut unmanaged, _sprites) = gba.display.object.get();

loop {
let mut palette = [0x0; 16];
Expand Down Expand Up @@ -74,7 +74,7 @@ fn main(mut gba: agb::Gba) -> ! {
vblank.wait_for_vblank();
input.update();
let oam = &mut unmanaged.iter();
wr.commit(oam);
wr.set_at(oam, (0, HEIGHT - 40).into());

let start = timer.value();
if frame % 4 == 0 {
Expand All @@ -84,7 +84,7 @@ fn main(mut gba: agb::Gba) -> ! {
line_done = false;
wr.pop_line();
}
wr.update((0, HEIGHT - 40).into());
wr.update();
let end = timer.value();

frame += 1;
Expand Down
Loading