2023-12-31 18:48:35 -08:00

150 lines
3.1 KiB
Rust

use cgmath::{Deg, InnerSpace};
use crate::{
content,
inputstatus::InputStatus,
physics::{util, Physics, ShipHandle},
};
pub trait ShipBehavior
where
Self: Send,
{
fn update_controls(
&mut self,
physics: &mut Physics,
input: &InputStatus,
content: &content::Content,
);
fn get_handle(&self) -> ShipHandle;
}
pub struct Dummy {
_handle: ShipHandle,
}
impl Dummy {
pub fn new(handle: ShipHandle) -> Box<Self> {
Box::new(Self { _handle: handle })
}
}
impl ShipBehavior for Dummy {
fn update_controls(
&mut self,
_physics: &mut Physics,
_input: &InputStatus,
_content: &content::Content,
) {
}
fn get_handle(&self) -> ShipHandle {
return self._handle;
}
}
pub struct Player {
handle: ShipHandle,
}
impl Player {
pub fn new(handle: ShipHandle) -> Box<Self> {
Box::new(Self { handle })
}
}
impl ShipBehavior for Player {
fn update_controls(
&mut self,
physics: &mut Physics,
input: &InputStatus,
_content: &content::Content,
) {
let s = physics.get_ship_mut(&self.handle).unwrap();
s.controls.left = input.key_left;
s.controls.right = input.key_right;
s.controls.guns = input.key_guns;
s.controls.thrust = input.key_thrust;
}
fn get_handle(&self) -> ShipHandle {
return self.handle;
}
}
pub struct Point {
handle: ShipHandle,
}
impl Point {
pub fn new(handle: ShipHandle) -> Box<Self> {
Box::new(Self { handle })
}
}
impl ShipBehavior for Point {
fn update_controls(
&mut self,
physics: &mut Physics,
_input: &InputStatus,
content: &content::Content,
) {
// Turn off all controls
let s = physics.get_ship_mut(&self.handle).unwrap();
s.controls.left = false;
s.controls.right = false;
s.controls.guns = false;
s.controls.thrust = false;
let (my_s, my_r) = physics.get_ship_body(&self.handle).unwrap();
let my_position = util::rigidbody_position(my_r);
let my_rotation = util::rigidbody_rotation(my_r);
let my_angvel = my_r.angvel();
let my_faction = content.get_faction(my_s.faction);
// Iterate all possible targets
let mut it = physics
.iter_ship_body()
.filter(|(s, _)| match my_faction.relationships[&s.faction] {
content::Relationship::Hostile => true,
_ => false,
})
.map(|(_, r)| r);
// Find the closest target
let mut closest_enemy_position = match it.next() {
Some(c) => util::rigidbody_position(c),
None => return, // Do nothing if no targets are available
};
let mut d = (my_position - closest_enemy_position).magnitude();
for r in it {
let p = util::rigidbody_position(r);
let new_d = (my_position - p).magnitude();
if new_d < d {
d = new_d;
closest_enemy_position = p;
}
}
let angle_delta: Deg<f32> = (my_rotation)
.angle(closest_enemy_position - my_position)
.into();
let s = physics.get_ship_mut(&self.handle).unwrap();
s.controls.left = false;
s.controls.right = false;
if angle_delta < Deg(0.0) && my_angvel > -0.3 {
s.controls.right = true;
} else if angle_delta > Deg(0.0) && my_angvel < 0.3 {
s.controls.left = true;
}
s.controls.guns = true;
s.controls.thrust = false;
}
fn get_handle(&self) -> ShipHandle {
return self.handle;
}
}