use sevenx_engine::*;
struct UltimateGame {
player_pos: Vec3,
player_rot: f32,
player_vel: Vec3,
player_health: f32,
player_ammo: i32,
camera_pitch: f32,
mouse_sensitivity: f32,
enemies: Vec<Enemy>,
enemy_spawn_timer: f32,
shoot_cooldown: f32,
bullets: Vec<Bullet>,
explosions: Vec<Explosion>,
world_meshes: Vec<Mesh3D>,
collectibles: Vec<Collectible>,
particle_systems: Vec<ParticleSystem>,
score: i32,
wave: i32,
kills: i32,
shake_intensity: f32,
flash_alpha: f32,
game_time: f32,
slow_motion: f32,
}
struct Enemy {
pos: Vec3,
vel: Vec3,
health: f32,
attack_timer: f32,
mesh: Mesh3D,
}
struct Bullet {
pos: Vec3,
vel: Vec3,
lifetime: f32,
}
struct Explosion {
pos: Vec3,
time: f32,
radius: f32,
}
struct Collectible {
pos: Vec3,
rotation: f32,
ctype: CollectibleType,
}
#[derive(Clone, Copy)]
enum CollectibleType {
Health,
Ammo,
PowerUp,
}
impl GameState for UltimateGame {
fn new(engine: &mut Engine) -> Self {
println!("🎮 ULTIMATE SHOWCASE - Carregando...");
engine.camera3d.position = Vec3::new(0.0, 1.8, 0.0);
let mut world_meshes = Vec::new();
let mut floor = Mesh3D::grid(50, 50, 2.0);
floor.set_color(30, 30, 40, 255);
world_meshes.push(floor);
for i in 0..20 {
let angle = (i as f32) * std::f32::consts::PI * 2.0 / 20.0;
let x = angle.cos() * 40.0;
let z = angle.sin() * 40.0;
let mut wall = Mesh3D::cube();
wall.translate(x, 3.0, z);
wall.scale(2.0, 6.0, 2.0);
wall.set_color(60, 60, 80, 255);
world_meshes.push(wall);
}
for i in 0..8 {
let angle = (i as f32) * std::f32::consts::PI * 2.0 / 8.0;
let x = angle.cos() * 20.0;
let z = angle.sin() * 20.0;
let mut platform = Mesh3D::cylinder(1.5, 0.5, 16);
platform.translate(x, 2.0, z);
platform.set_color(80, 100, 120, 255);
world_meshes.push(platform);
}
Self {
player_pos: Vec3::new(0.0, 1.8, 0.0),
player_rot: 0.0,
player_vel: Vec3::new(0.0, 0.0, 0.0),
player_health: 100.0,
player_ammo: 100,
camera_pitch: 0.0,
mouse_sensitivity: 0.002,
enemies: Vec::new(),
enemy_spawn_timer: 0.0,
shoot_cooldown: 0.0,
bullets: Vec::new(),
explosions: Vec::new(),
world_meshes,
collectibles: Vec::new(),
particle_systems: Vec::new(),
score: 0,
wave: 1,
kills: 0,
shake_intensity: 0.0,
flash_alpha: 0.0,
game_time: 0.0,
slow_motion: 1.0,
}
}
fn update(&mut self, engine: &mut Engine) {
let dt = engine.delta_time * self.slow_motion;
self.game_time += dt;
let (mdx, mdy) = engine.input.get_mouse_delta();
self.player_rot -= mdx as f32 * self.mouse_sensitivity;
self.camera_pitch -= mdy as f32 * self.mouse_sensitivity;
self.camera_pitch = self.camera_pitch.clamp(-1.5, 1.5);
let mut move_dir = Vec3::new(0.0, 0.0, 0.0);
let speed = if engine.input.is_shift_pressed() { 12.0 } else { 6.0 };
if engine.input.is_key_pressed(Key::W) {
move_dir.z -= 1.0;
}
if engine.input.is_key_pressed(Key::S) {
move_dir.z += 1.0;
}
if engine.input.is_key_pressed(Key::A) {
move_dir.x -= 1.0;
}
if engine.input.is_key_pressed(Key::D) {
move_dir.x += 1.0;
}
if move_dir.length() > 0.0 {
let rotated_x = move_dir.x * self.player_rot.cos() - move_dir.z * self.player_rot.sin();
let rotated_z = move_dir.x * self.player_rot.sin() + move_dir.z * self.player_rot.cos();
self.player_vel.x = rotated_x * speed;
self.player_vel.z = rotated_z * speed;
} else {
self.player_vel.x *= 0.8;
self.player_vel.z *= 0.8;
}
if engine.input.is_key_just_pressed(Key::Space) && self.player_pos.y <= 1.81 {
self.player_vel.y = 8.0;
}
self.player_vel.y -= 20.0 * dt;
self.player_pos.x += self.player_vel.x * dt;
self.player_pos.y += self.player_vel.y * dt;
self.player_pos.z += self.player_vel.z * dt;
if self.player_pos.y < 1.8 {
self.player_pos.y = 1.8;
self.player_vel.y = 0.0;
}
let max_dist = 38.0;
if self.player_pos.x.abs() > max_dist {
self.player_pos.x = self.player_pos.x.signum() * max_dist;
}
if self.player_pos.z.abs() > max_dist {
self.player_pos.z = self.player_pos.z.signum() * max_dist;
}
engine.camera3d.position = self.player_pos;
engine.camera3d.rotation.x = self.camera_pitch;
engine.camera3d.rotation.y = self.player_rot;
self.shoot_cooldown -= dt;
if engine.input.is_mouse_button_pressed(MouseBtn::Left) && self.shoot_cooldown <= 0.0 && self.player_ammo > 0 {
self.shoot(engine);
self.shoot_cooldown = 0.1;
self.player_ammo -= 1;
self.shake_intensity = 0.3;
self.flash_alpha = 0.5;
}
if engine.input.is_key_just_pressed(Key::E) {
self.slow_motion = if self.slow_motion > 0.5 { 0.3 } else { 1.0 };
}
self.enemy_spawn_timer -= dt;
if self.enemy_spawn_timer <= 0.0 {
self.spawn_enemy();
self.enemy_spawn_timer = 2.0 / (self.wave as f32);
}
for enemy in &mut self.enemies {
let dir = (self.player_pos - enemy.pos).normalize();
enemy.vel = dir * 3.0;
enemy.pos = enemy.pos + enemy.vel * dt;
enemy.attack_timer -= dt;
if (enemy.pos - self.player_pos).length() < 2.0 && enemy.attack_timer <= 0.0 {
self.player_health -= 10.0;
self.shake_intensity = 0.5;
self.flash_alpha = 0.8;
enemy.attack_timer = 1.0;
}
}
self.bullets.retain_mut(|bullet| {
bullet.pos = bullet.pos + bullet.vel * dt;
bullet.lifetime -= dt;
if bullet.lifetime <= 0.0 {
return false;
}
for (i, enemy) in self.enemies.iter_mut().enumerate() {
if (bullet.pos - enemy.pos).length() < 1.5 {
enemy.health -= 25.0;
if enemy.health <= 0.0 {
self.create_explosion(enemy.pos);
self.score += 100;
self.kills += 1;
if rand::random::<f32>() < 0.3 {
self.spawn_collectible(enemy.pos);
}
}
return false;
}
}
true
});
self.enemies.retain(|e| e.health > 0.0);
self.explosions.retain_mut(|exp| {
exp.time += dt * 3.0;
exp.time < 1.0
});
for col in &mut self.collectibles {
col.rotation += dt * 2.0;
col.pos.y = 2.0 + (self.game_time * 2.0 + col.pos.x).sin() * 0.3;
if (col.pos - self.player_pos).length() < 2.0 {
match col.ctype {
CollectibleType::Health => {
self.player_health = (self.player_health + 30.0).min(100.0);
}
CollectibleType::Ammo => {
self.player_ammo += 30;
}
CollectibleType::PowerUp => {
self.slow_motion = 0.3;
}
}
}
}
self.collectibles.retain(|c| (c.pos - self.player_pos).length() > 2.0);
self.shake_intensity *= 0.9;
self.flash_alpha *= 0.9;
if self.enemies.is_empty() && self.kills >= self.wave * 5 {
self.wave += 1;
self.score += self.wave * 500;
}
if self.player_health <= 0.0 {
println!("💀 GAME OVER! Score: {} | Kills: {} | Wave: {}", self.score, self.kills, self.wave);
self.player_health = 100.0;
self.player_ammo = 100;
self.score = 0;
self.kills = 0;
self.wave = 1;
self.enemies.clear();
}
}
fn draw(&mut self, engine: &mut Engine) {
engine.renderer.clear(10, 10, 15);
if self.shake_intensity > 0.01 {
let shake_x = (rand::random::<f32>() - 0.5) * self.shake_intensity * 10.0;
let shake_y = (rand::random::<f32>() - 0.5) * self.shake_intensity * 10.0;
engine.camera3d.position.x += shake_x;
engine.camera3d.position.y += shake_y;
}
for mesh in &self.world_meshes {
engine.renderer3d.render_mesh(&mesh, &engine.camera3d);
}
for enemy in &self.enemies {
engine.renderer3d.render_mesh(&enemy.mesh, &engine.camera3d);
}
for bullet in &self.bullets {
let mut bullet_mesh = Mesh3D::sphere(0.2, 8, 8);
bullet_mesh.translate(bullet.pos.x, bullet.pos.y, bullet.pos.z);
bullet_mesh.set_color(255, 255, 0, 255);
engine.renderer3d.render_mesh(&bullet_mesh, &engine.camera3d);
}
for exp in &self.explosions {
let size = exp.radius * exp.time;
let alpha = ((1.0 - exp.time) * 255.0) as u8;
let mut exp_mesh = Mesh3D::sphere(size, 12, 12);
exp_mesh.translate(exp.pos.x, exp.pos.y, exp.pos.z);
exp_mesh.set_color(255, 100, 0, alpha);
engine.renderer3d.render_mesh(&exp_mesh, &engine.camera3d);
}
for col in &self.collectibles {
let (r, g, b) = match col.ctype {
CollectibleType::Health => (0, 255, 0),
CollectibleType::Ammo => (255, 255, 0),
CollectibleType::PowerUp => (255, 0, 255),
};
let mut col_mesh = Mesh3D::sphere(0.5, 12, 12);
col_mesh.translate(col.pos.x, col.pos.y, col.pos.z);
col_mesh.rotate_y(col.rotation);
col_mesh.set_color(r, g, b, 255);
engine.renderer3d.render_mesh(&col_mesh, &engine.camera3d);
}
if self.flash_alpha > 0.01 {
let alpha = (self.flash_alpha * 100.0) as u8;
engine.renderer.draw_filled_rect(0, 0, 800, 600, 255, 0, 0, alpha);
}
self.draw_hud(engine);
let cx = 400;
let cy = 300;
engine.renderer.draw_line(cx - 10, cy, cx + 10, cy, 255, 255, 255, 200);
engine.renderer.draw_line(cx, cy - 10, cx, cy + 10, 255, 255, 255, 200);
}
}
impl UltimateGame {
fn shoot(&mut self, _engine: &mut Engine) {
let dir_x = self.camera_pitch.cos() * self.player_rot.sin();
let dir_y = -self.camera_pitch.sin();
let dir_z = -self.camera_pitch.cos() * self.player_rot.cos();
let bullet = Bullet {
pos: self.player_pos + Vec3::new(dir_x, dir_y, dir_z) * 2.0,
vel: Vec3::new(dir_x, dir_y, dir_z) * 50.0,
lifetime: 3.0,
};
self.bullets.push(bullet);
}
fn spawn_enemy(&mut self) {
let angle = rand::random::<f32>() * std::f32::consts::PI * 2.0;
let dist = 30.0;
let x = angle.cos() * dist;
let z = angle.sin() * dist;
let mut mesh = Mesh3D::cube();
mesh.translate(x, 1.0, z);
mesh.scale(1.0, 2.0, 1.0);
mesh.set_color(255, 50, 50, 255);
self.enemies.push(Enemy {
pos: Vec3::new(x, 1.0, z),
vel: Vec3::new(0.0, 0.0, 0.0),
health: 50.0 + (self.wave as f32) * 10.0,
attack_timer: 0.0,
mesh,
});
}
fn create_explosion(&mut self, pos: Vec3) {
self.explosions.push(Explosion {
pos,
time: 0.0,
radius: 3.0,
});
self.shake_intensity = 0.8;
}
fn spawn_collectible(&mut self, pos: Vec3) {
let ctype = match rand::random::<u32>() % 3 {
0 => CollectibleType::Health,
1 => CollectibleType::Ammo,
_ => CollectibleType::PowerUp,
};
self.collectibles.push(Collectible {
pos,
rotation: 0.0,
ctype,
});
}
fn draw_hud(&self, engine: &mut Engine) {
let health_width = (self.player_health * 2.0) as i32;
engine.renderer.draw_filled_rect(10, 10, 204, 24, 0, 0, 0, 150);
engine.renderer.draw_filled_rect(12, 12, health_width, 20, 255, 0, 0, 255);
engine.renderer.draw_filled_rect(10, 40, 204, 24, 0, 0, 0, 150);
let ammo_text = format!("AMMO: {}", self.player_ammo);
engine.renderer.draw_text(&ammo_text, 15, 45, 255, 255, 0, 255);
let score_text = format!("SCORE: {}", self.score);
engine.renderer.draw_text(&score_text, 600, 10, 255, 255, 255, 255);
let wave_text = format!("WAVE: {}", self.wave);
engine.renderer.draw_text(&wave_text, 600, 30, 0, 255, 255, 255);
let kills_text = format!("KILLS: {}", self.kills);
engine.renderer.draw_text(&kills_text, 600, 50, 255, 100, 100, 255);
let enemies_text = format!("ENEMIES: {}", self.enemies.len());
engine.renderer.draw_text(&enemies_text, 600, 70, 255, 0, 0, 255);
if self.slow_motion < 0.5 {
engine.renderer.draw_text("SLOW-MO", 350, 550, 255, 0, 255, 255);
}
}
}
fn main() {
let config = EngineConfig {
title: "🎮 ULTIMATE SHOWCASE - SevenX Engine".to_string(),
width: 800,
height: 600,
target_fps: 60,
..Default::default()
};
let mut engine = Engine::new(config);
engine.run::<UltimateGame>();
}