1use std::{
12 fmt::Debug,
13 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
14};
15
16use sdl2::rect::Point;
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
23pub enum Direction {
24 North,
26 South,
28 East,
30 West,
32}
33
34#[allow(clippy::enum_glob_use)]
35impl Direction {
36 #[must_use]
38 pub fn flipped(self) -> Self {
39 self.flip_x().flip_y()
40 }
41
42 #[must_use]
44 pub fn flip_x(self) -> Self {
45 use Direction::*;
46 match self {
47 East => West,
48 West => East,
49 v => v,
50 }
51 }
52
53 #[must_use]
55 pub fn flip_y(self) -> Self {
56 use Direction::*;
57 match self {
58 North => South,
59 South => North,
60 v => v,
61 }
62 }
63}
64
65impl Neg for Direction {
67 type Output = Self;
68
69 fn neg(self) -> Self::Output {
70 self.flipped()
71 }
72}
73
74#[allow(clippy::enum_glob_use)]
75impl From<Direction> for Vec2 {
76 fn from(v: Direction) -> Self {
77 use Direction::*;
78 match v {
79 North => (0.0, -1.0).into(),
80 South => (0.0, 1.0).into(),
81 East => (1.0, 0.0).into(),
82 West => (-1.0, 0.0).into(),
83 }
84 }
85}
86
87#[allow(clippy::enum_glob_use)]
88impl From<Direction> for Vec2Int {
89 fn from(v: Direction) -> Self {
90 use Direction::*;
91 match v {
92 North => (0, -1).into(),
93 South => (0, 1).into(),
94 East => (1, 0).into(),
95 West => (-1, 0).into(),
96 }
97 }
98}
99
100impl From<Point> for Vec2 {
101 fn from(p: Point) -> Self {
102 let x: (i32, i32) = p.into();
103 x.into()
104 }
105}
106
107impl From<Point> for Vec2Int {
108 fn from(p: Point) -> Self {
109 let x: (i32, i32) = p.into();
110 x.into()
111 }
112}
113
114impl Mul<f32> for Direction {
115 type Output = Vec2;
116
117 fn mul(self, rhs: f32) -> Self::Output {
118 Vec2::from(self) * rhs
119 }
120}
121
122impl Mul<i32> for Direction {
123 type Output = Vec2Int;
124
125 fn mul(self, rhs: i32) -> Self::Output {
126 Vec2Int::from(self) * rhs
127 }
128}
129
130#[derive(Clone, Copy, Default, PartialEq)]
133pub struct Vec2 {
134 pub x: f32,
136 pub y: f32,
138}
139
140impl Debug for Vec2 {
141 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
142 f.debug_tuple("Vec2").field(&self.x).field(&self.y).finish()
143 }
144}
145
146impl Vec2 {
147 #[must_use]
151 pub const fn new(x: f32, y: f32) -> Vec2 {
152 Self { x, y }
153 }
154
155 #[must_use]
159 pub fn sq_magnitude(self) -> f32 {
160 self.x * self.x + self.y * self.y
161 }
162
163 #[must_use]
165 pub fn magnitude(self) -> f32 {
166 self.sq_magnitude().sqrt()
167 }
168
169 #[must_use]
173 pub fn sq_dist(self, rhs: Self) -> f32 {
174 (self - rhs).sq_magnitude()
175 }
176
177 #[must_use]
179 pub fn dist(self, rhs: Self) -> f32 {
180 (self - rhs).magnitude()
181 }
182
183 #[must_use]
185 pub fn normalized(self) -> Self {
186 self / self.magnitude()
187 }
188
189 #[must_use]
193 pub fn rounded(self) -> Vec2Int {
194 #[allow(clippy::cast_possible_truncation)]
195 Vec2Int {
196 x: self.x as i32,
197 y: self.y as i32,
198 }
199 }
200}
201
202impl From<(i32, i32)> for Vec2 {
203 fn from(v: (i32, i32)) -> Self {
204 Vec2Int::from(v).to_f32()
205 }
206}
207
208impl From<(f32, f32)> for Vec2 {
209 fn from(v: (f32, f32)) -> Self {
210 Self { x: v.0, y: v.1 }
211 }
212}
213
214impl From<Vec2> for (f32, f32) {
215 fn from(v: Vec2) -> Self {
216 (v.x, v.y)
217 }
218}
219
220impl PartialEq<(i32, i32)> for Vec2 {
221 fn eq(&self, other: &(i32, i32)) -> bool {
222 self == &Self::from(*other)
223 }
224}
225
226impl PartialEq<(f32, f32)> for Vec2 {
227 fn eq(&self, other: &(f32, f32)) -> bool {
228 self == &Self::from(*other)
229 }
230}
231
232impl Neg for Vec2 {
234 type Output = Self;
235
236 fn neg(self) -> Self::Output {
237 self * -1.0
238 }
239}
240
241impl Add for Vec2 {
242 type Output = Self;
243
244 fn add(self, rhs: Self) -> Self::Output {
245 Self {
246 x: self.x + rhs.x,
247 y: self.y + rhs.y,
248 }
249 }
250}
251
252impl Add<Direction> for Vec2 {
253 type Output = Self;
254
255 fn add(self, rhs: Direction) -> Self::Output {
256 self + Self::from(rhs)
257 }
258}
259
260impl<T> AddAssign<T> for Vec2
261where
262 Vec2: Add<T, Output = Self>,
263{
264 fn add_assign(&mut self, rhs: T) {
265 *self = *self + rhs;
266 }
267}
268
269impl<T> Sub<T> for Vec2
270where
271 Vec2: Add<T, Output = Self>,
272{
273 type Output = Self;
274
275 fn sub(self, rhs: T) -> Self::Output {
276 -(-self + rhs)
277 }
278}
279
280impl<T> SubAssign<T> for Vec2
281where
282 Vec2: Sub<T, Output = Self>,
283{
284 fn sub_assign(&mut self, rhs: T) {
285 *self = *self - rhs;
286 }
287}
288
289impl Mul<f32> for Vec2 {
290 type Output = Self;
291
292 fn mul(self, rhs: f32) -> Self::Output {
293 Self {
294 x: self.x * rhs,
295 y: self.y * rhs,
296 }
297 }
298}
299
300impl Div<f32> for Vec2 {
301 type Output = Self;
302
303 fn div(self, rhs: f32) -> Self::Output {
304 Self {
305 x: self.x / rhs,
306 y: self.y / rhs,
307 }
308 }
309}
310
311impl MulAssign<f32> for Vec2 {
312 fn mul_assign(&mut self, rhs: f32) {
313 *self = *self * rhs;
314 }
315}
316
317impl DivAssign<f32> for Vec2 {
318 fn div_assign(&mut self, rhs: f32) {
319 *self = *self / rhs;
320 }
321}
322
323#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
326pub struct Vec2Int {
327 pub x: i32,
329 pub y: i32,
331}
332
333impl Debug for Vec2Int {
334 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
335 f.debug_tuple("Vec2Int")
336 .field(&self.x)
337 .field(&self.y)
338 .finish()
339 }
340}
341
342impl Vec2Int {
343 #[must_use]
347 pub const fn new(x: i32, y: i32) -> Vec2Int {
348 Self { x, y }
349 }
350
351 #[must_use]
355 pub fn sq_magnitude(self) -> i32 {
356 self.x * self.x + self.y * self.y
357 }
358
359 #[must_use]
361 pub fn magnitude(self) -> f32 {
362 #[allow(clippy::cast_precision_loss)]
363 (self.sq_magnitude() as f32).sqrt()
364 }
365
366 #[must_use]
370 pub fn sq_dist(self, rhs: Self) -> i32 {
371 (self - rhs).sq_magnitude()
372 }
373
374 #[must_use]
376 pub fn dist(self, rhs: Self) -> f32 {
377 (self - rhs).magnitude()
378 }
379
380 #[must_use]
384 pub fn to_f32(self) -> Vec2 {
385 #[allow(clippy::cast_precision_loss)]
386 Vec2 {
387 x: self.x as f32,
388 y: self.y as f32,
389 }
390 }
391}
392
393impl From<(i32, i32)> for Vec2Int {
394 fn from(v: (i32, i32)) -> Self {
395 Self { x: v.0, y: v.1 }
396 }
397}
398
399impl From<Vec2Int> for (i32, i32) {
400 fn from(v: Vec2Int) -> Self {
401 (v.x, v.y)
402 }
403}
404
405impl PartialEq<(i32, i32)> for Vec2Int {
406 fn eq(&self, other: &(i32, i32)) -> bool {
407 self == &Self::from(*other)
408 }
409}
410
411impl Neg for Vec2Int {
413 type Output = Self;
414
415 fn neg(self) -> Self::Output {
416 self * -1
417 }
418}
419
420impl Add for Vec2Int {
421 type Output = Self;
422
423 fn add(self, rhs: Self) -> Self::Output {
424 Self {
425 x: self.x + rhs.x,
426 y: self.y + rhs.y,
427 }
428 }
429}
430
431impl Add<Direction> for Vec2Int {
432 type Output = Self;
433
434 fn add(self, rhs: Direction) -> Self::Output {
435 self + Self::from(rhs)
436 }
437}
438
439impl<T> AddAssign<T> for Vec2Int
440where
441 Vec2Int: Add<T, Output = Self>,
442{
443 fn add_assign(&mut self, rhs: T) {
444 *self = *self + rhs;
445 }
446}
447
448impl<T> Sub<T> for Vec2Int
449where
450 Vec2Int: Add<T, Output = Self>,
451{
452 type Output = Self;
453
454 fn sub(self, rhs: T) -> Self::Output {
455 -(-self + rhs)
456 }
457}
458
459impl<T> SubAssign<T> for Vec2Int
460where
461 Vec2Int: Sub<T, Output = Self>,
462{
463 fn sub_assign(&mut self, rhs: T) {
464 *self = *self - rhs;
465 }
466}
467
468impl Mul<i32> for Vec2Int {
469 type Output = Self;
470
471 fn mul(self, rhs: i32) -> Self::Output {
472 Self {
473 x: self.x * rhs,
474 y: self.y * rhs,
475 }
476 }
477}
478
479impl Div<i32> for Vec2Int {
480 type Output = Self;
481
482 fn div(self, rhs: i32) -> Self::Output {
483 Self {
484 x: self.x / rhs,
485 y: self.y / rhs,
486 }
487 }
488}
489
490impl MulAssign<i32> for Vec2Int {
491 fn mul_assign(&mut self, rhs: i32) {
492 *self = *self * rhs;
493 }
494}
495
496impl DivAssign<i32> for Vec2Int {
497 fn div_assign(&mut self, rhs: i32) {
498 *self = *self / rhs;
499 }
500}