use rusting_engine::prelude::*;
const PLAYER_SPEED: f32 = 5.0;
const ENEMY_SPEED: f32 = 1.5;
const ATTACK_REACH: f32 = 1.8;
const HIT_REACH: f32 = 0.9;
const KNOCKBACK: f32 = 3.0;
const ARENA: f32 = 7.0;
fn distance(a: [f32; 3], b: [f32; 3]) -> f32 {
(a[0] - b[0]).hypot(a[2] - b[2])
}
pub fn update(scene: &mut GameScene<'_>, time: &FrameTime) {
if scene.counter_complete("kills") || scene.counter_complete("hits") {
if scene.pressed("attack") {
scene.restart();
}
return;
}
let dt = time.delta.as_secs_f32();
let axis = |scene: &GameScene<'_>, minus: &str, plus: &str| {
f32::from(u8::from(scene.held(plus)))
- f32::from(u8::from(scene.held(minus)))
};
let (dx, dz) = (axis(scene, "left", "right"), axis(scene, "up", "down"));
let length = dx.hypot(dz);
let mut player = scene.object("Player").position();
if length > 0.0 {
let step = PLAYER_SPEED * dt / length;
player[0] = (player[0] + dx * step).clamp(-ARENA, ARENA);
player[2] = (player[2] + dz * step).clamp(-ARENA, ARENA);
scene.object("Player").set_position(player);
}
if scene.pressed("attack") {
scene.flash("Player");
for enemy in scene.in_class("enemy") {
if distance(scene.object(&enemy).position(), player) <= ATTACK_REACH
{
scene.despawn(&enemy);
scene.add_to_counter("kills", 1);
}
}
}
for enemy in scene.in_class("enemy") {
let mut position = scene.object(&enemy).position();
let gap = distance(position, player);
if gap == 0.0 {
continue;
}
let (ux, uz) = (
(player[0] - position[0]) / gap,
(player[2] - position[2]) / gap,
);
let step = (ENEMY_SPEED * dt).min(gap);
position[0] += ux * step;
position[2] += uz * step;
if distance(position, player) < HIT_REACH {
scene.add_to_counter("hits", 1);
scene.add_trauma("Game Camera", 0.4);
position[0] = player[0] - ux * KNOCKBACK;
position[2] = player[2] - uz * KNOCKBACK;
}
scene.object(&enemy).set_position(position);
}
}
rusting_game!(update);