dev/render-all-scene-cache-and-camera-integration #16
@ -14,7 +14,7 @@ use prometeu_hal::glyph::Glyph;
|
||||
use prometeu_hal::glyph_bank::{GlyphBank, TileSize};
|
||||
use prometeu_hal::sample::Sample;
|
||||
use prometeu_hal::scene_bank::SceneBank;
|
||||
use prometeu_hal::scene_layer::{MotionFactor, SceneLayer};
|
||||
use prometeu_hal::scene_layer::{ParallaxFactor, SceneLayer};
|
||||
use prometeu_hal::sound_bank::SoundBank;
|
||||
use prometeu_hal::tile::Tile;
|
||||
use prometeu_hal::tilemap::TileMap;
|
||||
@ -748,7 +748,7 @@ impl AssetManager {
|
||||
active: false,
|
||||
glyph_bank_id: 0,
|
||||
tile_size: TileSize::Size8,
|
||||
motion_factor: MotionFactor { x: 1.0, y: 1.0 },
|
||||
parallax_factor: ParallaxFactor { x: 1.0, y: 1.0 },
|
||||
tilemap: TileMap { width: 0, height: 0, tiles: Vec::new() },
|
||||
});
|
||||
let mut layers = layers;
|
||||
@ -770,20 +770,20 @@ impl AssetManager {
|
||||
32 => TileSize::Size32,
|
||||
other => return Err(format!("Invalid SCENE tile size: {}", other)),
|
||||
};
|
||||
let motion_factor_x = f32::from_le_bytes([
|
||||
let parallax_factor_x = f32::from_le_bytes([
|
||||
buffer[offset + 4],
|
||||
buffer[offset + 5],
|
||||
buffer[offset + 6],
|
||||
buffer[offset + 7],
|
||||
]);
|
||||
let motion_factor_y = f32::from_le_bytes([
|
||||
let parallax_factor_y = f32::from_le_bytes([
|
||||
buffer[offset + 8],
|
||||
buffer[offset + 9],
|
||||
buffer[offset + 10],
|
||||
buffer[offset + 11],
|
||||
]);
|
||||
if !motion_factor_x.is_finite() || !motion_factor_y.is_finite() {
|
||||
return Err("Invalid SCENE motion_factor".to_string());
|
||||
if !parallax_factor_x.is_finite() || !parallax_factor_y.is_finite() {
|
||||
return Err("Invalid SCENE parallax_factor".to_string());
|
||||
}
|
||||
|
||||
let width = u32::from_le_bytes([
|
||||
@ -847,7 +847,7 @@ impl AssetManager {
|
||||
active: (flags & 0b0000_0001) != 0,
|
||||
glyph_bank_id,
|
||||
tile_size,
|
||||
motion_factor: MotionFactor { x: motion_factor_x, y: motion_factor_y },
|
||||
parallax_factor: ParallaxFactor { x: parallax_factor_x, y: parallax_factor_y },
|
||||
tilemap: TileMap { width, height, tiles },
|
||||
};
|
||||
}
|
||||
@ -1105,7 +1105,7 @@ mod tests {
|
||||
SCENE_PAYLOAD_MAGIC_V1, SCENE_PAYLOAD_VERSION_V1,
|
||||
};
|
||||
use prometeu_hal::glyph::Glyph;
|
||||
use prometeu_hal::scene_layer::{MotionFactor, SceneLayer};
|
||||
use prometeu_hal::scene_layer::{ParallaxFactor, SceneLayer};
|
||||
use prometeu_hal::tile::Tile;
|
||||
use prometeu_hal::tilemap::TileMap;
|
||||
|
||||
@ -1144,11 +1144,11 @@ mod tests {
|
||||
|
||||
fn test_scene() -> SceneBank {
|
||||
let make_layer =
|
||||
|glyph_bank_id: u8, motion_x: f32, motion_y: f32, tile_size: TileSize| SceneLayer {
|
||||
|glyph_bank_id: u8, parallax_x: f32, parallax_y: f32, tile_size: TileSize| SceneLayer {
|
||||
active: glyph_bank_id != 3,
|
||||
glyph_bank_id,
|
||||
tile_size,
|
||||
motion_factor: MotionFactor { x: motion_x, y: motion_y },
|
||||
parallax_factor: ParallaxFactor { x: parallax_x, y: parallax_y },
|
||||
tilemap: TileMap {
|
||||
width: 2,
|
||||
height: 2,
|
||||
@ -1227,8 +1227,8 @@ mod tests {
|
||||
data.push(layer.glyph_bank_id);
|
||||
data.push(layer.tile_size as u8);
|
||||
data.push(0);
|
||||
data.extend_from_slice(&layer.motion_factor.x.to_le_bytes());
|
||||
data.extend_from_slice(&layer.motion_factor.y.to_le_bytes());
|
||||
data.extend_from_slice(&layer.parallax_factor.x.to_le_bytes());
|
||||
data.extend_from_slice(&layer.parallax_factor.y.to_le_bytes());
|
||||
data.extend_from_slice(&(layer.tilemap.width as u32).to_le_bytes());
|
||||
data.extend_from_slice(&(layer.tilemap.height as u32).to_le_bytes());
|
||||
data.extend_from_slice(&(layer.tilemap.tiles.len() as u32).to_le_bytes());
|
||||
@ -1359,7 +1359,7 @@ mod tests {
|
||||
let decoded = AssetManager::decode_scene_bank_from_buffer(&entry, &data).expect("scene");
|
||||
|
||||
assert_eq!(decoded.layers[1].glyph_bank_id, 1);
|
||||
assert_eq!(decoded.layers[1].motion_factor.x, 0.5);
|
||||
assert_eq!(decoded.layers[1].parallax_factor.x, 0.5);
|
||||
assert_eq!(decoded.layers[2].tile_size, TileSize::Size32);
|
||||
assert_eq!(decoded.layers[0].tilemap.tiles[1].flip_x, true);
|
||||
assert_eq!(decoded.layers[2].tilemap.tiles[2].flip_y, true);
|
||||
|
||||
197
crates/console/prometeu-drivers/src/frame_composer.rs
Normal file
197
crates/console/prometeu-drivers/src/frame_composer.rs
Normal file
@ -0,0 +1,197 @@
|
||||
use crate::memory_banks::SceneBankPoolAccess;
|
||||
use prometeu_hal::glyph::Glyph;
|
||||
use prometeu_hal::scene_bank::SceneBank;
|
||||
use prometeu_hal::scene_viewport_cache::SceneViewportCache;
|
||||
use prometeu_hal::scene_viewport_resolver::SceneViewportResolver;
|
||||
use prometeu_hal::sprite::Sprite;
|
||||
use std::sync::Arc;
|
||||
|
||||
const EMPTY_SPRITE: Sprite = Sprite {
|
||||
glyph: Glyph { glyph_id: 0, palette_id: 0 },
|
||||
x: 0,
|
||||
y: 0,
|
||||
bank_id: 0,
|
||||
active: false,
|
||||
flip_x: false,
|
||||
flip_y: false,
|
||||
priority: 0,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
pub enum SceneStatus {
|
||||
#[default]
|
||||
Unbound,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SpriteController {
|
||||
sprites: [Sprite; 512],
|
||||
}
|
||||
|
||||
impl Default for SpriteController {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl SpriteController {
|
||||
pub fn new() -> Self {
|
||||
Self { sprites: [EMPTY_SPRITE; 512] }
|
||||
}
|
||||
|
||||
pub fn sprites(&self) -> &[Sprite; 512] {
|
||||
&self.sprites
|
||||
}
|
||||
|
||||
pub fn sprites_mut(&mut self) -> &mut [Sprite; 512] {
|
||||
&mut self.sprites
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FrameComposer {
|
||||
scene_bank_pool: Arc<dyn SceneBankPoolAccess>,
|
||||
viewport_width_px: usize,
|
||||
viewport_height_px: usize,
|
||||
active_scene_id: Option<usize>,
|
||||
active_scene: Option<Arc<SceneBank>>,
|
||||
scene_status: SceneStatus,
|
||||
camera_x_px: i32,
|
||||
camera_y_px: i32,
|
||||
cache: Option<SceneViewportCache>,
|
||||
resolver: Option<SceneViewportResolver>,
|
||||
sprite_controller: SpriteController,
|
||||
}
|
||||
|
||||
impl FrameComposer {
|
||||
pub fn new(
|
||||
viewport_width_px: usize,
|
||||
viewport_height_px: usize,
|
||||
scene_bank_pool: Arc<dyn SceneBankPoolAccess>,
|
||||
) -> Self {
|
||||
Self {
|
||||
scene_bank_pool,
|
||||
viewport_width_px,
|
||||
viewport_height_px,
|
||||
active_scene_id: None,
|
||||
active_scene: None,
|
||||
scene_status: SceneStatus::Unbound,
|
||||
camera_x_px: 0,
|
||||
camera_y_px: 0,
|
||||
cache: None,
|
||||
resolver: None,
|
||||
sprite_controller: SpriteController::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn viewport_size(&self) -> (usize, usize) {
|
||||
(self.viewport_width_px, self.viewport_height_px)
|
||||
}
|
||||
|
||||
pub fn scene_bank_pool(&self) -> &Arc<dyn SceneBankPoolAccess> {
|
||||
&self.scene_bank_pool
|
||||
}
|
||||
|
||||
pub fn scene_bank_slot(&self, slot: usize) -> Option<Arc<SceneBank>> {
|
||||
self.scene_bank_pool.scene_bank_slot(slot)
|
||||
}
|
||||
|
||||
pub fn scene_bank_slot_count(&self) -> usize {
|
||||
self.scene_bank_pool.scene_bank_slot_count()
|
||||
}
|
||||
|
||||
pub fn active_scene_id(&self) -> Option<usize> {
|
||||
self.active_scene_id
|
||||
}
|
||||
|
||||
pub fn active_scene(&self) -> Option<&Arc<SceneBank>> {
|
||||
self.active_scene.as_ref()
|
||||
}
|
||||
|
||||
pub fn scene_status(&self) -> SceneStatus {
|
||||
self.scene_status
|
||||
}
|
||||
|
||||
pub fn camera(&self) -> (i32, i32) {
|
||||
(self.camera_x_px, self.camera_y_px)
|
||||
}
|
||||
|
||||
pub fn cache(&self) -> Option<&SceneViewportCache> {
|
||||
self.cache.as_ref()
|
||||
}
|
||||
|
||||
pub fn resolver(&self) -> Option<&SceneViewportResolver> {
|
||||
self.resolver.as_ref()
|
||||
}
|
||||
|
||||
pub fn sprite_controller(&self) -> &SpriteController {
|
||||
&self.sprite_controller
|
||||
}
|
||||
|
||||
pub fn sprite_controller_mut(&mut self) -> &mut SpriteController {
|
||||
&mut self.sprite_controller
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::memory_banks::{MemoryBanks, SceneBankPoolInstaller};
|
||||
use prometeu_hal::glyph::Glyph;
|
||||
use prometeu_hal::glyph_bank::TileSize;
|
||||
use prometeu_hal::scene_layer::{ParallaxFactor, SceneLayer};
|
||||
use prometeu_hal::tile::Tile;
|
||||
use prometeu_hal::tilemap::TileMap;
|
||||
|
||||
fn make_scene() -> SceneBank {
|
||||
let layer = SceneLayer {
|
||||
active: true,
|
||||
glyph_bank_id: 1,
|
||||
tile_size: TileSize::Size8,
|
||||
parallax_factor: ParallaxFactor { x: 1.0, y: 0.5 },
|
||||
tilemap: TileMap {
|
||||
width: 2,
|
||||
height: 2,
|
||||
tiles: vec![
|
||||
Tile {
|
||||
active: true,
|
||||
glyph: Glyph { glyph_id: 9, palette_id: 1 },
|
||||
flip_x: false,
|
||||
flip_y: false,
|
||||
};
|
||||
4
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
SceneBank { layers: std::array::from_fn(|_| layer.clone()) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn frame_composer_starts_unbound_with_empty_owned_state() {
|
||||
let frame_composer = FrameComposer::new(320, 180, Arc::new(MemoryBanks::new()));
|
||||
|
||||
assert_eq!(frame_composer.viewport_size(), (320, 180));
|
||||
assert_eq!(frame_composer.active_scene_id(), None);
|
||||
assert!(frame_composer.active_scene().is_none());
|
||||
assert_eq!(frame_composer.scene_status(), SceneStatus::Unbound);
|
||||
assert_eq!(frame_composer.camera(), (0, 0));
|
||||
assert!(frame_composer.cache().is_none());
|
||||
assert!(frame_composer.resolver().is_none());
|
||||
assert_eq!(frame_composer.sprite_controller().sprites().len(), 512);
|
||||
assert!(frame_composer.sprite_controller().sprites().iter().all(|sprite| !sprite.active));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn frame_composer_exposes_shared_scene_bank_access() {
|
||||
let banks = Arc::new(MemoryBanks::new());
|
||||
banks.install_scene_bank(3, Arc::new(make_scene()));
|
||||
|
||||
let frame_composer = FrameComposer::new(320, 180, banks);
|
||||
let scene =
|
||||
frame_composer.scene_bank_slot(3).expect("scene bank slot 3 should be resident");
|
||||
|
||||
assert_eq!(frame_composer.scene_bank_slot_count(), 16);
|
||||
assert_eq!(scene.layers[0].tile_size, TileSize::Size8);
|
||||
assert_eq!(scene.layers[0].parallax_factor.y, 0.5);
|
||||
}
|
||||
}
|
||||
@ -822,7 +822,7 @@ mod tests {
|
||||
use crate::memory_banks::{GlyphBankPoolInstaller, MemoryBanks};
|
||||
use prometeu_hal::glyph_bank::TileSize;
|
||||
use prometeu_hal::scene_bank::SceneBank;
|
||||
use prometeu_hal::scene_layer::{MotionFactor, SceneLayer};
|
||||
use prometeu_hal::scene_layer::{ParallaxFactor, SceneLayer};
|
||||
use prometeu_hal::scene_viewport_cache::SceneViewportCache;
|
||||
use prometeu_hal::scene_viewport_resolver::SceneViewportResolver;
|
||||
use prometeu_hal::tile::Tile;
|
||||
@ -853,7 +853,7 @@ mod tests {
|
||||
active: true,
|
||||
glyph_bank_id,
|
||||
tile_size: TileSize::Size8,
|
||||
motion_factor: MotionFactor { x: 1.0, y: 1.0 },
|
||||
parallax_factor: ParallaxFactor { x: 1.0, y: 1.0 },
|
||||
tilemap: TileMap {
|
||||
width,
|
||||
height,
|
||||
@ -875,7 +875,7 @@ mod tests {
|
||||
active: false,
|
||||
glyph_bank_id,
|
||||
tile_size: TileSize::Size8,
|
||||
motion_factor: MotionFactor { x: 1.0, y: 1.0 },
|
||||
parallax_factor: ParallaxFactor { x: 1.0, y: 1.0 },
|
||||
tilemap: TileMap { width, height, tiles: vec![Tile::default(); width * height] },
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
use crate::asset::AssetManager;
|
||||
use crate::audio::Audio;
|
||||
use crate::frame_composer::FrameComposer;
|
||||
use crate::gfx::Gfx;
|
||||
use crate::memory_banks::{
|
||||
GlyphBankPoolAccess, GlyphBankPoolInstaller, MemoryBanks, SceneBankPoolInstaller,
|
||||
SoundBankPoolAccess, SoundBankPoolInstaller,
|
||||
GlyphBankPoolAccess, GlyphBankPoolInstaller, MemoryBanks, SceneBankPoolAccess,
|
||||
SceneBankPoolInstaller, SoundBankPoolAccess, SoundBankPoolInstaller,
|
||||
};
|
||||
use crate::pad::Pad;
|
||||
use crate::touch::Touch;
|
||||
@ -26,6 +27,8 @@ use std::sync::Arc;
|
||||
pub struct Hardware {
|
||||
/// The Graphics Processing Unit (GPU). Handles drawing primitives, sprites, and tilemaps.
|
||||
pub gfx: Gfx,
|
||||
/// Canonical frame orchestration owner for scene/camera/cache/resolver/sprites.
|
||||
pub frame_composer: FrameComposer,
|
||||
/// The Sound Processing Unit (SPU). Manages sample playback and volume control.
|
||||
pub audio: Audio,
|
||||
/// The standard digital gamepad. Provides state for D-Pad, face buttons, and triggers.
|
||||
@ -98,6 +101,11 @@ impl Hardware {
|
||||
Self::H,
|
||||
Arc::clone(&memory_banks) as Arc<dyn GlyphBankPoolAccess>,
|
||||
),
|
||||
frame_composer: FrameComposer::new(
|
||||
Self::W,
|
||||
Self::H,
|
||||
Arc::clone(&memory_banks) as Arc<dyn SceneBankPoolAccess>,
|
||||
),
|
||||
audio: Audio::new(Arc::clone(&memory_banks) as Arc<dyn SoundBankPoolAccess>),
|
||||
pad: Pad::default(),
|
||||
touch: Touch::default(),
|
||||
@ -122,7 +130,7 @@ mod tests {
|
||||
use prometeu_hal::glyph::Glyph;
|
||||
use prometeu_hal::glyph_bank::{GlyphBank, TileSize};
|
||||
use prometeu_hal::scene_bank::SceneBank;
|
||||
use prometeu_hal::scene_layer::{MotionFactor, SceneLayer};
|
||||
use prometeu_hal::scene_layer::{ParallaxFactor, SceneLayer};
|
||||
use prometeu_hal::scene_viewport_cache::SceneViewportCache;
|
||||
use prometeu_hal::scene_viewport_resolver::SceneViewportResolver;
|
||||
use prometeu_hal::tile::Tile;
|
||||
@ -142,7 +150,7 @@ mod tests {
|
||||
active: true,
|
||||
glyph_bank_id: 0,
|
||||
tile_size: TileSize::Size8,
|
||||
motion_factor: MotionFactor { x: 1.0, y: 1.0 },
|
||||
parallax_factor: ParallaxFactor { x: 1.0, y: 1.0 },
|
||||
tilemap: TileMap {
|
||||
width: 4,
|
||||
height: 4,
|
||||
@ -182,4 +190,20 @@ mod tests {
|
||||
|
||||
assert_eq!(hardware.gfx.front_buffer()[0], Color::RED.raw());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hardware_constructs_frame_composer_with_shared_scene_bank_access() {
|
||||
let banks = Arc::new(MemoryBanks::new());
|
||||
banks.install_scene_bank(2, Arc::new(make_scene()));
|
||||
|
||||
let hardware = Hardware::new_with_memory_banks(banks);
|
||||
let scene = hardware
|
||||
.frame_composer
|
||||
.scene_bank_slot(2)
|
||||
.expect("scene bank slot 2 should be resident");
|
||||
|
||||
assert_eq!(hardware.frame_composer.viewport_size(), (Hardware::W, Hardware::H));
|
||||
assert_eq!(hardware.frame_composer.scene_bank_slot_count(), 16);
|
||||
assert_eq!(scene.layers[0].tile_size, TileSize::Size8);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
mod asset;
|
||||
mod audio;
|
||||
mod frame_composer;
|
||||
mod gfx;
|
||||
pub mod hardware;
|
||||
mod memory_banks;
|
||||
@ -8,6 +9,7 @@ mod touch;
|
||||
|
||||
pub use crate::asset::AssetManager;
|
||||
pub use crate::audio::{Audio, AudioCommand, Channel, MAX_CHANNELS, OUTPUT_SAMPLE_RATE};
|
||||
pub use crate::frame_composer::{FrameComposer, SceneStatus, SpriteController};
|
||||
pub use crate::gfx::Gfx;
|
||||
pub use crate::memory_banks::{
|
||||
GlyphBankPoolAccess, GlyphBankPoolInstaller, MemoryBanks, SceneBankPoolAccess,
|
||||
|
||||
@ -10,16 +10,16 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::glyph::Glyph;
|
||||
use crate::glyph_bank::TileSize;
|
||||
use crate::scene_layer::MotionFactor;
|
||||
use crate::scene_layer::ParallaxFactor;
|
||||
use crate::tile::Tile;
|
||||
use crate::tilemap::TileMap;
|
||||
|
||||
fn layer(glyph_bank_id: u8, motion_x: f32, motion_y: f32, glyph_id: u16) -> SceneLayer {
|
||||
fn layer(glyph_bank_id: u8, parallax_x: f32, parallax_y: f32, glyph_id: u16) -> SceneLayer {
|
||||
SceneLayer {
|
||||
active: true,
|
||||
glyph_bank_id,
|
||||
tile_size: TileSize::Size16,
|
||||
motion_factor: MotionFactor { x: motion_x, y: motion_y },
|
||||
parallax_factor: ParallaxFactor { x: parallax_x, y: parallax_y },
|
||||
tilemap: TileMap {
|
||||
width: 1,
|
||||
height: 1,
|
||||
|
||||
@ -2,7 +2,7 @@ use crate::glyph_bank::TileSize;
|
||||
use crate::tilemap::TileMap;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct MotionFactor {
|
||||
pub struct ParallaxFactor {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
}
|
||||
@ -12,7 +12,7 @@ pub struct SceneLayer {
|
||||
pub active: bool,
|
||||
pub glyph_bank_id: u8,
|
||||
pub tile_size: TileSize,
|
||||
pub motion_factor: MotionFactor,
|
||||
pub parallax_factor: ParallaxFactor,
|
||||
pub tilemap: TileMap,
|
||||
}
|
||||
|
||||
@ -23,12 +23,12 @@ mod tests {
|
||||
use crate::tile::Tile;
|
||||
|
||||
#[test]
|
||||
fn scene_layer_preserves_motion_factor_and_tilemap_ownership() {
|
||||
fn scene_layer_preserves_parallax_factor_and_tilemap_ownership() {
|
||||
let layer = SceneLayer {
|
||||
active: true,
|
||||
glyph_bank_id: 7,
|
||||
tile_size: TileSize::Size16,
|
||||
motion_factor: MotionFactor { x: 0.5, y: 0.75 },
|
||||
parallax_factor: ParallaxFactor { x: 0.5, y: 0.75 },
|
||||
tilemap: TileMap {
|
||||
width: 2,
|
||||
height: 1,
|
||||
@ -50,8 +50,8 @@ mod tests {
|
||||
};
|
||||
|
||||
assert_eq!(layer.glyph_bank_id, 7);
|
||||
assert_eq!(layer.motion_factor.x, 0.5);
|
||||
assert_eq!(layer.motion_factor.y, 0.75);
|
||||
assert_eq!(layer.parallax_factor.x, 0.5);
|
||||
assert_eq!(layer.parallax_factor.y, 0.75);
|
||||
assert_eq!(layer.tilemap.width, 2);
|
||||
assert_eq!(layer.tilemap.tiles[1].glyph.glyph_id, 22);
|
||||
assert!(layer.tilemap.tiles[1].flip_x);
|
||||
|
||||
@ -270,7 +270,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::glyph::Glyph;
|
||||
use crate::glyph_bank::TileSize;
|
||||
use crate::scene_layer::MotionFactor;
|
||||
use crate::scene_layer::ParallaxFactor;
|
||||
use crate::tile::Tile;
|
||||
use crate::tilemap::TileMap;
|
||||
|
||||
@ -295,7 +295,7 @@ mod tests {
|
||||
active: true,
|
||||
glyph_bank_id,
|
||||
tile_size: TileSize::Size16,
|
||||
motion_factor: MotionFactor { x: 1.0, y: 1.0 },
|
||||
parallax_factor: ParallaxFactor { x: 1.0, y: 1.0 },
|
||||
tilemap: TileMap { width: 4, height: 4, tiles },
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,8 +96,8 @@ impl SceneViewportResolver {
|
||||
let layer_inputs: [(i32, i32, i32, i32, i32); 4] = std::array::from_fn(|i| {
|
||||
let layer = &scene.layers[i];
|
||||
let tile_size_px = layer.tile_size as i32;
|
||||
let layer_camera_x_px = ((camera_x_px as f32) * layer.motion_factor.x).floor() as i32;
|
||||
let layer_camera_y_px = ((camera_y_px as f32) * layer.motion_factor.y).floor() as i32;
|
||||
let layer_camera_x_px = ((camera_x_px as f32) * layer.parallax_factor.x).floor() as i32;
|
||||
let layer_camera_y_px = ((camera_y_px as f32) * layer.parallax_factor.y).floor() as i32;
|
||||
let layer_center_x_px = layer_camera_x_px + self.viewport_width_px / 2;
|
||||
let layer_center_y_px = layer_camera_y_px + self.viewport_height_px / 2;
|
||||
(
|
||||
@ -388,14 +388,14 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::glyph::Glyph;
|
||||
use crate::glyph_bank::TileSize;
|
||||
use crate::scene_layer::{MotionFactor, SceneLayer};
|
||||
use crate::scene_layer::{ParallaxFactor, SceneLayer};
|
||||
use crate::tile::Tile;
|
||||
use crate::tilemap::TileMap;
|
||||
|
||||
fn make_layer(
|
||||
tile_size: TileSize,
|
||||
motion_x: f32,
|
||||
motion_y: f32,
|
||||
parallax_x: f32,
|
||||
parallax_y: f32,
|
||||
width: usize,
|
||||
height: usize,
|
||||
) -> SceneLayer {
|
||||
@ -413,7 +413,7 @@ mod tests {
|
||||
active: true,
|
||||
glyph_bank_id: 1,
|
||||
tile_size,
|
||||
motion_factor: MotionFactor { x: motion_x, y: motion_y },
|
||||
parallax_factor: ParallaxFactor { x: parallax_x, y: parallax_y },
|
||||
tilemap: TileMap { width, height, tiles },
|
||||
}
|
||||
}
|
||||
@ -443,7 +443,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn per_layer_copy_requests_follow_motion_factor() {
|
||||
fn per_layer_copy_requests_follow_parallax_factor() {
|
||||
let scene = make_scene();
|
||||
let mut resolver = SceneViewportResolver::new(320, 180, 25, 16, 12, 20);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user