sevenx_engine 0.2.11

Engine de jogos 2D/3D completa com suporte Android, física, áudio, partículas, tilemap, UI, eventos e sistema 3D avançado com PBR.
Documentation
use crate::camera::Camera;
use crate::world::World;

pub struct Renderer {
    pub camera: Camera,
    pub clear_color: [u8; 4],
}

impl Renderer {
    pub fn new(width: u32, height: u32) -> Self {
        Self {
            camera: Camera::new(width, height),
            clear_color: [0x10, 0x10, 0x10, 0xFF],
        }
    }

    pub fn with_clear_color(mut self, color: [u8; 4]) -> Self {
        self.clear_color = color;
        self
    }

    pub fn draw(&self, world: &World, pixels: &mut [u8]) {
        // Limpa o buffer
        for pixel in pixels.chunks_exact_mut(4) {
            pixel.copy_from_slice(&self.clear_color);
        }

        // Renderiza objetos ordenados por z_index
        for object in &world.game_objects {
            if !object.active {
                continue;
            }
            if let Some(sheet) = object.sheets.get(&object.current_action) {
                let frame_width = sheet.frame_width;
                let frame_height = sheet.frame_height;

                let mut current_frame_index = 0;
                if let Some(anim) = object.animations.get(&object.facing_direction) {
                    current_frame_index = anim.get_current_absolute_frame();
                }

                let frames_per_row = sheet.width / frame_width;
                let frame_row = (current_frame_index as u32) / frames_per_row;
                let frame_col = (current_frame_index as u32) % frames_per_row;
                let frame_x_offset = frame_col * frame_width;
                let frame_y_offset = frame_row * frame_height;

                for y in 0..frame_height {
                    for x in 0..frame_width {
                        // Aplica transformação da câmera
                        let world_x = object.transform.position.0 + x as f32;
                        let world_y = object.transform.position.1 + y as f32;
                        let (screen_x, screen_y) = self.camera.world_to_screen(world_x, world_y);

                        if screen_x < 0
                            || screen_x >= self.camera.viewport_width as i32
                            || screen_y < 0
                            || screen_y >= self.camera.viewport_height as i32
                        {
                            continue;
                        }
                        let sheet_x = frame_x_offset + x;
                        let sheet_y = frame_y_offset + y;
                        let sheet_pixel_index = ((sheet_y * sheet.width) + sheet_x) as usize * 4;
                        if sheet_pixel_index + 3 >= sheet.rgba_data.len() {
                            continue;
                        }
                        let color = &sheet.rgba_data[sheet_pixel_index..sheet_pixel_index + 4];
                        if color[3] > 0 {
                            let screen_pixel_index = ((screen_y as u32 * self.camera.viewport_width)
                                + screen_x as u32) as usize
                                * 4;
                            if screen_pixel_index + 3 < pixels.len() {
                                pixels[screen_pixel_index..screen_pixel_index + 4]
                                    .copy_from_slice(color);
                            }
                        }
                    }
                }
            }
        }
    }
}