use sevenx_engine::*;
use sevenx_engine::world::World;
struct Platformer3D {
renderer3d: Renderer3D,
player: Mesh3D,
player_pos: Vec3,
player_vel: Vec3,
on_ground: bool,
platforms: Vec<Platform>,
camera_distance: f32,
camera_height: f32,
particles: ParticleSystem3D,
score: i32,
coins: Vec<Coin>,
}
struct Platform {
mesh: Mesh3D,
position: Vec3,
size: Vec3,
}
struct Coin {
mesh: Mesh3D,
position: Vec3,
rotation: f32,
collected: bool,
}
impl GameState for Platformer3D {
fn new() -> Self {
let mut renderer3d = Renderer3D::new(800, 600);
renderer3d.wireframe = false;
renderer3d.backface_culling = true;
let mut player = Mesh3D::cube(1.0);
for vertex in &mut player.vertices {
vertex.color = [100, 200, 255, 255]; }
let mut platforms = Vec::new();
platforms.push(Platform::new(Vec3::new(0.0, -2.0, 0.0), Vec3::new(8.0, 0.5, 8.0), [100, 150, 100, 255]));
platforms.push(Platform::new(Vec3::new(10.0, -1.0, 0.0), Vec3::new(6.0, 0.5, 6.0), [150, 100, 100, 255]));
platforms.push(Platform::new(Vec3::new(18.0, 1.0, 0.0), Vec3::new(6.0, 0.5, 6.0), [100, 100, 150, 255]));
platforms.push(Platform::new(Vec3::new(26.0, 3.0, 0.0), Vec3::new(6.0, 0.5, 6.0), [150, 150, 100, 255]));
platforms.push(Platform::new(Vec3::new(5.0, 2.0, 8.0), Vec3::new(4.0, 0.5, 4.0), [100, 150, 150, 255]));
platforms.push(Platform::new(Vec3::new(15.0, 4.0, -8.0), Vec3::new(4.0, 0.5, 4.0), [150, 100, 150, 255]));
let mut coins = Vec::new();
coins.push(Coin::new(Vec3::new(10.0, 1.0, 0.0)));
coins.push(Coin::new(Vec3::new(18.0, 3.0, 0.0)));
coins.push(Coin::new(Vec3::new(26.0, 5.0, 0.0)));
coins.push(Coin::new(Vec3::new(5.0, 4.0, 8.0)));
coins.push(Coin::new(Vec3::new(15.0, 6.0, -8.0)));
let particles = ParticleSystem3D::new(300);
Self {
renderer3d,
player,
player_pos: Vec3::new(0.0, 0.0, 0.0),
player_vel: Vec3::new(0.0, 0.0, 0.0),
on_ground: false,
platforms,
camera_distance: 15.0,
camera_height: 8.0,
particles,
score: 0,
coins,
}
}
fn update(&mut self, dt: f32, input: &sevenx_engine::input::InputHandler, _world: &mut World) {
let (move_x, move_y) = input.get_movement_vector();
let speed = if input.is_shift_pressed() { 12.0 } else { 8.0 };
self.player_pos.x += move_x * speed * dt;
self.player_pos.z += move_y * speed * dt;
if input.is_key_just_pressed(KeyCode::Space) && self.on_ground {
self.player_vel.y = 12.0;
self.on_ground = false;
self.particles.sparkles(self.player_pos);
println!("🦘 Pulo!");
}
let scroll = input.get_mouse_wheel_delta();
if scroll != 0.0 {
self.camera_distance = (self.camera_distance - scroll * 2.0).clamp(5.0, 30.0);
}
self.player_vel.y -= 25.0 * dt;
self.player_pos.y += self.player_vel.y * dt;
self.on_ground = false;
for platform in &self.platforms {
if self.check_collision(&platform) {
if self.player_vel.y < 0.0 {
self.player_pos.y = platform.position.y + platform.size.y / 2.0 + 0.5;
self.player_vel.y = 0.0;
self.on_ground = true;
}
}
}
for coin in &mut self.coins {
if !coin.collected {
let dist = (self.player_pos.x - coin.position.x).abs() +
(self.player_pos.y - coin.position.y).abs() +
(self.player_pos.z - coin.position.z).abs();
if dist < 2.0 {
coin.collected = true;
self.score += 100;
self.particles.sparkles(coin.position);
}
}
}
for coin in &mut self.coins {
if !coin.collected {
coin.rotation += 3.0 * dt;
coin.mesh.rotation.y = coin.rotation;
}
}
if self.player_pos.y < -20.0 {
self.player_pos = Vec3::new(0.0, 0.0, 0.0);
self.player_vel = Vec3::zero();
}
self.update_camera();
self.particles.update(dt);
}
fn draw(&mut self, _world: &World, frame: &mut [u8]) {
for y in 0..600 {
let sky_color = 100 + (y as f32 / 600.0 * 100.0) as u8;
for x in 0..800 {
let idx = ((y * 800 + x) * 4) as usize;
if idx + 3 < frame.len() {
frame[idx] = sky_color / 3;
frame[idx + 1] = sky_color / 2;
frame[idx + 2] = sky_color;
frame[idx + 3] = 255;
}
}
}
for platform in &self.platforms {
self.renderer3d.render_mesh(&platform.mesh, frame, 800, 600);
}
for coin in &self.coins {
if !coin.collected {
self.renderer3d.render_mesh(&coin.mesh, frame, 800, 600);
}
}
self.player.position = self.player_pos;
self.renderer3d.render_mesh(&self.player, frame, 800, 600);
self.renderer3d.render_particles(&self.particles, frame, 800, 600);
self.draw_hud(frame);
}
}
impl Platformer3D {
fn update_camera(&mut self) {
self.renderer3d.camera.position = Vec3::new(
self.player_pos.x - self.camera_distance * 0.7,
self.player_pos.y + self.camera_height,
self.player_pos.z + self.camera_distance * 0.7,
);
self.renderer3d.camera.look_at(self.player_pos);
}
fn check_collision(&self, platform: &Platform) -> bool {
let px = self.player_pos.x;
let py = self.player_pos.y;
let pz = self.player_pos.z;
let min_x = platform.position.x - platform.size.x / 2.0;
let max_x = platform.position.x + platform.size.x / 2.0;
let min_z = platform.position.z - platform.size.z / 2.0;
let max_z = platform.position.z + platform.size.z / 2.0;
let top_y = platform.position.y + platform.size.y / 2.0;
px > min_x && px < max_x &&
pz > min_z && pz < max_z &&
py > top_y - 1.0 && py < top_y + 1.0
}
fn draw_hud(&self, frame: &mut [u8]) {
for y in 0..50 {
for x in 0..800 {
let idx = ((y * 800 + x) * 4) as usize;
if idx + 3 < frame.len() {
frame[idx] = (frame[idx] as f32 * 0.3) as u8;
frame[idx + 1] = (frame[idx + 1] as f32 * 0.3) as u8;
frame[idx + 2] = (frame[idx + 2] as f32 * 0.3) as u8;
}
}
}
self.draw_text(frame, 20, 15, &format!("SCORE: {}", self.score));
let coins_left = self.coins.iter().filter(|c| !c.collected).count();
self.draw_text(frame, 200, 15, &format!("COINS: {}", coins_left));
self.draw_text(frame, 400, 15, "WASD: Move | SPACE: Jump");
}
fn draw_text(&self, frame: &mut [u8], x: usize, y: usize, text: &str) {
for (i, _c) in text.chars().enumerate() {
let px = x + i * 8;
if px < 800 && y < 600 {
for dy in 0..8 {
for dx in 0..6 {
let idx = (((y + dy) * 800 + (px + dx)) * 4) as usize;
if idx + 3 < frame.len() {
frame[idx] = 255;
frame[idx + 1] = 255;
frame[idx + 2] = 255;
}
}
}
}
}
}
}
impl Platform {
fn new(position: Vec3, size: Vec3, color: [u8; 4]) -> Self {
let mut mesh = Mesh3D::cube(1.0);
mesh.position = position;
mesh.scale = size;
for vertex in &mut mesh.vertices {
vertex.color = color;
}
Self { mesh, position, size }
}
}
impl Coin {
fn new(position: Vec3) -> Self {
let mut mesh = Mesh3D::cube(0.5);
mesh.position = position;
mesh.scale = Vec3::new(0.5, 0.5, 0.1);
for vertex in &mut mesh.vertices {
vertex.color = [255, 215, 0, 255]; }
Self {
mesh,
position,
rotation: 0.0,
collected: false,
}
}
}
fn main() {
println!("🎮 SevenX Engine v0.2.7 - Plataforma 3D");
println!("🎲 Jogo de Plataforma 3D Completo");
println!();
println!("🎯 Controles:");
println!(" WASD - Mover");
println!(" Shift - Correr (v0.2.7!)");
println!(" Espaço - Pular");
println!(" Scroll - Zoom da câmera (v0.2.7!)");
println!();
println!("🎯 Objetivo: Colete todas as moedas douradas!");
println!();
let config = EngineConfig::default()
.with_title("SevenX Engine v0.2.7 - Plataforma 3D")
.with_size(800, 600);
let engine = Engine::with_config(config);
engine.run::<Platformer3D>();
}