spacorium/src/ships/player.rs
2025-11-16 13:36:11 +05:00

129 lines
3.6 KiB
Rust

use crate::{
collision::Collider,
damagable::Damagable,
projectile::{ProjectileSprite, spawn_projectile},
ships::Factions,
velocity::Velocity,
};
use bevy::prelude::*;
use rand::random_range;
#[derive(Component)]
#[require(Velocity)]
pub struct PlayerMovement {
acceleration: f32,
deceleration: f32,
stop_epsilon: f32,
}
#[derive(Component)]
pub struct PlayerGun {
shoot_timer: Timer,
damage: u32,
}
pub fn spawn_player(commands: &mut Commands, sprite: Handle<Image>, at: Vec2) {
commands.spawn((
PlayerMovement {
acceleration: 100.,
deceleration: 300.,
stop_epsilon: 50.,
},
PlayerGun {
shoot_timer: Timer::from_seconds(0.2, TimerMode::Once),
damage: 1,
},
Collider::new(8.),
Sprite::from(sprite),
Transform::from_xyz(at.x, at.y, 0.),
Factions::PlayerFaction,
Damagable::new(15),
));
}
pub(super) fn player_movement_system(
time: Res<Time>,
keyboard_input: Res<ButtonInput<KeyCode>>,
query: Single<(&mut Velocity, &PlayerMovement)>,
) {
let (mut velocity, player) = query.into_inner();
let mut movement_factor = 0.0;
let mut rotation_factor = 0.0;
if keyboard_input.pressed(KeyCode::ArrowLeft) {
rotation_factor += 1.0;
}
if keyboard_input.pressed(KeyCode::ArrowRight) {
rotation_factor -= 1.0;
}
if keyboard_input.pressed(KeyCode::ArrowUp) {
movement_factor += 1.0;
}
if keyboard_input.pressed(KeyCode::ArrowDown) {
movement_factor -= 1.0;
}
if movement_factor > 0. {
if velocity.linear_speed >= 0. {
velocity.linear_speed = (velocity.linear_speed
+ player.acceleration * time.delta_secs())
.clamp(-velocity.max_linear_speed, velocity.max_linear_speed);
} else {
velocity.linear_speed = (velocity.linear_speed
+ player.deceleration * time.delta_secs())
.clamp(-velocity.max_linear_speed, velocity.max_linear_speed);
if velocity.linear_speed > -player.stop_epsilon {
velocity.linear_speed = 0.;
}
}
}
if movement_factor < 0. {
if velocity.linear_speed <= 0. {
velocity.linear_speed = (velocity.linear_speed
- player.acceleration * time.delta_secs())
.clamp(-velocity.max_linear_speed, velocity.max_linear_speed);
} else {
velocity.linear_speed = (velocity.linear_speed
- player.deceleration * time.delta_secs())
.clamp(-velocity.max_linear_speed, velocity.max_linear_speed);
if velocity.linear_speed < player.stop_epsilon {
velocity.linear_speed = 0.;
}
}
}
velocity.rotation_speed = rotation_factor * velocity.max_rotation_speed;
}
pub fn player_shooting_system(
mut commands: Commands,
time: Res<Time>,
keyboard_input: Res<ButtonInput<KeyCode>>,
projectile_sprite: Res<ProjectileSprite>,
query: Single<(&mut PlayerGun, &Transform)>,
) {
let (mut gun, transform) = query.into_inner();
gun.shoot_timer.tick(time.delta());
if gun.shoot_timer.is_finished() == false || keyboard_input.pressed(KeyCode::Space) == false {
return;
}
let five_degrees = f32::to_radians(5.);
let mut bullet_transform = transform.clone();
bullet_transform.rotate_z(random_range(-five_degrees..five_degrees));
spawn_projectile(
&mut commands,
projectile_sprite,
bullet_transform,
gun.damage,
Factions::PlayerFaction,
);
gun.shoot_timer.reset();
}