1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use ggez::{
graphics,
graphics::DrawParam,
nalgebra::{Point2, Vector2},
Context, GameResult,
};
const DIMENSION_RATIO: (u8, u8) = (2, 1);
pub struct Vehicle {
pub size: f32,
pub max_speed: f32,
pub max_steering_force: f32,
pub pos: Point2<f32>,
pub angle: f32,
vel: Vector2<f32>,
acc: Vector2<f32>,
}
impl Vehicle {
pub fn new(
size: f32,
max_speed: f32,
max_steering_force: f32,
pos: Point2<f32>,
angle: f32,
) -> Self {
Self {
size,
max_speed,
max_steering_force,
acc: Vector2::new(0.0, 0.0),
vel: Vector2::new(0.0, 0.0),
angle,
pos,
}
}
pub fn seek(&mut self, target: &Point2<f32>) {
let mut desired = target - self.pos;
desired = desired.normalize() * self.max_speed;
let mut steering_force = desired - self.vel;
if steering_force.magnitude() > self.max_steering_force {
steering_force = steering_force.normalize() * self.max_steering_force;
}
self.acc += steering_force;
}
pub fn update(&mut self) {
if self.vel.magnitude() > self.max_speed {
self.vel = self.vel.normalize() * self.max_speed;
}
self.vel += self.acc;
self.angle = self.vel.y.atan2(self.vel.x);
self.pos += self.vel;
self.acc *= 0.0;
}
pub fn draw(&self, ctx: &mut Context) -> GameResult {
let dimensions = (
DIMENSION_RATIO.0 as f32 * self.size,
DIMENSION_RATIO.1 as f32 * self.size,
);
let triangle = graphics::Mesh::new_polygon(
ctx,
graphics::DrawMode::fill(),
&[
Point2::new(dimensions.0 * 0.5, 0.0),
Point2::new(-dimensions.0 * 0.5, dimensions.1 * 0.5),
Point2::new(-dimensions.0 * 0.5, -dimensions.1 * 0.5),
],
[0.0, 1.0, 0.0, 1.0].into(),
)?;
let mut parameters = DrawParam::new();
parameters = parameters.dest(self.pos);
parameters = parameters.rotation(self.angle);
graphics::draw(ctx, &triangle, parameters)?;
Ok(())
}
}