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::collections::HashMap;
|
||||||
use std::f32::consts::TAU;
|
use std::f32::consts::TAU;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use std::sync::atomic::AtomicBool;
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
use macroquad::prelude::*;
|
use macroquad::prelude::*;
|
||||||
use parry2d::math::Pose;
|
use parry2d::math::Pose;
|
||||||
|
|
@ -16,19 +18,48 @@ use parry2d::shape::Shape;
|
||||||
const VIEW_DIST: f32 = 180.0;
|
const VIEW_DIST: f32 = 180.0;
|
||||||
const BOT_RADIUS: f32 = 16.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 {
|
struct Robot {
|
||||||
pose: Pose,
|
pose: Pose,
|
||||||
alive: bool,
|
alive: AtomicBool,
|
||||||
collider: Ball,
|
collider: Ball,
|
||||||
sensor: Sensor,
|
sensor: Sensor,
|
||||||
team: Color,
|
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 {
|
impl Robot {
|
||||||
fn new(position: Vec2, team: Color) -> Self {
|
fn new(position: Vec2, team: Color) -> Self {
|
||||||
let rand_angle = rand::gen_range(0, 1000) as f32 * TAU / 1000.0;
|
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));
|
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) {
|
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)
|
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 {
|
fn view_end(&self) -> Vec2 {
|
||||||
self.pose.translation + self.ahead() * VIEW_DIST
|
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> {
|
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());
|
let collider = Segment::new(self.pose.translation, self.view_end());
|
||||||
|
|
@ -76,7 +96,7 @@ impl Robot {
|
||||||
struct Food {
|
struct Food {
|
||||||
pose: Pose,
|
pose: Pose,
|
||||||
collider: Ball,
|
collider: Ball,
|
||||||
alive: bool,
|
alive: AtomicBool,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Sensor {
|
enum Sensor {
|
||||||
|
|
@ -86,22 +106,33 @@ enum Sensor {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Food {
|
impl Mortal for Food {
|
||||||
fn new(position: Vec2) -> Self {
|
fn draw(&self) {
|
||||||
let pose:Pose = Pose::from_translation(position.to_array().into());
|
|
||||||
Self { pose, alive: true, collider: Ball::new(BOT_RADIUS) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw(&self) {
|
|
||||||
let tl = self.pose.translation;
|
let tl = self.pose.translation;
|
||||||
draw_circle(tl.x, tl.y, BOT_RADIUS, BLACK);
|
draw_circle(tl.x, tl.y, BOT_RADIUS, BLACK);
|
||||||
draw_circle(tl.x, tl.y, BOT_RADIUS-1.0, GREEN);
|
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)
|
(&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> {
|
fn detect<'a>(&self, things: impl Iterator<Item = &'a Robot>) -> Option<Color> {
|
||||||
things
|
things
|
||||||
.map(|robot| contact(&self.pose, &self.collider, &robot.pose, &robot.collider, 0.0).unwrap().map(|a| (a,robot.team))).flatten()
|
.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;
|
let mut loo = 0;
|
||||||
loop {
|
loop {
|
||||||
let rendered = loo %30 == 0;
|
let rendered = loo %100 == 0;
|
||||||
clear_background(LIGHTGRAY);
|
clear_background(LIGHTGRAY);
|
||||||
|
|
||||||
for food in &mut food{
|
for food in &mut food{
|
||||||
if let Some(team) = food.detect(robots.iter()) {
|
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);
|
score.entry(color_hash(team)).and_modify(|s| *s +=1 ).or_insert(1);
|
||||||
food.alive = false;
|
food.kill();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if rendered { food.draw(); }
|
if rendered { food.draw(); }
|
||||||
// TODO: die upon collision with robot
|
// 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();
|
let mut sensors = Vec::new();
|
||||||
for robot in &*robots {
|
for robot in &*robots {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue