use crate::constants::*; use macroquad::color::*; use macroquad::math::Vec2; use macroquad::prelude::Image; use macroquad::rand::RandomRange; use std::f32::consts::PI; #[derive(Debug)] pub(crate) struct Ant { pos: Vec2, dir: f32, } impl Ant { pub(crate) fn init(num: i32) -> Vec { let dir_steps = PI * 2. / num as f32; (0..num) .into_iter() .map(|n| Ant { pos: Vec2::new((MAP_WIDTH / 2) as f32, (MAP_HEIGHT / 2) as f32), dir: n as f32 * dir_steps, }) .collect() } pub(crate) fn walk(&mut self, frame_time: f32, trail_map: &mut Image) { self.sense(trail_map); let new_dir = PI / 8. * RandomRange::gen_range(-2, 2) as f32; self.dir += new_dir; if self.dir > 2. * PI { self.dir -= 2. * PI; } let acceleration = Vec2::new(self.dir.sin(), -self.dir.cos()); self.pos += acceleration * ANT_SPEED * frame_time; // if we are out of the map, turn around 180 degrees (or pi in radian) if self.pos.x < 0.0 || self.pos.x >= (MAP_WIDTH - 1) as f32 || self.pos.y < 0.0 || self.pos.y >= (MAP_HEIGHT - 1) as f32 { self.dir += PI; } self.pos.x = self.pos.x.clamp(0., (MAP_WIDTH - 1) as f32); self.pos.y = self.pos.y.clamp(0., (MAP_HEIGHT - 1) as f32); } fn sense(&self, trail_map: &mut Image) { trail_map.set_pixel(self.dir.sin() as u32, -self.dir.cos() as u32, YELLOW); trail_map.set_pixel(self.dir.sin() as u32, -self.dir.cos() as u32, YELLOW); trail_map.set_pixel(self.dir.sin() as u32, -self.dir.cos() as u32, YELLOW); } // TODO: change color over time or based on other factors pub(crate) fn draw(&self, trail_map: &mut Image) { let radius: i32 = 3; for x in -radius..radius { for y in -radius..radius { let x = (self.pos.x as i32 + x) as u32; let y = (self.pos.y as i32 + y) as u32; if x < (MAP_WIDTH - 1) && y < (MAP_HEIGHT - 1) { trail_map.set_pixel(x, y, RED); } } } } }