v0.1 working
This commit is contained in:
parent
c718d36fe2
commit
8e65ff65c5
@ -46,7 +46,7 @@ impl Machine {
|
|||||||
/// Lógica do frame (demo hardcoded por enquanto).
|
/// Lógica do frame (demo hardcoded por enquanto).
|
||||||
pub fn tick(&mut self) {
|
pub fn tick(&mut self) {
|
||||||
// Limpa a tela com um azul escuro "estilo console"
|
// Limpa a tela com um azul escuro "estilo console"
|
||||||
self.gfx.clear(Color::rgb(0x20, 0x20, 0x40));
|
self.gfx.clear(Color::BLACK);
|
||||||
|
|
||||||
// Simula o carregamento de um banco se estiver vazio (apenas para teste)
|
// Simula o carregamento de um banco se estiver vazio (apenas para teste)
|
||||||
if self.gfx.banks[0].is_none() {
|
if self.gfx.banks[0].is_none() {
|
||||||
@ -62,22 +62,103 @@ impl Machine {
|
|||||||
let px = start_x + x;
|
let px = start_x + x;
|
||||||
let py = start_y + y;
|
let py = start_y + y;
|
||||||
let idx = py * 128 + px;
|
let idx = py * 128 + px;
|
||||||
test_bank.pixels[idx] = Color::WHITE;
|
test_bank.pixels[idx] = Color::GREEN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.gfx.banks[0] = Some(test_bank);
|
self.gfx.banks[0] = Some(test_bank);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Coloca o Tile ID 1 no mapa do HUD (canto superior esquerdo)
|
// Simula o carregamento de um banco se estiver vazio (apenas para teste)
|
||||||
self.gfx.hud.map.set_tile(0, 0, crate::model::Tile { id: 1, ..Default::default() });
|
if self.gfx.banks[1].is_none() {
|
||||||
|
let mut test_bank = crate::model::TileBank::new(crate::model::TileSize::Size16, 128, 128);
|
||||||
|
// Pinta o primeiro tile (ID 1) de Branco para teste
|
||||||
|
// Ele começa no pixel (16, 0) pois o ID 0 é o primeiro (0,0)
|
||||||
|
let tile_size = 16;
|
||||||
|
let start_x = 16; // ID 1 está na segunda posição da primeira linha
|
||||||
|
let start_y = 0;
|
||||||
|
|
||||||
for i in 0..10 {
|
for y in 0..tile_size {
|
||||||
|
for x in 0..tile_size {
|
||||||
|
let px = start_x + x;
|
||||||
|
let py = start_y + y;
|
||||||
|
let idx = py * 128 + px;
|
||||||
|
test_bank.pixels[idx] = Color::RED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.gfx.banks[1] = Some(test_bank);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simula o carregamento de um banco se estiver vazio (apenas para teste)
|
||||||
|
if self.gfx.banks[2].is_none() {
|
||||||
|
let mut test_bank = crate::model::TileBank::new(crate::model::TileSize::Size16, 128, 128);
|
||||||
|
// Pinta o primeiro tile (ID 1) de Branco para teste
|
||||||
|
// Ele começa no pixel (16, 0) pois o ID 0 é o primeiro (0,0)
|
||||||
|
let tile_size = 16;
|
||||||
|
let start_x = 16; // ID 1 está na segunda posição da primeira linha
|
||||||
|
let start_y = 0;
|
||||||
|
|
||||||
|
for y in 0..tile_size {
|
||||||
|
for x in 0..tile_size {
|
||||||
|
let px = start_x + x;
|
||||||
|
let py = start_y + y;
|
||||||
|
let idx = py * 128 + px;
|
||||||
|
test_bank.pixels[idx] = Color::INDIGO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.gfx.banks[2] = Some(test_bank);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Coloca o Tile ID 1 no mapa do HUD (canto superior esquerdo)
|
||||||
|
self.gfx.hud.map.set_tile(18, 6, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
|
||||||
|
self.gfx.layers[0].bank_id = 1;
|
||||||
|
self.gfx.layers[0].map.set_tile(8, 1, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[0].map.set_tile(8, 2, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[0].map.set_tile(8, 3, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[0].map.set_tile(8, 4, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[0].map.set_tile(8, 5, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[1].bank_id = 1;
|
||||||
|
self.gfx.layers[1].map.set_tile(9, 1, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[1].map.set_tile(9, 2, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[1].map.set_tile(9, 3, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[1].map.set_tile(9, 4, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[1].map.set_tile(9, 5, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[2].bank_id = 1;
|
||||||
|
self.gfx.layers[2].map.set_tile(10, 1, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[2].map.set_tile(10, 2, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[2].map.set_tile(10, 3, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[2].map.set_tile(10, 4, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[2].map.set_tile(10, 5, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[3].bank_id = 1;
|
||||||
|
self.gfx.layers[3].map.set_tile(11, 1, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[3].map.set_tile(11, 2, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[3].map.set_tile(11, 3, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[3].map.set_tile(11, 4, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
self.gfx.layers[3].map.set_tile(11, 5, crate::model::Tile { id: 1, ..Default::default() });
|
||||||
|
|
||||||
|
for i in 0..512 {
|
||||||
let s = &mut self.gfx.sprites[i];
|
let s = &mut self.gfx.sprites[i];
|
||||||
s.active = true;
|
s.active = true;
|
||||||
s.bank_id = 0;
|
|
||||||
|
// Distribui os sprites entre os 3 bancos de teste que você criou
|
||||||
|
s.bank_id = (i % 2) as u8 + 1;
|
||||||
s.tile.id = 1;
|
s.tile.id = 1;
|
||||||
s.x = ((self.frame_index + (i as u64 * 20)) % 320) as i32;
|
|
||||||
s.y = (i as i32 * 15) + 20;
|
// Cria um movimento caótico baseado no index do sprite e no frame_index
|
||||||
|
let speed = (1 + (i % 3)) as u64;
|
||||||
|
s.x = (((self.frame_index * speed) + (i as u64 * 10)) % 400) as i32 - 40;
|
||||||
|
s.y = (((self.frame_index * speed) + (i as u64 * 4)) % 180) as i32;
|
||||||
|
if i % 2 != 0 {
|
||||||
|
s.y = 179 - s.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Distribui as prioridades de 0 a 4
|
||||||
|
// Isso vai fazer alguns sprites passarem atrás do cenário e outros na frente
|
||||||
|
s.priority = (i % 5) as u8;
|
||||||
|
|
||||||
|
// Efeito de flip alternado para testar a lógica de espelhamento
|
||||||
|
s.flip_x = i % 2 == 0;
|
||||||
|
s.flip_y = i % 3 == 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
pub struct Color(pub u16);
|
pub struct Color(pub u16);
|
||||||
|
|
||||||
impl Color {
|
impl Color {
|
||||||
|
pub const INDIGO: Self = Self::rgb(32, 32, 64);
|
||||||
pub const BLACK: Self = Self::rgb(0, 0, 0); // 0x0000
|
pub const BLACK: Self = Self::rgb(0, 0, 0); // 0x0000
|
||||||
pub const WHITE: Self = Self::rgb(255, 255, 255); // 0xFFFF
|
pub const WHITE: Self = Self::rgb(255, 255, 255); // 0xFFFF
|
||||||
pub const RED: Self = Self::rgb(255, 0, 0); // 0xF800
|
pub const RED: Self = Self::rgb(255, 0, 0); // 0xF800
|
||||||
@ -35,7 +36,7 @@ impl Color {
|
|||||||
pub const fn pack_from_native(r: u8, g: u8, b: u8) -> u16 {
|
pub const fn pack_from_native(r: u8, g: u8, b: u8) -> u16 {
|
||||||
((r as u16 & 0x1F) << 11) | ((g as u16 & 0x3F) << 5) | (b as u16 & 0x1F)
|
((r as u16 & 0x1F) << 11) | ((g as u16 & 0x3F) << 5) | (b as u16 & 0x1F)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cria uma cor RGB565 a partir de componentes 8-bit (0..255).
|
/// Cria uma cor RGB565 a partir de componentes 8-bit (0..255).
|
||||||
pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
|
pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
|
||||||
let r5 = (r as u16 >> 3) & 0x1F;
|
let r5 = (r as u16 >> 3) & 0x1F;
|
||||||
|
|||||||
@ -9,5 +9,5 @@ pub struct Sprite {
|
|||||||
pub active: bool,
|
pub active: bool,
|
||||||
pub flip_x: bool,
|
pub flip_x: bool,
|
||||||
pub flip_y: bool,
|
pub flip_y: bool,
|
||||||
// No futuro: priority, palette override, etc.
|
pub priority: u8,
|
||||||
}
|
}
|
||||||
@ -38,6 +38,7 @@ impl Gfx {
|
|||||||
active: false,
|
active: false,
|
||||||
flip_x: false,
|
flip_x: false,
|
||||||
flip_y: false,
|
flip_y: false,
|
||||||
|
priority: 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
let len = w * h;
|
let len = w * h;
|
||||||
@ -114,15 +115,20 @@ impl Gfx {
|
|||||||
/// Pipeline principal de renderização do frame.
|
/// Pipeline principal de renderização do frame.
|
||||||
/// Segue a ordem de prioridade do manual (Capítulo 4.11).
|
/// Segue a ordem de prioridade do manual (Capítulo 4.11).
|
||||||
pub fn render_all(&mut self) {
|
pub fn render_all(&mut self) {
|
||||||
// 1. Layers de jogo (0 a 3)
|
// 1. Sprites de prioridade 0 (Atrás da Layer 0 - o fundo do fundo)
|
||||||
|
self.render_sprites_by_priority(0);
|
||||||
|
|
||||||
for i in 0..self.layers.len() {
|
for i in 0..self.layers.len() {
|
||||||
|
// 2. Layers de jogo (0 a 3)
|
||||||
self.render_layer(i);
|
self.render_layer(i);
|
||||||
|
// 3. Sprites de acordo com prioridade
|
||||||
|
// i=0 desenha sprites priority 1 (sobre layer 0)
|
||||||
|
// i=1 desenha sprites priority 2 (sobre layer 1)
|
||||||
|
// i=2 desenha sprites priority 3 (sobre layer 2)
|
||||||
|
// i=3 desenha sprites priority 4 (sobre layer 3 - à frente de tudo)
|
||||||
|
self.render_sprites_by_priority((i + 1) as u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Sprites
|
|
||||||
self.render_sprites();
|
|
||||||
|
|
||||||
|
|
||||||
// 3. HUD (Sempre por cima)
|
// 3. HUD (Sempre por cima)
|
||||||
self.render_hud();
|
self.render_hud();
|
||||||
}
|
}
|
||||||
@ -189,9 +195,11 @@ impl Gfx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_sprites(&mut self) {
|
fn render_sprites_by_priority(&mut self, priority: u8) {
|
||||||
for sprite in self.sprites.iter() {
|
for sprite in self.sprites.iter() {
|
||||||
if !sprite.active { continue; }
|
if !sprite.active || sprite.priority != priority {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let bank = match self.banks.get(sprite.bank_id as usize) {
|
let bank = match self.banks.get(sprite.bank_id as usize) {
|
||||||
Some(Some(b)) => b,
|
Some(Some(b)) => b,
|
||||||
|
|||||||
@ -31,6 +31,9 @@ struct PrometeuApp {
|
|||||||
|
|
||||||
frame_target_dt: Duration,
|
frame_target_dt: Duration,
|
||||||
next_frame: Instant,
|
next_frame: Instant,
|
||||||
|
|
||||||
|
last_stats_update: Instant,
|
||||||
|
frames_since_last_update: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrometeuApp {
|
impl PrometeuApp {
|
||||||
@ -45,6 +48,9 @@ impl PrometeuApp {
|
|||||||
|
|
||||||
frame_target_dt: Duration::from_nanos(1_000_000_000 / 60),
|
frame_target_dt: Duration::from_nanos(1_000_000_000 / 60),
|
||||||
next_frame: Instant::now(),
|
next_frame: Instant::now(),
|
||||||
|
|
||||||
|
last_stats_update: Instant::now(),
|
||||||
|
frames_since_last_update: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +78,7 @@ impl PrometeuApp {
|
|||||||
impl ApplicationHandler for PrometeuApp {
|
impl ApplicationHandler for PrometeuApp {
|
||||||
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
||||||
let attrs = WindowAttributes::default()
|
let attrs = WindowAttributes::default()
|
||||||
.with_title(format!("PROMETEU - host_desktop | GFX Mem: {:.2} KB | Frame: {}", 0.0, 0))
|
.with_title(format!("PROMETEU | GFX: {:.1} KB | FPS: {:.1} | Frame: {}", 0.0, 0.0, 0))
|
||||||
.with_inner_size(LogicalSize::new(960.0, 540.0))
|
.with_inner_size(LogicalSize::new(960.0, 540.0))
|
||||||
.with_min_inner_size(LogicalSize::new(320.0, 180.0));
|
.with_min_inner_size(LogicalSize::new(320.0, 180.0));
|
||||||
|
|
||||||
@ -188,18 +194,25 @@ impl ApplicationHandler for PrometeuApp {
|
|||||||
// executa 1 frame do PROMETEU
|
// executa 1 frame do PROMETEU
|
||||||
self.machine.step_frame(&self.input_signals);
|
self.machine.step_frame(&self.input_signals);
|
||||||
|
|
||||||
// temp: atualiza o título da janela a cada 1 segundo (60 frames)
|
self.frames_since_last_update += 1;
|
||||||
if self.machine.frame_index % 60 == 0 {
|
|
||||||
|
let elapsed = now.duration_since(self.last_stats_update);
|
||||||
|
if elapsed >= Duration::from_secs(1) {
|
||||||
if let Some(window) = self.window {
|
if let Some(window) = self.window {
|
||||||
|
let fps = self.frames_since_last_update as f64 / elapsed.as_secs_f64();
|
||||||
let usage_bytes = self.machine.gfx.memory_usage_bytes();
|
let usage_bytes = self.machine.gfx.memory_usage_bytes();
|
||||||
let kb = usage_bytes as f64 / 1024.0;
|
let kb = usage_bytes as f64 / 1024.0;
|
||||||
|
|
||||||
let title = format!(
|
let title = format!(
|
||||||
"PROMETEU - host_desktop | GFX Mem: {:.2} KB | Frame: {}",
|
"PROMETEU | GFX: {:.1} KB | FPS: {:.1} | Frame: {}",
|
||||||
kb,
|
kb,
|
||||||
|
fps,
|
||||||
self.machine.frame_index);
|
self.machine.frame_index);
|
||||||
window.set_title(&title);
|
window.set_title(&title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.last_stats_update = now;
|
||||||
|
self.frames_since_last_update = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pede redraw
|
// pede redraw
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user