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
// Sistema de primitivas 2D para renderização direta

pub struct Primitives2D<'a> {
    pixels: &'a mut [u8],
    width: u32,
    height: u32,
}

impl<'a> Primitives2D<'a> {
    pub fn new(pixels: &'a mut [u8], width: u32, height: u32) -> Self {
        Self { pixels, width, height }
    }

    // Desenha um pixel
    pub fn draw_pixel(&mut self, x: i32, y: i32, color: [u8; 4]) {
        if x < 0 || x >= self.width as i32 || y < 0 || y >= self.height as i32 {
            return;
        }
        let index = ((y as u32 * self.width + x as u32) * 4) as usize;
        if index + 3 < self.pixels.len() {
            self.pixels[index..index + 4].copy_from_slice(&color);
        }
    }

    // Desenha uma linha (algoritmo de Bresenham)
    pub fn draw_line(&mut self, x0: i32, y0: i32, x1: i32, y1: i32, color: [u8; 4]) {
        let dx = (x1 - x0).abs();
        let dy = (y1 - y0).abs();
        let sx = if x0 < x1 { 1 } else { -1 };
        let sy = if y0 < y1 { 1 } else { -1 };
        let mut err = dx - dy;
        let mut x = x0;
        let mut y = y0;

        loop {
            self.draw_pixel(x, y, color);
            if x == x1 && y == y1 {
                break;
            }
            let e2 = 2 * err;
            if e2 > -dy {
                err -= dy;
                x += sx;
            }
            if e2 < dx {
                err += dx;
                y += sy;
            }
        }
    }

    // Desenha um retângulo preenchido
    pub fn draw_rect_filled(&mut self, x: i32, y: i32, width: u32, height: u32, color: [u8; 4]) {
        for dy in 0..height as i32 {
            for dx in 0..width as i32 {
                self.draw_pixel(x + dx, y + dy, color);
            }
        }
    }

    // Desenha um retângulo vazio (contorno)
    pub fn draw_rect(&mut self, x: i32, y: i32, width: u32, height: u32, color: [u8; 4]) {
        // Topo e base
        for dx in 0..width as i32 {
            self.draw_pixel(x + dx, y, color);
            self.draw_pixel(x + dx, y + height as i32 - 1, color);
        }
        // Lados
        for dy in 0..height as i32 {
            self.draw_pixel(x, y + dy, color);
            self.draw_pixel(x + width as i32 - 1, y + dy, color);
        }
    }

    // Desenha um círculo (algoritmo de Bresenham)
    pub fn draw_circle(&mut self, cx: i32, cy: i32, radius: i32, color: [u8; 4]) {
        let mut x = 0;
        let mut y = radius;
        let mut d = 3 - 2 * radius;

        while x <= y {
            self.draw_pixel(cx + x, cy + y, color);
            self.draw_pixel(cx - x, cy + y, color);
            self.draw_pixel(cx + x, cy - y, color);
            self.draw_pixel(cx - x, cy - y, color);
            self.draw_pixel(cx + y, cy + x, color);
            self.draw_pixel(cx - y, cy + x, color);
            self.draw_pixel(cx + y, cy - x, color);
            self.draw_pixel(cx - y, cy - x, color);

            if d < 0 {
                d = d + 4 * x + 6;
            } else {
                d = d + 4 * (x - y) + 10;
                y -= 1;
            }
            x += 1;
        }
    }

    // Desenha um círculo preenchido
    pub fn draw_circle_filled(&mut self, cx: i32, cy: i32, radius: i32, color: [u8; 4]) {
        for y in -radius..=radius {
            for x in -radius..=radius {
                if x * x + y * y <= radius * radius {
                    self.draw_pixel(cx + x, cy + y, color);
                }
            }
        }
    }

