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 sevenx_engine::{
    audio::AudioSystem,
    events::{EventData, EventSystem, EventType},
    game_object::{Direction, ObjectType, PlayerAction},
    gamepad::{GamepadAxis, GamepadButton, GamepadManager},
    input::InputHandler,
    particles::{ParticleConfig, ParticleSystem},
    ui::{render_text, Button},
    world::World,
    Engine, EngineConfig, GameState, KeyCode,
};

#[derive(PartialEq)]
enum GameMode {
    Menu,
    Playing,
    GameOver,
}

struct CompleteGame {
    mode: GameMode,
    score: u32,
    lives: i32,
    audio: AudioSystem,
    events: EventSystem,
    particles: ParticleSystem,
    gamepad: GamepadManager,
    menu_button: Button,
}

impl GameState for CompleteGame {
    fn new() -> Self {
        let mut audio = AudioSystem::new();
        audio.set_music_volume(0.7);
        audio.set_sfx_volume(0.8);

        let mut events = EventSystem::new();
        events.on(EventType::CoinCollected, |_| {
            println!("💰 +10 pontos!");
        });

        events.on(EventType::PlayerDied, |_| {
            println!("💀 Você morreu!");
        });

        let particles = ParticleSystem::new(500);
        let gamepad = GamepadManager::new().with_deadzone(0.2);

        let menu_button = Button::new(300, 250, 200, 50, "START GAME")
            .with_color([50, 150, 50, 255])
            .with_hover_color([70, 200, 70, 255]);

        CompleteGame {
            mode: GameMode::Menu,
            score: 0,
            lives: 3,
            audio,
            events,
            particles,
            gamepad,
            menu_button,
        }
    }

    fn update(&mut self, dt: f32, input: &InputHandler, world: &mut World) {
        match self.mode {
            GameMode::Menu => {
                // Atualiza botão (simulando mouse em 400, 275)
                if self.menu_button.update(400, 275, input.is_key_pressed(KeyCode::Space)) {
                    self.mode = GameMode::Playing;
                    self.start_game(world);
                    self.audio.play_music("menu_music", true);
                }
            }
            GameMode::Playing => {
                self.update_gameplay(dt, input, world);
                self.particles.update(dt, world.gravity);
                self.events.process_queue();

                if self.lives <= 0 {
                    self.mode = GameMode::GameOver;
                    self.audio.stop_music();
                }
            }
            GameMode::GameOver => {
                if input.is_key_pressed(KeyCode::Enter) {
                    self.mode = GameMode::Menu;
                    self.reset_game(world);
                }
            }
        }
    }

    fn draw(&mut self, _world: &World, pixels: &mut [u8]) {
        match self.mode {
            GameMode::Menu => {
                render_text("SEVENX ENGINE", 300, 100, [255, 255, 255, 255], pixels, 800);
                render_text("PRESS SPACE", 320, 300, [200, 200, 200, 255], pixels, 800);
            }
            GameMode::Playing => {
                // Renderiza partículas
                self.particles.render(pixels, 0.0, 0.0, 800, 600);

                // HUD
                let score_text = format!("SCORE: {}", self.score);
                render_text(&score_text, 10, 10, [255, 255, 255, 255], pixels, 800);

                let lives_text = format!("LIVES: {}", self.lives);
                render_text(&lives_text, 10, 30, [255, 100, 100, 255], pixels, 800);
            }
            GameMode::GameOver => {
                render_text("GAME OVER", 320, 250, [255, 0, 0, 255], pixels, 800);
                let score_text = format!("SCORE: {}", self.score);
                render_text(&score_text, 320, 280, [255, 255, 255, 255], pixels, 800);
                render_text("PRESS ENTER", 300, 320, [200, 200, 200, 255], pixels, 800);
            }
        }
    }
}

impl CompleteGame {
    fn start_game(&mut self, _world: &mut World) {
        self.score = 0;
        self.lives = 3;
        println!("🎮 Jogo iniciado!");
    }

