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]) {
for pixel in pixels.chunks_exact_mut(4) {
pixel.copy_from_slice(&self.clear_color);
}
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 {
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);
}
}
}
}
}
}
}
}