summaryrefslogtreecommitdiff
path: root/2026/games_submissions/rpc2dot0/src/entity.rs
blob: 3b4200f45064c338c01d7a44c50df42cb8d61340 (plain)
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
use crate::color::EntityColor;
use crate::constants::{DAMPING_FACTOR, MIN_SPEED};
use crate::effects::{PacmanChase, Rogue};
use crate::math::{BoundingCircle, Vec2};

pub trait Update {
    fn update(&mut self, delta_ms: f32);
}

#[derive(Debug, Clone)]
pub struct Entity {
    pub _id: u32,
    pub pos: Vec2,
    pub vel: Vec2,
    pub speed: f32,
    pub color: EntityColor,
    pub radius: f32,
    pub alive: bool,
    pub spawn_time_ms: Option<f32>,
    pub rogue: Option<Rogue>,
    pub pacman_chase: Option<PacmanChase>,
}

impl Entity {
    pub fn new(id: u32, pos: Vec2, vel: Vec2, color: EntityColor, speed: f32, radius: f32) -> Self {
        let mut entity = Self {
            _id: id,
            pos,
            vel,
            speed,
            color,
            radius,
            alive: true,
            spawn_time_ms: None,
            rogue: None,
            pacman_chase: None,
        };
        entity.normalize_velocity();
        entity
    }

    pub fn normalize_velocity(&mut self) {
        let length = self.vel.length();
        if length <= f32::EPSILON {
            self.vel = Vec2::new(1.0, 0.0);
        } else {
            self.vel = self.vel / length * self.speed;
        }
    }

    pub fn apply_jitter(&mut self, jitter: Vec2) {
        self.vel += jitter;
        self.normalize_velocity();
    }

    pub fn dampen_speed(&mut self, max_speed: f32) {
        self.speed = (self.speed * DAMPING_FACTOR).clamp(MIN_SPEED, max_speed);
        self.normalize_velocity();
    }

    pub fn bounds_bounce(&mut self, width: f32, height: f32) {
        let min_bounds = Vec2::splat(self.radius);
        let max_bounds = Vec2::new(width, height) - min_bounds;

        let hit_min = self.pos.cmple(min_bounds);
        let hit_max = self.pos.cmpge(max_bounds);

        self.pos = self.pos.clamp(min_bounds, max_bounds);

        self.vel = Vec2::select(hit_min, self.vel.abs(), self.vel);
        self.vel = Vec2::select(hit_max, -self.vel.abs(), self.vel);
    }
}

impl Update for Entity {
    fn update(&mut self, delta_ms: f32) {
        let dt = delta_ms / 1000.0;
        self.pos += self.vel * dt;
    }
}

impl BoundingCircle for Entity {
    fn center(&self) -> Vec2 {
        self.pos
    }

    fn radius(&self) -> f32 {
        self.radius
    }
}