    // Desenha uma elipse
    pub fn draw_ellipse(&mut self, cx: i32, cy: i32, rx: i32, ry: i32, color: [u8; 4]) {
        let mut x = 0;
        let mut y = ry;
        let rx2 = rx * rx;
        let ry2 = ry * ry;
        let mut p = ry2 - (rx2 * ry) + (rx2 / 4);

        while (ry2 * x) <= (rx2 * y) {
            self.draw_pixel(cx + x, cy + y, color);
            self.draw_pixel(cx - x, cy + y, color);
            self.draw_pixel(cx + x, cy - y, color);
            self.draw_pixel(cx - x, cy - y, color);

            if p < 0 {
                x += 1;
                p = p + (2 * ry2 * x) + ry2;
            } else {
                x += 1;
                y -= 1;
                p = p + (2 * ry2 * x) - (2 * rx2 * y) + ry2;
            }
        }
    }

    // Desenha um triângulo preenchido
    pub fn draw_triangle_filled(&mut self, x0: i32, y0: i32, x1: i32, y1: i32, x2: i32, y2: i32, color: [u8; 4]) {
        // Ordena os vértices por y
        let mut points = [(x0, y0), (x1, y1), (x2, y2)];
        points.sort_by_key(|p| p.1);
        let (x0, y0) = points[0];
        let (x1, y1) = points[1];
        let (x2, y2) = points[2];

        // Preenche o triângulo
        for y in y0..=y2 {
            let mut x_start = x0;
            let mut x_end = x0;

            if y <= y1 {
                if y1 != y0 {
                    x_start = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
                }
                if y2 != y0 {
                    x_end = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
                }
            } else {
                if y2 != y1 {
                    x_start = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
                }
                if y2 != y0 {
                    x_end = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
                }
            }

            if x_start > x_end {
                std::mem::swap(&mut x_start, &mut x_end);
            }

            for x in x_start..=x_end {
                self.draw_pixel(x, y, color);
            }
        }
    }

    // Desenha um triângulo (contorno)
    pub fn draw_triangle(&mut self, x0: i32, y0: i32, x1: i32, y1: i32, x2: i32, y2: i32, color: [u8; 4]) {
        self.draw_line(x0, y0, x1, y1, color);
        self.draw_line(x1, y1, x2, y2, color);
        self.draw_line(x2, y2, x0, y0, color);
    }

    // Desenha um polígono (contorno)
    pub fn draw_polygon(&mut self, points: &[(i32, i32)], color: [u8; 4]) {
        if points.len() < 2 {
            return;
        }
        for i in 0..points.len() {
            let (x0, y0) = points[i];
            let (x1, y1) = points[(i + 1) % points.len()];
            self.draw_line(x0, y0, x1, y1, color);
        }
    }

    // Desenha uma linha grossa
    pub fn draw_thick_line(&mut self, x0: i32, y0: i32, x1: i32, y1: i32, thickness: i32, color: [u8; 4]) {
        for t in -thickness/2..=thickness/2 {
            let dx = (y1 - y0) as f32;
            let dy = (x1 - x0) as f32;
            let len = (dx * dx + dy * dy).sqrt();
            if len > 0.0 {
                let offset_x = (t as f32 * dx / len) as i32;
                let offset_y = (t as f32 * dy / len) as i32;
                self.draw_line(x0 + offset_x, y0 - offset_y, x1 + offset_x, y1 - offset_y, color);
            }
        }
    }

    // Desenha um arco
    pub fn draw_arc(&mut self, cx: i32, cy: i32, radius: i32, start_angle: f32, end_angle: f32, color: [u8; 4]) {
        let steps = (radius as f32 * (end_angle - start_angle).abs()) as i32;
        for i in 0..=steps {
            let angle = start_angle + (end_angle - start_angle) * (i as f32 / steps as f32);
            let x = cx + (angle.cos() * radius as f32) as i32;
            let y = cy + (angle.sin() * radius as f32) as i32;
            self.draw_pixel(x, y, color);
        }
    }

    // Desenha uma grade
    pub fn draw_grid(&mut self, cell_size: u32, color: [u8; 4]) {
        // Linhas verticais
        for x in (0..self.width).step_by(cell_size as usize) {
            for y in 0..self.height {
                self.draw_pixel(x as i32, y as i32, color);
            }
        }
        // Linhas horizontais
        for y in (0..self.height).step_by(cell_size as usize) {
            for x in 0..self.width {
                self.draw_pixel(x as i32, y as i32, color);
            }
        }
    }

