Deduplicate background tiles (#477)

This started as an attempt to get dungeon puzzler in the combo rom,
ended up fixing a _load_ of 256 colour bugs and the ability to
deduplicate tiles you import.

Fixes #448

- [x] Changelog updated / no changelog update needed
This commit is contained in:
Gwilym Inzani 2023-08-29 20:02:38 +01:00 committed by GitHub
commit dc5bf9de98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 711 additions and 201 deletions

View file

@ -12,14 +12,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- New tracker for playing XM files (see the `agb-tracker` crate).
- You can now declare where looping sound channels should restart.
- Fixnums now have constructors from_f32 and from_f64. This is mainly useful if using agb-fixnum outside of the Game Boy Advance e.g. in build scripts or macros.
- New option when loading a background to automatically deduplicate tiles.
- Methods on tile_setting to toggle its hflip and vflip status.
### Changed
- Sound channel panning and volume options are now `Num<i16, 8>` rather than `Num<i16, 4>` for improved precision and sound quality.
- Due to dependency changes, agb-gbafix is now released under MPL rather than GPL.
- `include_background_gfx!` now produces tile settings directly rather than palette assigments.
### Fixed
- 256-colour backgrounds are better supported.
- Mono looping samples will now correctly play to the end if it doesn't perfectly align with a buffer boundry and short samples now also loop correctly.
## [0.16.0] - 2023/07/18

View file

@ -11,4 +11,5 @@ pub(crate) trait Config {
pub(crate) trait Image {
fn filename(&self) -> String;
fn colours(&self) -> Colours;
fn deduplicate(&self) -> bool;
}

View file

@ -0,0 +1,152 @@
use std::{collections::HashMap, hash::BuildHasher};
use crate::{colour::Colour, image_loader::Image};
pub struct Transformation {
pub vflip: bool,
pub hflip: bool,
}
impl Transformation {
pub fn none() -> Self {
Self {
vflip: false,
hflip: false,
}
}
pub fn vflipped() -> Self {
Self {
vflip: true,
hflip: false,
}
}
pub fn hflipped() -> Self {
Self {
vflip: false,
hflip: true,
}
}
pub fn vhflipped() -> Self {
Self {
vflip: true,
hflip: true,
}
}
}
pub struct DeduplicatedData {
pub new_index: usize,
pub transformation: Transformation,
}
#[derive(Clone, PartialEq, Eq, Hash)]
struct Tile {
data: [Colour; 64],
}
impl Tile {
fn split_image(input: &Image) -> Vec<Self> {
let mut ret = vec![];
for y in 0..(input.height / 8) {
for x in 0..(input.width / 8) {
let mut tile_data = Vec::with_capacity(64);
for j in 0..8 {
for i in 0..8 {
tile_data.push(input.colour(x * 8 + i, y * 8 + j));
}
}
ret.push(Tile {
data: tile_data.try_into().unwrap(),
});
}
}
ret
}
fn vflipped(&self) -> Self {
let mut new_data = self.data;
for y in 0..4 {
for x in 0..8 {
new_data.swap(y * 8 + x, (7 - y) * 8 + x);
}
}
Self { data: new_data }
}
fn hflipped(&self) -> Self {
let mut new_data = self.data;
for y in 0..8 {
for x in 0..4 {
new_data.swap(y * 8 + x, y * 8 + (7 - x));
}
}
Self { data: new_data }
}
}
pub(crate) fn deduplicate_image(input: &Image, can_flip: bool) -> (Image, Vec<DeduplicatedData>) {
let mut resulting_tiles = vec![];
let mut deduplication_data = vec![];
let all_tiles = Tile::split_image(input);
let mut existing_tiles = HashMap::new();
let hasher = std::collections::hash_map::RandomState::new();
for tile in all_tiles {
let (tile, transformation) = if can_flip {
let vflipped = tile.vflipped();
let hflipped = tile.hflipped();
let vhflipped = vflipped.hflipped();
// find the one with the smallest hash
let tile_hash = hasher.hash_one(&tile);
let vflipped_hash = hasher.hash_one(&vflipped);
let hflipped_hash = hasher.hash_one(&hflipped);
let vhflipped_hash = hasher.hash_one(&vhflipped);
let minimum = tile_hash
.min(vflipped_hash)
.min(hflipped_hash)
.min(vhflipped_hash);
if minimum == tile_hash {
(tile, Transformation::none())
} else if minimum == vflipped_hash {
(vflipped, Transformation::vflipped())
} else if minimum == hflipped_hash {
(hflipped, Transformation::hflipped())
} else {
(vhflipped, Transformation::vhflipped())
}
} else {
(tile, Transformation::none())
};
let index = *existing_tiles.entry(tile.clone()).or_insert_with(|| {
resulting_tiles.push(tile);
resulting_tiles.len() - 1
});
deduplication_data.push(DeduplicatedData {
new_index: index,
transformation,
});
}
let image_data = resulting_tiles
.iter()
.flat_map(|tile| tile.data)
.collect::<Vec<_>>();
(Image::from_colour_data(image_data), deduplication_data)
}

View file

@ -4,6 +4,7 @@ use image::{DynamicImage, GenericImageView};
use crate::colour::Colour;
#[derive(Clone)]
pub(crate) struct Image {
pub width: usize,
pub height: usize,
@ -42,6 +43,14 @@ impl Image {
}
}
pub fn from_colour_data(colour_data: Vec<Colour>) -> Self {
Self {
height: colour_data.len() / 8,
colour_data,
width: 8,
}
}
pub fn colour(&self, x: usize, y: usize) -> Colour {
self.colour_data[x + y * self.width]
}

View file

@ -15,6 +15,7 @@ use quote::{format_ident, quote, ToTokens};
mod aseprite;
mod colour;
mod config;
mod deduplicator;
mod font_loader;
mod image_loader;
mod palette16;
@ -36,6 +37,7 @@ struct BackgroundGfxOption {
module_name: String,
file_name: String,
colours: Colours,
deduplicate: bool,
}
impl config::Image for BackgroundGfxOption {
@ -46,6 +48,10 @@ impl config::Image for BackgroundGfxOption {
fn colours(&self) -> Colours {
self.colours
}
fn deduplicate(&self) -> bool {
self.deduplicate
}
}
impl Parse for BackgroundGfxOption {
@ -72,12 +78,30 @@ impl Parse for BackgroundGfxOption {
Colours::Colours16
};
let lookahead = input.lookahead1();
let deduplicate = if lookahead.peek(syn::Ident) {
let deduplicate: syn::Ident = input.parse()?;
if deduplicate == "deduplicate" {
true
} else {
return Err(syn::Error::new_spanned(
deduplicate,
"Must either be the literal deduplicate or missing",
));
}
} else {
false
};
let file_name: syn::LitStr = input.parse()?;
Ok(Self {
module_name: module_name.to_string(),
file_name: file_name.value(),
colours,
deduplicate,
})
}
}
@ -406,6 +430,7 @@ fn convert_image(
) -> proc_macro2::TokenStream {
let image_filename = &parent.join(settings.filename());
let image = Image::load_from_file(image_filename);
let deduplicate = settings.deduplicate();
rust_generator::generate_code(
variable_name,
@ -414,6 +439,7 @@ fn convert_image(
&image_filename.to_string_lossy(),
crate_prefix.to_owned(),
assignment_offset,
deduplicate,
)
}
@ -468,7 +494,14 @@ fn palette_tile_data(
let mut tile_data = Vec::new();
for (image_idx, image) in images.iter().enumerate() {
add_image_to_tile_data(&mut tile_data, image, optimiser, image_idx, true)
add_image_to_tile_data(
&mut tile_data,
image,
optimiser,
image_idx,
true,
&(0..images.len()).collect::<Vec<_>>(),
);
}
let tile_data = collapse_to_4bpp(&tile_data);
@ -491,6 +524,7 @@ fn add_image_to_tile_data(
optimiser: &Palette16OptimisationResults,
assignment_offset: usize,
is_sprite: bool,
remap_index: &[usize],
) {
let tile_size = 8;
let tiles_x = image.width / tile_size;
@ -501,7 +535,7 @@ fn add_image_to_tile_data(
let assignment = if is_sprite {
assignment_offset
} else {
y * tiles_x + x + assignment_offset
remap_index[y * tiles_x + x] + assignment_offset
};
let palette_index = optimiser.assignments[assignment];

View file

@ -1,3 +1,4 @@
use crate::deduplicator::{DeduplicatedData, Transformation};
use crate::palette16::Palette16OptimisationResults;
use crate::{add_image_256_to_tile_data, add_image_to_tile_data, collapse_to_4bpp};
use crate::{image_loader::Image, ByteString};
@ -5,6 +6,7 @@ use crate::{image_loader::Image, ByteString};
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use std::collections::BTreeMap;
use std::iter;
pub(crate) fn generate_palette_code(
@ -40,36 +42,77 @@ pub(crate) fn generate_code(
image_filename: &str,
crate_prefix: String,
assignment_offset: Option<usize>,
deduplicate: bool,
) -> TokenStream {
let crate_prefix = format_ident!("{}", crate_prefix);
let output_variable_name = format_ident!("{}", output_variable_name);
let (image, dedup_data) = if deduplicate {
let (new_image, dedup_data) =
crate::deduplicator::deduplicate_image(image, assignment_offset.is_some());
(new_image, dedup_data)
} else {
(
image.clone(),
(0..(image.width * image.height / 8 / 8))
.map(|i| DeduplicatedData {
new_index: i,
transformation: Transformation::none(),
})
.collect(),
)
};
let remap_index = dedup_data
.iter()
.enumerate()
.map(|(i, data)| (data.new_index, i))
.collect::<BTreeMap<_, _>>(); // BTreeMap so that values below is in order
let remap_index = remap_index.values().cloned().collect::<Vec<_>>();
let (tile_data, assignments) = if let Some(assignment_offset) = assignment_offset {
let mut tile_data = Vec::new();
add_image_to_tile_data(&mut tile_data, image, results, assignment_offset, false);
add_image_to_tile_data(
&mut tile_data,
&image,
results,
assignment_offset,
false,
&remap_index,
);
let tile_data = collapse_to_4bpp(&tile_data);
let num_tiles = image.width * image.height / 8usize.pow(2);
let assignments = results
.assignments
.iter()
.skip(assignment_offset)
.take(num_tiles)
.map(|&x| x as u8)
let all_assignments = &results.assignments[assignment_offset..];
let assignments = (0..num_tiles)
.map(|tile_id| all_assignments[remap_index[tile_id]] as u8)
.collect();
(tile_data, assignments)
} else {
let mut tile_data = Vec::new();
add_image_256_to_tile_data(&mut tile_data, image, results);
add_image_256_to_tile_data(&mut tile_data, &image, results);
(tile_data, vec![])
};
let tile_settings = dedup_data.iter().map(|data| {
let palette_assignment = assignments.get(data.new_index).unwrap_or(&0);
let vflipped = data.transformation.vflip;
let hflipped = data.transformation.hflip;
let index = data.new_index as u16;
quote! {
#crate_prefix::display::tiled::TileSetting::new(#index, #hflipped, #vflipped, #palette_assignment)
}
});
let data = ByteString(&tile_data);
quote! {
@ -91,11 +134,11 @@ pub(crate) fn generate_code(
&ALIGNED.bytes
};
const PALETTE_ASSIGNMENT: &[u8] = &[
#(#assignments),*
const TILE_SETTINGS: &[#crate_prefix::display::tiled::TileSetting] = &[
#(#tile_settings),*
];
#crate_prefix::display::tile_data::TileData::new(TILE_DATA, PALETTE_ASSIGNMENT)
#crate_prefix::display::tile_data::TileData::new(TILE_DATA, TILE_SETTINGS)
};
}
}

View file

@ -3,7 +3,7 @@
use agb::{
display::{
tiled::{RegularBackgroundSize, TileFormat, TileSet, TileSetting, TiledMap},
tiled::{RegularBackgroundSize, TileFormat, TileSet, TiledMap},
Priority,
},
include_background_gfx,
@ -32,7 +32,7 @@ fn main(mut gba: agb::Gba) -> ! {
&mut vram,
(x, y).into(),
&tileset,
TileSetting::new(0, false, false, 0),
water_tiles::water_tiles.tile_settings[0],
);
}
}

View file

@ -1,6 +1,6 @@
use super::tiled::{RegularMap, TileFormat, TileSet, TileSetting, TiledMap, VRamManager};
use super::tiled::{RegularMap, TileFormat, TileSet, TiledMap, VRamManager};
crate::include_background_gfx!(crate, agb_logo, test_logo => "gfx/test_logo.png");
crate::include_background_gfx!(crate, agb_logo, test_logo => deduplicate "gfx/test_logo.png");
pub fn display_logo(map: &mut RegularMap, vram: &mut VRamManager) {
vram.set_background_palettes(agb_logo::PALETTES);
@ -11,10 +11,12 @@ pub fn display_logo(map: &mut RegularMap, vram: &mut VRamManager) {
for x in 0..30 {
let tile_id = y * 30 + x;
let palette_entry = agb_logo::test_logo.palette_assignments[tile_id as usize];
let tile_setting = TileSetting::new(tile_id, false, false, palette_entry);
map.set_tile(vram, (x, y).into(), &background_tilemap, tile_setting);
map.set_tile(
vram,
(x as u16, y as u16).into(),
&background_tilemap,
agb_logo::test_logo.tile_settings[tile_id],
);
}
}

View file

@ -1,15 +1,17 @@
use super::tiled::TileSetting;
#[non_exhaustive]
pub struct TileData {
pub tiles: &'static [u8],
pub palette_assignments: &'static [u8],
pub tile_settings: &'static [TileSetting],
}
impl TileData {
#[must_use]
pub const fn new(tiles: &'static [u8], palette_assignments: &'static [u8]) -> Self {
pub const fn new(tiles: &'static [u8], tile_settings: &'static [TileSetting]) -> Self {
TileData {
tiles,
palette_assignments,
tile_settings,
}
}
}

View file

@ -10,7 +10,7 @@ use crate::memory_mapped::MemoryMapped;
use super::{
AffineBackgroundSize, BackgroundID, BackgroundSize, BackgroundSizePrivate,
RegularBackgroundSize, Tile, TileFormat, TileIndex, TileSet, TileSetting, VRamManager,
RegularBackgroundSize, Tile, TileFormat, TileSet, TileSetting, VRamManager,
};
use alloc::{vec, vec::Vec};
@ -20,10 +20,9 @@ pub trait TiledMapTypes: private::Sealed {
}
trait TiledMapPrivate: TiledMapTypes {
type TileType: Into<TileIndex> + Copy + Default + Eq + PartialEq;
type AffineMatrix;
fn tiles_mut(&mut self) -> &mut [Self::TileType];
fn tiles_mut(&mut self) -> &mut [Tile];
fn tiles_dirty(&mut self) -> &mut bool;
fn colours(&self) -> TileFormat;
@ -59,9 +58,11 @@ where
T::Size: BackgroundSizePrivate,
{
fn clear(&mut self, vram: &mut VRamManager) {
let colours = self.colours();
for tile in self.tiles_mut() {
if *tile != Default::default() {
vram.remove_tile((*tile).into());
vram.remove_tile(tile.tile_index(colours));
}
*tile = Default::default();
@ -82,18 +83,18 @@ where
fn commit(&mut self, vram: &mut VRamManager) {
let screenblock_memory = self.screenblock_memory();
let tile_count_divisor = self.colours().tile_size() / TileFormat::FourBpp.tile_size();
if *self.tiles_dirty() {
unsafe {
dma_copy16(
self.tiles_mut().as_ptr() as *const u16,
screenblock_memory,
self.map_size().num_tiles() / tile_count_divisor,
self.map_size().num_tiles(),
);
}
}
let tile_colour_flag: u16 = (tile_count_divisor == 2).into();
let tile_colour_flag: u16 = (self.colours() == TileFormat::EightBpp).into();
let new_bg_control_value = (self.priority() as u16)
| ((self.screenblock() as u16) << 8)
@ -134,10 +135,9 @@ impl TiledMapTypes for RegularMap {
}
impl TiledMapPrivate for RegularMap {
type TileType = Tile;
type AffineMatrix = ();
fn tiles_mut(&mut self) -> &mut [Self::TileType] {
fn tiles_mut(&mut self) -> &mut [Tile] {
&mut self.tiles
}
fn tiles_dirty(&mut self) -> &mut bool {
@ -195,11 +195,12 @@ impl RegularMap {
tileset: &TileSet<'_>,
tile_setting: TileSetting,
) {
if tileset.format() != self.colours() {
let colours = self.colours();
if tileset.format() != colours {
panic!(
"Cannot set a {:?} colour tile on a {:?} colour background",
tileset.format(),
self.colours()
colours
);
}
@ -207,7 +208,7 @@ impl RegularMap {
let old_tile = self.tiles_mut()[pos];
if old_tile != Tile::default() {
vram.remove_tile(old_tile.into());
vram.remove_tile(old_tile.tile_index(colours));
}
let tile_index = tile_setting.index();
@ -254,7 +255,7 @@ pub struct AffineMap {
transform: AffineMatrixBackground,
tiles: Vec<u8>,
tiles: Vec<Tile>,
tiles_dirty: bool,
}
@ -263,10 +264,9 @@ impl TiledMapTypes for AffineMap {
}
impl TiledMapPrivate for AffineMap {
type TileType = u8;
type AffineMatrix = AffineMatrixBackground;
fn tiles_mut(&mut self) -> &mut [Self::TileType] {
fn tiles_mut(&mut self) -> &mut [Tile] {
&mut self.tiles
}
fn tiles_dirty(&mut self) -> &mut bool {
@ -320,19 +320,20 @@ impl AffineMap {
tile_id: u8,
) {
let pos = self.map_size().gba_offset(pos);
let colours = self.colours();
let old_tile = self.tiles_mut()[pos];
if old_tile != 0 {
vram.remove_tile(old_tile.into());
if old_tile != Tile::default() {
vram.remove_tile(old_tile.tile_index(colours));
}
let tile_index = tile_id as u16;
let new_tile = if tile_index != TRANSPARENT_TILE_INDEX {
let new_tile_idx = vram.add_tile(tileset, tile_index);
new_tile_idx.raw_index() as u8
Tile::new(new_tile_idx, TileSetting(0))
} else {
0
Tile::default()
};
if old_tile == new_tile {

View file

@ -156,8 +156,8 @@ impl Tile {
Self(idx.raw_index() | setting.setting())
}
fn tile_index(self) -> TileIndex {
TileIndex::new(self.0 as usize & ((1 << 10) - 1), TileFormat::FourBpp)
fn tile_index(self, format: TileFormat) -> TileIndex {
TileIndex::new(self.0 as usize & ((1 << 10) - 1), format)
}
}
@ -165,6 +165,8 @@ impl Tile {
pub struct TileSetting(u16);
impl TileSetting {
pub const BLANK: Self = TileSetting::new(1023, false, false, 0);
#[must_use]
pub const fn new(tile_id: u16, hflip: bool, vflip: bool, palette_id: u8) -> Self {
Self(
@ -180,6 +182,16 @@ impl TileSetting {
Self(raw)
}
#[must_use]
pub const fn hflip(self, should_flip: bool) -> Self {
Self(self.0 ^ ((should_flip as u16) << 10))
}
#[must_use]
pub const fn vflip(self, should_flip: bool) -> Self {
Self(self.0 ^ ((should_flip as u16) << 11))
}
fn index(self) -> u16 {
self.0 & ((1 << 10) - 1)
}

View file

@ -2,7 +2,6 @@ use core::{alloc::Layout, ptr::NonNull};
use alloc::{slice, vec::Vec};
use crate::display::tiled::Tile;
use crate::{
agb_alloc::{block_allocator::BlockAllocator, bump_allocator::StartEnd},
display::palette16,
@ -66,21 +65,21 @@ impl<'a> TileSet<'a> {
#[derive(Debug, Clone, Copy)]
pub enum TileIndex {
FourBpp(u16),
EightBpp(u8),
EightBpp(u16),
}
impl TileIndex {
pub(crate) const fn new(index: usize, format: TileFormat) -> Self {
match format {
TileFormat::FourBpp => Self::FourBpp(index as u16),
TileFormat::EightBpp => Self::EightBpp(index as u8),
TileFormat::EightBpp => Self::EightBpp(index as u16),
}
}
pub(crate) const fn raw_index(self) -> u16 {
match self {
TileIndex::FourBpp(x) => x,
TileIndex::EightBpp(x) => x as u16,
TileIndex::EightBpp(x) => x,
}
}
@ -99,18 +98,6 @@ impl TileIndex {
}
}
impl From<Tile> for TileIndex {
fn from(tile: Tile) -> Self {
tile.tile_index()
}
}
impl From<u8> for TileIndex {
fn from(index: u8) -> TileIndex {
TileIndex::new(usize::from(index), TileFormat::EightBpp)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct TileReference(NonNull<u32>);
@ -302,7 +289,7 @@ impl VRamManager {
let new_reference: NonNull<u32> =
unsafe { TILE_ALLOCATOR.alloc(layout_of(tile_set.format)) }
.unwrap()
.expect("Ran out of video RAM for tiles")
.cast();
let tile_reference = TileReference(new_reference);
reference.or_insert(tile_reference);

View file

@ -33,7 +33,7 @@
//!
//! To get started with agb, you should clone the [template repo](https://github.com/agbrs/template) and work from there.
/// This macro is used to convert a png or bmp into a format usable by the Game Boy Advance.
/// This macro is used to convert a png, bmp or aseprite file into a format usable by the Game Boy Advance.
///
/// Suppose you have a file in `examples/water_tiles.png` which contains some tiles you'd like to use.
///
@ -89,7 +89,7 @@
/// &mut vram,
/// (x, y).into(),
/// &tileset,
/// TileSetting::new(0, false, false, 0),
/// water_tiles::tiles.tile_settings[0],
/// );
/// }
/// }

View file

@ -52,7 +52,7 @@ dependencies = [
"image",
"proc-macro2",
"quote",
"syn",
"syn 2.0.28",
]
[[package]]
@ -61,7 +61,7 @@ version = "0.16.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.28",
]
[[package]]
@ -71,7 +71,47 @@ dependencies = [
"hound",
"proc-macro2",
"quote",
"syn",
"syn 2.0.28",
]
[[package]]
name = "agb_tracker"
version = "0.16.0"
dependencies = [
"agb",
"agb_tracker_interop",
"agb_xm",
]
[[package]]
name = "agb_tracker_interop"
version = "0.16.0"
dependencies = [
"agb_fixnum",
"proc-macro2",
"quote",
]
[[package]]
name = "agb_xm"
version = "0.16.0"
dependencies = [
"agb_xm_core",
"proc-macro-error",
"proc-macro2",
]
[[package]]
name = "agb_xm_core"
version = "0.16.0"
dependencies = [
"agb_fixnum",
"agb_tracker_interop",
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.28",
"xmrs",
]
[[package]]
@ -133,6 +173,12 @@ dependencies = [
"byteorder",
]
[[package]]
name = "base64"
version = "0.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53"
[[package]]
name = "bilge"
version = "0.2.0"
@ -153,7 +199,16 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
"syn 2.0.28",
]
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
@ -199,6 +254,7 @@ dependencies = [
"agb",
"amplitude",
"hyperspace-roll",
"the-dungeon-puzzlers-lament",
"the-hat-chooses-the-wizard",
"the-purple-night",
]
@ -228,6 +284,12 @@ version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "flate2"
version = "1.0.26"
@ -244,7 +306,7 @@ version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0793f5137567643cf65ea42043a538804ff0fbf288649e2141442b602d81f9bc"
dependencies = [
"hashbrown",
"hashbrown 0.13.2",
"ttf-parser",
]
@ -257,6 +319,17 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "getrandom"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "hashbrown"
version = "0.13.2"
@ -266,6 +339,12 @@ dependencies = [
"ahash",
]
[[package]]
name = "hashbrown"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
[[package]]
name = "hound"
version = "3.5.0"
@ -294,6 +373,16 @@ dependencies = [
"png",
]
[[package]]
name = "indexmap"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
dependencies = [
"equivalent",
"hashbrown 0.14.0",
]
[[package]]
name = "itertools"
version = "0.11.0"
@ -309,6 +398,12 @@ version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "libc"
version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "libflate"
version = "0.1.27"
@ -321,12 +416,38 @@ dependencies = [
"take_mut",
]
[[package]]
name = "libflate"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ff4ae71b685bbad2f2f391fe74f6b7659a34871c08b210fdc039e43bee07d18"
dependencies = [
"adler32",
"crc32fast",
"libflate_lz77",
]
[[package]]
name = "libflate_lz77"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a52d3a8bfc85f250440e4424db7d857e241a3aebbbe301f3eb606ab15c39acbf"
dependencies = [
"rle-decode-fast",
]
[[package]]
name = "log"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "memchr"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f478948fd84d9f8e86967bf432640e46adfb5a4bd4f14ef7e864ab38220534ae"
[[package]]
name = "miniz_oxide"
version = "0.3.7"
@ -392,6 +513,27 @@ dependencies = [
"autocfg",
]
[[package]]
name = "num_enum"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1"
dependencies = [
"num_enum_derive",
]
[[package]]
name = "num_enum_derive"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.28",
]
[[package]]
name = "once_cell"
version = "1.18.0"
@ -410,6 +552,22 @@ dependencies = [
"miniz_oxide 0.3.7",
]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro-crate"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
dependencies = [
"once_cell",
"toml_edit",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
@ -419,6 +577,7 @@ dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn 1.0.109",
"version_check",
]
@ -451,6 +610,36 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "rle-decode-fast"
version = "1.0.3"
@ -478,6 +667,15 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "serde-big-array"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f"
dependencies = [
"serde",
]
[[package]]
name = "serde_derive"
version = "1.0.183"
@ -486,7 +684,7 @@ checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.28",
]
[[package]]
@ -500,6 +698,25 @@ dependencies = [
"serde",
]
[[package]]
name = "slotmap"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342"
dependencies = [
"version_check",
]
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.28"
@ -517,6 +734,18 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60"
[[package]]
name = "the-dungeon-puzzlers-lament"
version = "0.1.0"
dependencies = [
"agb",
"agb_tracker",
"proc-macro2",
"quote",
"slotmap",
"tiled 0.11.1",
]
[[package]]
name = "the-hat-chooses-the-wizard"
version = "0.1.0"
@ -533,7 +762,7 @@ dependencies = [
"agb",
"generational-arena",
"quote",
"tiled",
"tiled 0.9.4",
]
[[package]]
@ -542,11 +771,39 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d2c30aeea9d8159cb461a17dba23ad28980a2a9c217a6784a14e931e4979d6f"
dependencies = [
"base64",
"libflate",
"base64 0.10.1",
"libflate 0.1.27",
"xml-rs",
]
[[package]]
name = "tiled"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "181e2402be287d74e951a8e81c8798d0737cc94b1a089237bb3b838be76c6b5b"
dependencies = [
"base64 0.21.3",
"libflate 1.4.0",
"xml-rs",
]
[[package]]
name = "toml_datetime"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
[[package]]
name = "toml_edit"
version = "0.19.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a"
dependencies = [
"indexmap",
"toml_datetime",
"winnow",
]
[[package]]
name = "ttf-parser"
version = "0.15.2"
@ -565,8 +822,37 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winnow"
version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc"
dependencies = [
"memchr",
]
[[package]]
name = "xml-rs"
version = "0.8.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47430998a7b5d499ccee752b41567bc3afc57e1327dc855b1a2aa44ce29b5fa1"
[[package]]
name = "xmrs"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fa1ec7c01e6bb4c716f84a418f4ced5f4a735b2ae6364f4bb5850da61321d16"
dependencies = [
"bincode",
"libflate 1.4.0",
"num_enum",
"rand",
"serde",
"serde-big-array",
]

View file

@ -11,6 +11,7 @@ the-purple-night = { path = "../the-purple-night" }
the-hat-chooses-the-wizard = { path = "../the-hat-chooses-the-wizard" }
hyperspace-roll = { path = "../hyperspace-roll" }
amplitude = { path = "../amplitude" }
the-dungeon-puzzlers-lament = { path = "../the-dungeon-puzzlers-lament" }
[profile.dev]
opt-level = 3

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View file

@ -8,7 +8,7 @@ use alloc::boxed::Box;
use agb::{
display::{
tiled::{InfiniteScrolledMap, RegularBackgroundSize, TileFormat, TileSet, TileSetting},
tiled::{InfiniteScrolledMap, RegularBackgroundSize, TileFormat, TileSet},
Priority,
},
fixnum::{Num, Vector2D},
@ -21,6 +21,7 @@ pub enum Game {
TheHatChoosesTheWizard,
ThePurpleNight,
HyperspaceRoll,
TheDungeonPuzzlersLament,
Amplitude,
}
@ -30,6 +31,7 @@ impl Game {
Game::TheHatChoosesTheWizard => the_hat_chooses_the_wizard::main(gba),
Game::ThePurpleNight => the_purple_night::main(gba),
Game::HyperspaceRoll => hyperspace_roll::main(gba),
Game::TheDungeonPuzzlersLament => the_dungeon_puzzlers_lament::entry(gba),
Game::Amplitude => amplitude::main(gba),
}
}
@ -39,7 +41,8 @@ impl Game {
0 => Game::TheHatChoosesTheWizard,
1 => Game::ThePurpleNight,
2 => Game::HyperspaceRoll,
3 => Game::Amplitude,
3 => Game::TheDungeonPuzzlersLament,
4 => Game::Amplitude,
_ => unreachable!("game out of index in an unreachable manner"),
}
}
@ -47,10 +50,11 @@ impl Game {
include_background_gfx!(
games, "121105",
hat => "gfx/hat.png",
purple => "gfx/purple.png",
hyperspace => "gfx/hyperspace.png",
amplitude => "gfx/amplitude.png"
hat => 256 deduplicate "gfx/hat.png",
purple => 256 deduplicate "gfx/purple.png",
hyperspace => 256 deduplicate "gfx/hyperspace.png",
dungeon_puzzler => 256 deduplicate "gfx/dungeon_puzzler.png",
amplitude => 256 deduplicate "gfx/amplitude.png",
);
fn get_game(gba: &mut agb::Gba) -> Game {
@ -59,18 +63,20 @@ fn get_game(gba: &mut agb::Gba) -> Game {
let (tile, mut vram) = gba.display.video.tiled0();
let hat = TileSet::new(games::hat.tiles, TileFormat::FourBpp);
let purple = TileSet::new(games::purple.tiles, TileFormat::FourBpp);
let hyperspace = TileSet::new(games::hyperspace.tiles, TileFormat::FourBpp);
let amplitude = TileSet::new(games::amplitude.tiles, TileFormat::FourBpp);
let hat = TileSet::new(games::hat.tiles, TileFormat::EightBpp);
let purple = TileSet::new(games::purple.tiles, TileFormat::EightBpp);
let hyperspace = TileSet::new(games::hyperspace.tiles, TileFormat::EightBpp);
let dungeon_puzzler = TileSet::new(games::dungeon_puzzler.tiles, TileFormat::EightBpp);
let amplitude = TileSet::new(games::amplitude.tiles, TileFormat::EightBpp);
let tiles = [hat, purple, hyperspace, amplitude];
let tiles = [hat, purple, hyperspace, dungeon_puzzler, amplitude];
let palette_assignments = &[
games::hat.palette_assignments,
games::purple.palette_assignments,
games::hyperspace.palette_assignments,
games::amplitude.palette_assignments,
let tile_settings = &[
games::hat.tile_settings,
games::purple.tile_settings,
games::hyperspace.tile_settings,
games::dungeon_puzzler.tile_settings,
games::amplitude.tile_settings,
];
vram.set_background_palettes(games::PALETTES);
@ -79,7 +85,7 @@ fn get_game(gba: &mut agb::Gba) -> Game {
tile.background(
Priority::P0,
RegularBackgroundSize::Background32x32,
TileFormat::FourBpp,
TileFormat::EightBpp,
),
Box::new(|pos| {
let y = pos.y.rem_euclid(20);
@ -87,15 +93,7 @@ fn get_game(gba: &mut agb::Gba) -> Game {
let game = (pos.x).rem_euclid(tiles.len() as i32 * 30) as usize / 30;
let tile_id = (y * 30 + x) as usize;
(
&tiles[game],
TileSetting::new(
tile_id as u16,
false,
false,
palette_assignments[game][tile_id],
),
)
(&tiles[game], tile_settings[game][tile_id])
}),
);

View file

@ -6,11 +6,11 @@ use agb::{
use crate::sfx::Sfx;
include_background_gfx!(backgrounds, "121105",
stars => "gfx/stars.aseprite",
title => "gfx/title-screen.aseprite",
help => "gfx/help-text.aseprite",
descriptions1 => "gfx/descriptions1.png",
descriptions2 => "gfx/descriptions2.png",
stars => deduplicate "gfx/stars.aseprite",
title => deduplicate "gfx/title-screen.aseprite",
help => deduplicate "gfx/help-text.aseprite",
descriptions1 => deduplicate "gfx/descriptions1.png",
descriptions2 => deduplicate "gfx/descriptions2.png",
);
pub fn load_palettes(vram: &mut VRamManager) {
@ -35,12 +35,7 @@ pub(crate) fn load_help_text(
vram,
(x + at_tile.0, at_tile.1).into(),
&help_tileset,
TileSetting::new(
tile_id,
false,
false,
backgrounds::help.palette_assignments[tile_id as usize],
),
backgrounds::help.tile_settings[tile_id as usize],
)
}
}
@ -50,13 +45,13 @@ pub(crate) fn load_description(
descriptions_map: &mut RegularMap,
vram: &mut VRamManager,
) {
let (tileset, palette_assignments) = if face_id < 10 {
let (tileset, tile_settings) = if face_id < 10 {
(
TileSet::new(
backgrounds::descriptions1.tiles,
agb::display::tiled::TileFormat::FourBpp,
),
backgrounds::descriptions1.palette_assignments,
backgrounds::descriptions1.tile_settings,
)
} else {
(
@ -64,7 +59,7 @@ pub(crate) fn load_description(
backgrounds::descriptions2.tiles,
agb::display::tiled::TileFormat::FourBpp,
),
backgrounds::descriptions2.palette_assignments,
backgrounds::descriptions2.tile_settings,
)
};
@ -75,7 +70,7 @@ pub(crate) fn load_description(
vram,
(x, y).into(),
&tileset,
TileSetting::new(tile_id, false, false, palette_assignments[tile_id as usize]),
tile_settings[tile_id as usize],
)
}
}
@ -87,16 +82,12 @@ fn create_background_map(map: &mut RegularMap, vram: &mut VRamManager, stars_til
for y in 0..32u16 {
let blank = rng::gen().rem_euclid(32) < 30;
let (tile_id, palette_id) = if blank {
((1 << 10) - 1, 0)
let tile_setting = if blank {
TileSetting::new((1 << 10) - 1, false, false, 0)
} else {
let tile_id = rng::gen().rem_euclid(64) as u16;
(
tile_id,
backgrounds::stars.palette_assignments[tile_id as usize],
)
backgrounds::stars.tile_settings[tile_id as usize]
};
let tile_setting = TileSetting::new(tile_id, false, false, palette_id);
map.set_tile(vram, (x, y).into(), stars_tileset, tile_setting);
}
@ -121,12 +112,7 @@ pub fn show_title_screen(background: &mut RegularMap, vram: &mut VRamManager, sf
vram,
(x, y).into(),
&tile_set,
TileSetting::new(
tile_id,
false,
false,
backgrounds::title.palette_assignments[tile_id as usize],
),
backgrounds::title.tile_settings[tile_id as usize],
);
}

View file

@ -331,12 +331,10 @@ fn export_tiles(map: &tiled::Map, background: TokenStream) -> TokenStream {
tile_tileset_x * 2 + x_offset + tile_tileset_y * 9 * 4 + y_offset * 9 * 2;
let gba_tile_id = gba_tile_id as u16;
let palette_id =
quote! { backgrounds::#background.palette_assignments[#gba_tile_id as usize] };
quote! { TileSetting::new(#gba_tile_id, #hflip, #vflip, #palette_id) }
quote! { backgrounds::#background.tile_settings[#gba_tile_id as usize].hflip(#hflip).vflip(#vflip) }
}
None => {
quote! { TileSetting::new(1023, false, false, 0) }
quote! { TileSetting::BLANK }
}
}
});
@ -361,12 +359,11 @@ fn export_ui_tiles(map: &tiled::Map, background: TokenStream) -> TokenStream {
let tile_id = tile.id() as u16;
let vflip = tile.flip_v;
let hflip = tile.flip_h;
let palette_id =
quote! { backgrounds::#background.palette_assignments[#tile_id as usize] };
quote! { TileSetting::new(#tile_id, #hflip, #vflip, #palette_id) }
quote! { backgrounds::#background.tile_settings[#tile_id as usize].hflip(#hflip).vflip(#vflip) }
}
None => {
quote! { TileSetting::new(1023, false, false, 0) }
quote! { TileSetting::BLANK }
}
}
});

View file

@ -1,12 +1,12 @@
use agb::{
display::tiled::{RegularMap, TileFormat, TileSet, TileSetting, VRamManager},
display::tiled::{RegularMap, TileFormat, TileSet, VRamManager},
include_background_gfx,
};
include_background_gfx!(backgrounds, "1e151b",
ui => "maps/ui_tiles.png",
level => "maps/level.png",
ending => "gfx/ending_page.aseprite",
ui => deduplicate "maps/ui_tiles.png",
level => deduplicate "maps/level.png",
ending => deduplicate "gfx/ending_page.aseprite",
);
mod tilemaps {
@ -56,13 +56,13 @@ pub fn load_ending_page(map: &mut RegularMap, vram_manager: &mut VRamManager) {
for y in 0..20u16 {
for x in 0..30u16 {
let tile_pos = y * 30 + x;
let tile_setting = TileSetting::new(
tile_pos,
false,
false,
backgrounds::ending.palette_assignments[tile_pos as usize],
map.set_tile(
vram_manager,
(x, y).into(),
&ending_tileset,
backgrounds::ending.tile_settings[tile_pos as usize],
);
map.set_tile(vram_manager, (x, y).into(), &ending_tileset, tile_setting);
}
}
}

View file

@ -3,10 +3,10 @@ use agb::display::{
HEIGHT, WIDTH,
};
const LEVEL_START: u16 = 12 * 28;
const NUMBERS_START: u16 = 12 * 28 + 3;
const HYPHEN: u16 = 12 * 28 + 11;
pub const BLANK: u16 = 11 * 28;
const LEVEL_START: usize = 12 * 28;
const NUMBERS_START: usize = 12 * 28 + 3;
const HYPHEN: usize = 12 * 28 + 11;
pub const BLANK: usize = 11 * 28;
pub fn write_level(
map: &mut RegularMap,
@ -14,25 +14,21 @@ pub fn write_level(
level: u32,
tileset: &'_ TileSet<'_>,
vram: &mut VRamManager,
tile_settings: &[TileSetting],
) {
for (i, &tile) in [
LEVEL_START,
LEVEL_START + 1,
LEVEL_START + 2,
BLANK,
world as u16 + NUMBERS_START - 1,
world as usize + NUMBERS_START - 1,
HYPHEN,
level as u16 + NUMBERS_START - 1,
level as usize + NUMBERS_START - 1,
]
.iter()
.enumerate()
{
map.set_tile(
vram,
(i as u16, 0).into(),
tileset,
TileSetting::from_raw(tile),
);
map.set_tile(vram, (i as u16, 0).into(), tileset, tile_settings[tile]);
}
map.set_scroll_pos((-(WIDTH / 2 - 7 * 8 / 2) as i16, -(HEIGHT / 2 - 4) as i16).into());

View file

@ -11,7 +11,7 @@ use agb::{
object::{Graphics, OamManaged, Object, Tag, TagMap},
tiled::{
InfiniteScrolledMap, PartialUpdateStatus, RegularBackgroundSize, TileFormat, TileSet,
TileSetting, TiledMap, VRamManager,
TiledMap, VRamManager,
},
Priority, HEIGHT, WIDTH,
},
@ -101,7 +101,7 @@ mod map_tiles {
}
}
agb::include_background_gfx!(tile_sheet, "2ce8f4", background => "gfx/tile_sheet.png");
agb::include_background_gfx!(tile_sheet, "2ce8f4", background => deduplicate "gfx/tile_sheet.png");
const GRAPHICS: &Graphics = agb::include_aseprite!("gfx/sprites.aseprite");
const TAG_MAP: &TagMap = GRAPHICS.tags();
@ -801,7 +801,7 @@ pub fn main(mut agb: agb::Gba) -> ! {
&mut vram,
(x, y).into(),
&tileset,
TileSetting::from_raw(level_display::BLANK),
tile_sheet::background.tile_settings[level_display::BLANK],
);
}
}
@ -846,6 +846,7 @@ pub fn main(mut agb: agb::Gba) -> ! {
current_level % 8 + 1,
&tileset,
&mut vram,
tile_sheet::background.tile_settings,
);
world_display.commit(&mut vram);
@ -865,12 +866,11 @@ pub fn main(mut agb: agb::Gba) -> ! {
let level = &map_tiles::LEVELS[map_current_level as usize];
(
&tileset,
TileSetting::from_raw(
*level
.background
.get((pos.y * level.dimensions.x as i32 + pos.x) as usize)
.unwrap_or(&0),
),
tile_sheet::background.tile_settings[*level
.background
.get((pos.y * level.dimensions.x as i32 + pos.x) as usize)
.unwrap_or(&0)
as usize],
)
}),
);
@ -884,12 +884,11 @@ pub fn main(mut agb: agb::Gba) -> ! {
let level = &map_tiles::LEVELS[map_current_level as usize];
(
&tileset,
TileSetting::from_raw(
*level
.foreground
.get((pos.y * level.dimensions.x as i32 + pos.x) as usize)
.unwrap_or(&0),
),
tile_sheet::background.tile_settings[*level
.foreground
.get((pos.y * level.dimensions.x as i32 + pos.x) as usize)
.unwrap_or(&0)
as usize],
)
}),
);

View file

@ -1,9 +1,9 @@
use super::sfx::SfxPlayer;
use agb::display::tiled::{RegularMap, TileFormat, TileSet, TileSetting, TiledMap, VRamManager};
use agb::display::tiled::{RegularMap, TileFormat, TileSet, TiledMap, VRamManager};
agb::include_background_gfx!(splash_screens,
splash => "gfx/splash.png",
thanks_for_playing => "gfx/thanks_for_playing.png",
splash => deduplicate "gfx/splash.png",
thanks_for_playing => deduplicate "gfx/thanks_for_playing.png",
);
pub enum SplashScreen {
@ -18,12 +18,18 @@ pub fn show_splash_screen(
vram: &mut VRamManager,
) {
map.set_scroll_pos((0i16, 0i16).into());
let tileset = match which {
SplashScreen::Start => TileSet::new(splash_screens::splash.tiles, TileFormat::FourBpp),
let (tileset, settings) = match which {
SplashScreen::Start => (
TileSet::new(splash_screens::splash.tiles, TileFormat::FourBpp),
splash_screens::splash.tile_settings,
),
SplashScreen::End => TileSet::new(
splash_screens::thanks_for_playing.tiles,
TileFormat::FourBpp,
SplashScreen::End => (
TileSet::new(
splash_screens::thanks_for_playing.tiles,
TileFormat::FourBpp,
),
splash_screens::thanks_for_playing.tile_settings,
),
};
@ -40,7 +46,7 @@ pub fn show_splash_screen(
vram,
(x, y).into(),
&tileset,
TileSetting::from_raw(y * 30 + x),
settings[(y * 30 + x) as usize],
);
}

View file

@ -15,10 +15,7 @@ use alloc::{boxed::Box, vec::Vec};
use agb::{
display::{
object::{Graphics, OamManaged, Object, Sprite, Tag, TagMap},
tiled::{
InfiniteScrolledMap, RegularBackgroundSize, TileFormat, TileSet, TileSetting,
VRamManager,
},
tiled::{InfiniteScrolledMap, RegularBackgroundSize, TileFormat, TileSet, VRamManager},
Priority, HEIGHT, WIDTH,
},
fixnum::{num, FixedNum, Rect, Vector2D},
@ -57,7 +54,7 @@ const SWORDLESS_JUMP: &Tag = TAG_MAP.get("jump swordless");
const SWORDLESS_ATTACK: &Tag = KNIFE_ATTACK;
const SWORDLESS_JUMP_ATTACK: &Tag = KNIFE_JUMP_ATTACK;
agb::include_background_gfx!(background, "53269a", background => "gfx/background.aseprite");
agb::include_background_gfx!(background, "53269a", background => deduplicate "gfx/background.aseprite");
type Number = FixedNum<8>;
@ -2207,11 +2204,10 @@ fn game_with_level(gba: &mut agb::Gba) {
Box::new(|pos| {
(
&tileset,
TileSetting::from_raw(
*tilemap::BACKGROUND_MAP
.get((pos.x + tilemap::WIDTH * pos.y) as usize)
.unwrap_or(&0),
),
background::background.tile_settings[*tilemap::BACKGROUND_MAP
.get((pos.x + tilemap::WIDTH * pos.y) as usize)
.unwrap_or(&0)
as usize],
)
}),
);
@ -2225,11 +2221,10 @@ fn game_with_level(gba: &mut agb::Gba) {
Box::new(|pos| {
(
&tileset,
TileSetting::from_raw(
*tilemap::FOREGROUND_MAP
.get((pos.x + tilemap::WIDTH * pos.y) as usize)
.unwrap_or(&0),
),
background::background.tile_settings[*tilemap::FOREGROUND_MAP
.get((pos.x + tilemap::WIDTH * pos.y) as usize)
.unwrap_or(&0)
as usize],
)
}),
);
@ -2243,11 +2238,10 @@ fn game_with_level(gba: &mut agb::Gba) {
Box::new(|pos| {
(
&tileset,
TileSetting::from_raw(
*tilemap::CLOUD_MAP
.get((pos.x + tilemap::WIDTH * pos.y) as usize)
.unwrap_or(&0),
),
background::background.tile_settings[*tilemap::CLOUD_MAP
.get((pos.x + tilemap::WIDTH * pos.y) as usize)
.unwrap_or(&0)
as usize],
)
}),
);