    fn update_gameplay(&mut self, dt: f32, input: &InputHandler, world: &mut World) {
        // Controle do jogador usando movimento vetorial (v0.2.7!)
        if let Some(player) = world
            .game_objects
            .iter_mut()
            .find(|obj| obj.object_type == ObjectType::Player && obj.active)
        {
            // Usa get_movement_vector para simplificar (v0.2.7!)
            let (move_x, move_y) = input.get_movement_vector();
            let speed = if input.is_shift_pressed() { 400.0 } else { 200.0 };
            let mut moved = false;

            // Teclado
            if move_x != 0.0 {
                player.transform.translate(move_x * speed * dt, 0.0);
                player.facing_direction = if move_x < 0.0 { Direction::Left } else { Direction::Right };
                moved = true;
            }
            if move_y != 0.0 {
                player.transform.translate(0.0, move_y * speed * dt);
                moved = true;
            }

            // Gamepad
            let axis_x = self.gamepad.get_axis(GamepadAxis::LeftStickX);
            if axis_x.abs() > 0.1 {
                player.transform.translate(axis_x * speed * dt, 0.0);
                moved = true;
            }

            // Pulo usando just_pressed (v0.2.7!)
            if input.is_key_just_pressed(KeyCode::Space) || 
               self.gamepad.is_button_pressed(GamepadButton::South) {
                self.audio.play_sfx("jump");
                println!("🦘 Pulo!");
            }

            player.current_action = if moved {
                PlayerAction::Walk
            } else {
                PlayerAction::Idle
            };

            // Spawna partículas ao andar
            if moved {
                let config = ParticleConfig::new([200, 200, 200, 100])
                    .with_speed(10.0, 30.0)
                    .with_life(0.2, 0.5)
                    .with_size(1.0, 2.0);
                self.particles.emit_stream(
                    player.transform.position.0,
                    player.transform.position.1 + 32.0,
                    5.0,
                    dt,
                    config,
                );
            }
        }

        // Coleta moedas
        let mut collected = Vec::new();
        if let Some(player) = world
            .game_objects
            .iter()
            .find(|obj| obj.object_type == ObjectType::Player)
        {
            if let Some(player_rect) = player.get_collision_rect() {
                for (i, obj) in world.game_objects.iter().enumerate() {
                    if obj.object_type == ObjectType::Coin {
                        if let Some(coin_rect) = obj.get_collision_rect() {
                            if player_rect.intersects(&coin_rect) {
                                collected.push(i);
                                self.score += 10;
                                self.audio.play_sfx("coin");

                                // Explosão de partículas
                                let config = ParticleConfig::sparkle();
                                self.particles.emit_burst(
                                    obj.transform.position.0,
                                    obj.transform.position.1,
                                    20,
                                    config,
                                );

                                self.events.queue(
                                    EventData::new(EventType::CoinCollected)
                                        .with_data("points", "10"),
                                );
                            }
                        }
                    }
                }
            }
        }

        for i in collected.iter().rev() {
            world.game_objects.remove(*i);
        }
    }

    fn reset_game(&mut self, world: &mut World) {
        world.game_objects.clear();
        self.particles.clear();
    }
}

fn main() {
    println!("🎮 SevenX Engine v0.2.7 - Complete Game Demo");
    println!("✨ Demonstração de Todas as Features:");
    println!("   🎵 Sistema de Áudio");
    println!("   📡 Sistema de Eventos");
    println!("   💫 Partículas 2D");
    println!("   🎮 Suporte a Gamepad");
    println!("   🖱️ Input Avançado (v0.2.7!)");
    println!();
    println!("🎯 Controles:");
    println!("   WASD/Setas - Mover");
    println!("   Shift - Correr (v0.2.7!)");
    println!("   Espaço - Pular");
    println!("   Gamepad - Totalmente suportado");
    println!();

    let config = EngineConfig::new()
        .with_title("SevenX Engine v0.2.7 - Complete Game Demo")
        .with_size(800, 600)
        .with_gravity(980.0);

    Engine::with_config(config).run::<CompleteGame>();
}