v0.1 working

This commit is contained in:
Nilton Constantino 2026-01-13 08:17:06 +00:00
parent e440b7280c
commit 140c56d731
No known key found for this signature in database
5 changed files with 124 additions and 21 deletions

View File

@ -46,7 +46,7 @@ impl Machine {
/// Lógica do frame (demo hardcoded por enquanto).
pub fn tick(&mut self) {
// 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)
if self.gfx.banks[0].is_none() {
@ -62,22 +62,103 @@ impl Machine {
let px = start_x + x;
let py = start_y + y;
let idx = py * 128 + px;
test_bank.pixels[idx] = Color::WHITE;
test_bank.pixels[idx] = Color::GREEN;
}
}
self.gfx.banks[0] = Some(test_bank);
}
// Coloca o Tile ID 1 no mapa do HUD (canto superior esquerdo)
self.gfx.hud.map.set_tile(0, 0, crate::model::Tile { id: 1, ..Default::default() });
// Simula o carregamento de um banco se estiver vazio (apenas para teste)
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];
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.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;
}
}

View File

@ -9,6 +9,7 @@
pub struct Color(pub u16);
impl Color {
pub const INDIGO: Self = Self::rgb(32, 32, 64);
pub const BLACK: Self = Self::rgb(0, 0, 0); // 0x0000
pub const WHITE: Self = Self::rgb(255, 255, 255); // 0xFFFF
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 {
((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).
pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
let r5 = (r as u16 >> 3) & 0x1F;

View File

@ -9,5 +9,5 @@ pub struct Sprite {
pub active: bool,
pub flip_x: bool,
pub flip_y: bool,
// No futuro: priority, palette override, etc.
pub priority: u8,
}

View File

@ -38,6 +38,7 @@ impl Gfx {
active: false,
flip_x: false,
flip_y: false,
priority: 4,
};
let len = w * h;
@ -114,15 +115,20 @@ impl Gfx {
/// Pipeline principal de renderização do frame.
/// Segue a ordem de prioridade do manual (Capítulo 4.11).
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() {
// 2. Layers de jogo (0 a 3)
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)
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() {
if !sprite.active { continue; }
if !sprite.active || sprite.priority != priority {
continue;
}
let bank = match self.banks.get(sprite.bank_id as usize) {
Some(Some(b)) => b,

View File

@ -31,6 +31,9 @@ struct PrometeuApp {
frame_target_dt: Duration,
next_frame: Instant,
last_stats_update: Instant,
frames_since_last_update: u64,
}
impl PrometeuApp {
@ -45,6 +48,9 @@ impl PrometeuApp {
frame_target_dt: Duration::from_nanos(1_000_000_000 / 60),
next_frame: Instant::now(),
last_stats_update: Instant::now(),
frames_since_last_update: 0,
}
}
@ -72,7 +78,7 @@ impl PrometeuApp {
impl ApplicationHandler for PrometeuApp {
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
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_min_inner_size(LogicalSize::new(320.0, 180.0));
@ -188,18 +194,25 @@ impl ApplicationHandler for PrometeuApp {
// executa 1 frame do PROMETEU
self.machine.step_frame(&self.input_signals);
// temp: atualiza o título da janela a cada 1 segundo (60 frames)
if self.machine.frame_index % 60 == 0 {
self.frames_since_last_update += 1;
let elapsed = now.duration_since(self.last_stats_update);
if elapsed >= Duration::from_secs(1) {
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 kb = usage_bytes as f64 / 1024.0;
let title = format!(
"PROMETEU - host_desktop | GFX Mem: {:.2} KB | Frame: {}",
"PROMETEU | GFX: {:.1} KB | FPS: {:.1} | Frame: {}",
kb,
fps,
self.machine.frame_index);
window.set_title(&title);
}
self.last_stats_update = now;
self.frames_since_last_update = 0;
}
// pede redraw