define mortality
This commit is contained in:
parent
3d9f957c4f
commit
596db89430
1 changed files with 57 additions and 26 deletions
|
|
@ -2,6 +2,8 @@ use std::cmp::min;
|
|||
use std::collections::HashMap;
|
||||
use std::f32::consts::TAU;
|
||||
use std::ptr;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use macroquad::prelude::*;
|
||||
use parry2d::math::Pose;
|
||||
|
|
@ -16,19 +18,48 @@ use parry2d::shape::Shape;
|
|||
const VIEW_DIST: f32 = 180.0;
|
||||
const BOT_RADIUS: f32 = 16.0;
|
||||
|
||||
trait Mortal {
|
||||
fn collider(&self) -> (&Pose, &dyn Shape);
|
||||
fn kill(&self);
|
||||
fn living(&self) -> bool;
|
||||
|
||||
fn draw(&self);
|
||||
}
|
||||
|
||||
struct Robot {
|
||||
pose: Pose,
|
||||
alive: bool,
|
||||
alive: AtomicBool,
|
||||
collider: Ball,
|
||||
sensor: Sensor,
|
||||
team: Color,
|
||||
}
|
||||
|
||||
impl Mortal for Robot {
|
||||
fn draw(&self) {
|
||||
let tl = self.pose.translation;
|
||||
let tl2 = self.view_end();
|
||||
draw_circle(tl.x, tl.y, BOT_RADIUS, BLACK);
|
||||
draw_line(tl.x, tl.y, tl2.x, tl2.y, 2.0, BLUE);
|
||||
draw_circle(tl.x, tl.y, BOT_RADIUS-1.0, self.team);
|
||||
}
|
||||
|
||||
fn collider(&self) -> (&Pose, &dyn Shape) {
|
||||
(&self.pose, &self.collider)
|
||||
}
|
||||
|
||||
fn kill (&self) {
|
||||
self.alive.store(false, Ordering::Relaxed);
|
||||
}
|
||||
fn living(&self) -> bool {
|
||||
self.alive.load(Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
impl Robot {
|
||||
fn new(position: Vec2, team: Color) -> Self {
|
||||
let rand_angle = rand::gen_range(0, 1000) as f32 * TAU / 1000.0;
|
||||
let pose:Pose = Pose::from_parts(position.to_array().into(), Rot2::from_angle(rand_angle));
|
||||
Self { pose, alive: true, collider: Ball::new(BOT_RADIUS), sensor: Sensor::None, team}
|
||||
Self { pose, alive: AtomicBool::new(true), collider: Ball::new(BOT_RADIUS), sensor: Sensor::None, team}
|
||||
}
|
||||
|
||||
fn move_step(&mut self, forward: f32, right: f32) {
|
||||
|
|
@ -40,21 +71,10 @@ impl Robot {
|
|||
Vec2::new(self.pose.rotation.re, self.pose.rotation.im)
|
||||
}
|
||||
|
||||
pub fn draw(&self) {
|
||||
let tl = self.pose.translation;
|
||||
let tl2 = self.view_end();
|
||||
draw_circle(tl.x, tl.y, BOT_RADIUS, BLACK);
|
||||
draw_line(tl.x, tl.y, tl2.x, tl2.y, 2.0, BLUE);
|
||||
draw_circle(tl.x, tl.y, BOT_RADIUS-1.0, self.team);
|
||||
}
|
||||
|
||||
fn view_end(&self) -> Vec2 {
|
||||
self.pose.translation + self.ahead() * VIEW_DIST
|
||||
}
|
||||
|
||||
pub fn collider(&self) -> (&Pose, &dyn Shape) {
|
||||
(&self.pose, &self.collider)
|
||||
}
|
||||
|
||||
fn detect<'a>(&self, things: impl Iterator<Item = (&'a Pose, &'a dyn Shape)>) -> Option<f32> {
|
||||
let collider = Segment::new(self.pose.translation, self.view_end());
|
||||
|
|
@ -76,7 +96,7 @@ impl Robot {
|
|||
struct Food {
|
||||
pose: Pose,
|
||||
collider: Ball,
|
||||
alive: bool,
|
||||
alive: AtomicBool,
|
||||
}
|
||||
|
||||
enum Sensor {
|
||||
|
|
@ -86,22 +106,33 @@ enum Sensor {
|
|||
None
|
||||
}
|
||||
|
||||
impl Food {
|
||||
fn new(position: Vec2) -> Self {
|
||||
let pose:Pose = Pose::from_translation(position.to_array().into());
|
||||
Self { pose, alive: true, collider: Ball::new(BOT_RADIUS) }
|
||||
}
|
||||
|
||||
pub fn draw(&self) {
|
||||
impl Mortal for Food {
|
||||
fn draw(&self) {
|
||||
let tl = self.pose.translation;
|
||||
draw_circle(tl.x, tl.y, BOT_RADIUS, BLACK);
|
||||
draw_circle(tl.x, tl.y, BOT_RADIUS-1.0, GREEN);
|
||||
}
|
||||
|
||||
pub fn collider(&self) -> (&Pose, &dyn Shape) {
|
||||
fn collider(&self) -> (&Pose, &dyn Shape) {
|
||||
(&self.pose, &self.collider)
|
||||
}
|
||||
|
||||
fn kill (&self) {
|
||||
self.alive.store(false, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
fn living(&self) -> bool {
|
||||
self.alive.load(Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
impl Food {
|
||||
fn new(position: Vec2) -> Self {
|
||||
let pose:Pose = Pose::from_translation(position.to_array().into());
|
||||
Self { pose, alive: AtomicBool::new(true), collider: Ball::new(BOT_RADIUS) }
|
||||
}
|
||||
|
||||
|
||||
fn detect<'a>(&self, things: impl Iterator<Item = &'a Robot>) -> Option<Color> {
|
||||
things
|
||||
.map(|robot| contact(&self.pose, &self.collider, &robot.pose, &robot.collider, 0.0).unwrap().map(|a| (a,robot.team))).flatten()
|
||||
|
|
@ -140,21 +171,21 @@ async fn run_simulation() -> (i32, i32) {
|
|||
|
||||
let mut loo = 0;
|
||||
loop {
|
||||
let rendered = loo %30 == 0;
|
||||
let rendered = loo %100 == 0;
|
||||
clear_background(LIGHTGRAY);
|
||||
|
||||
for food in &mut food{
|
||||
if let Some(team) = food.detect(robots.iter()) {
|
||||
if food.alive {
|
||||
if food.living() {
|
||||
score.entry(color_hash(team)).and_modify(|s| *s +=1 ).or_insert(1);
|
||||
food.alive = false;
|
||||
food.kill();
|
||||
}
|
||||
}
|
||||
if rendered { food.draw(); }
|
||||
// TODO: die upon collision with robot
|
||||
}
|
||||
|
||||
food = food.into_iter().filter(|f| f.alive).collect(); // remove dead food
|
||||
food = food.into_iter().filter(Mortal::living).collect(); // remove dead food
|
||||
|
||||
let mut sensors = Vec::new();
|
||||
for robot in &*robots {
|
||||
|
|
|
|||
Loading…
Reference in a new issue