    // Preenche uma área com uma cor (flood fill)
    pub fn flood_fill(&mut self, x: i32, y: i32, target_color: [u8; 4], fill_color: [u8; 4]) {
        if x < 0 || x >= self.width as i32 || y < 0 || y >= self.height as i32 {
            return;
        }

        let index = ((y as u32 * self.width + x as u32) * 4) as usize;
        if index + 3 >= self.pixels.len() {
            return;
        }

        let current_color = [
            self.pixels[index],
            self.pixels[index + 1],
            self.pixels[index + 2],
            self.pixels[index + 3],
        ];

        if current_color != target_color || current_color == fill_color {
            return;
        }

        let mut stack = vec![(x, y)];
        while let Some((px, py)) = stack.pop() {
            if px < 0 || px >= self.width as i32 || py < 0 || py >= self.height as i32 {
                continue;
            }

            let idx = ((py as u32 * self.width + px as u32) * 4) as usize;
            if idx + 3 >= self.pixels.len() {
                continue;
            }

            let pixel_color = [
                self.pixels[idx],
                self.pixels[idx + 1],
                self.pixels[idx + 2],
                self.pixels[idx + 3],
            ];

            if pixel_color == target_color {
                self.draw_pixel(px, py, fill_color);
                stack.push((px + 1, py));
                stack.push((px - 1, py));
                stack.push((px, py + 1));
                stack.push((px, py - 1));
            }
        }
    }

    // Desenha um gradiente horizontal
    pub fn draw_gradient_h(&mut self, x: i32, y: i32, width: u32, height: u32, color1: [u8; 4], color2: [u8; 4]) {
        for dx in 0..width {
            let t = dx as f32 / width as f32;
            let r = (color1[0] as f32 * (1.0 - t) + color2[0] as f32 * t) as u8;
            let g = (color1[1] as f32 * (1.0 - t) + color2[1] as f32 * t) as u8;
            let b = (color1[2] as f32 * (1.0 - t) + color2[2] as f32 * t) as u8;
            let a = (color1[3] as f32 * (1.0 - t) + color2[3] as f32 * t) as u8;
            let color = [r, g, b, a];
            
            for dy in 0..height {
                self.draw_pixel(x + dx as i32, y + dy as i32, color);
            }
        }
    }

    // Desenha um gradiente vertical
    pub fn draw_gradient_v(&mut self, x: i32, y: i32, width: u32, height: u32, color1: [u8; 4], color2: [u8; 4]) {
        for dy in 0..height {
            let t = dy as f32 / height as f32;
            let r = (color1[0] as f32 * (1.0 - t) + color2[0] as f32 * t) as u8;
            let g = (color1[1] as f32 * (1.0 - t) + color2[1] as f32 * t) as u8;
            let b = (color1[2] as f32 * (1.0 - t) + color2[2] as f32 * t) as u8;
            let a = (color1[3] as f32 * (1.0 - t) + color2[3] as f32 * t) as u8;
            let color = [r, g, b, a];
            
            for dx in 0..width {
                self.draw_pixel(x + dx as i32, y + dy as i32, color);
            }
        }
    }

    // Desenha um gradiente radial
    pub fn draw_gradient_radial(&mut self, cx: i32, cy: i32, radius: i32, color1: [u8; 4], color2: [u8; 4]) {
        for y in -radius..=radius {
            for x in -radius..=radius {
                let dist = ((x * x + y * y) as f32).sqrt();
                if dist <= radius as f32 {
                    let t = dist / radius as f32;
                    let r = (color1[0] as f32 * (1.0 - t) + color2[0] as f32 * t) as u8;
                    let g = (color1[1] as f32 * (1.0 - t) + color2[1] as f32 * t) as u8;
                    let b = (color1[2] as f32 * (1.0 - t) + color2[2] as f32 * t) as u8;
                    let a = (color1[3] as f32 * (1.0 - t) + color2[3] as f32 * t) as u8;
                    self.draw_pixel(cx + x, cy + y, [r, g, b, a]);
                }
            }
        }
    }
}