pop done
This commit is contained in:
parent
1f0b6e06e0
commit
666c9a8b8e
|
@ -89,7 +89,7 @@ impl Asteroid {
|
||||||
AsteroidSize::Medium => 1.2,
|
AsteroidSize::Medium => 1.2,
|
||||||
AsteroidSize::Small => 0.8,
|
AsteroidSize::Small => 0.8,
|
||||||
},
|
},
|
||||||
WHITE,
|
Color::new(1., 1., 1., 0.5),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
16
src/main.rs
16
src/main.rs
|
@ -16,11 +16,21 @@ async fn main() {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
set_camera(&cam);
|
set_camera(&cam);
|
||||||
let mut pop = Population::new(5);
|
let mut pop = Population::new(100);
|
||||||
|
let mut speedup = false;
|
||||||
loop {
|
loop {
|
||||||
clear_background(BLACK);
|
clear_background(BLACK);
|
||||||
pop.update();
|
if is_key_pressed(KeyCode::S) {
|
||||||
pop.draw();
|
speedup = !speedup;
|
||||||
|
}
|
||||||
|
if speedup {
|
||||||
|
for _ in 0..100 {
|
||||||
|
pop.update();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pop.update();
|
||||||
|
pop.draw();
|
||||||
|
}
|
||||||
next_frame().await
|
next_frame().await
|
||||||
}
|
}
|
||||||
// let mut world = World::new();
|
// let mut world = World::new();
|
||||||
|
|
|
@ -14,11 +14,12 @@ pub struct Player {
|
||||||
last_shot: f32,
|
last_shot: f32,
|
||||||
shot_interval: f32,
|
shot_interval: f32,
|
||||||
pub brain: Option<NN>,
|
pub brain: Option<NN>,
|
||||||
search_radius: f32,
|
asteroids_data: Vec<f32>,
|
||||||
proximity_asteroids: Vec<f32>,
|
|
||||||
max_asteroids: usize,
|
max_asteroids: usize,
|
||||||
debug: bool,
|
debug: bool,
|
||||||
alive: bool,
|
alive: bool,
|
||||||
|
pub lifespan: u32,
|
||||||
|
pub shots: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Player {
|
impl Player {
|
||||||
|
@ -30,7 +31,6 @@ impl Player {
|
||||||
// Change scaling when passing inputs if this is changed
|
// Change scaling when passing inputs if this is changed
|
||||||
drag: 0.001,
|
drag: 0.001,
|
||||||
shot_interval: 0.3,
|
shot_interval: 0.3,
|
||||||
search_radius: 300.,
|
|
||||||
alive: true,
|
alive: true,
|
||||||
debug: false,
|
debug: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -50,8 +50,11 @@ impl Player {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_player_collision(&mut self, asteroid: &mut Asteroid) -> bool {
|
pub fn check_player_collision(&mut self, asteroid: &mut Asteroid) -> bool {
|
||||||
self.proximity_asteroids
|
self.asteroids_data.extend([
|
||||||
.extend([asteroid.pos.x, asteroid.pos.y, asteroid.radius]);
|
asteroid.pos.x / screen_width() + 0.5,
|
||||||
|
asteroid.pos.y / screen_height() + 0.5,
|
||||||
|
asteroid.radius / 50.,
|
||||||
|
]);
|
||||||
if asteroid.check_collision(self.pos, 8.) {
|
if asteroid.check_collision(self.pos, 8.) {
|
||||||
self.alive = false;
|
self.alive = false;
|
||||||
return true;
|
return true;
|
||||||
|
@ -71,10 +74,11 @@ impl Player {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self) {
|
pub fn update(&mut self) {
|
||||||
|
self.lifespan += 1;
|
||||||
let mut mag = 0.;
|
let mut mag = 0.;
|
||||||
let mut keys = vec![false, false, false, false];
|
let mut keys = vec![false, false, false, false];
|
||||||
|
|
||||||
self.proximity_asteroids.resize(self.max_asteroids, 0.);
|
self.asteroids_data.resize(self.max_asteroids, 0.);
|
||||||
let mut inputs = vec![
|
let mut inputs = vec![
|
||||||
self.pos.x / screen_width() + 0.5,
|
self.pos.x / screen_width() + 0.5,
|
||||||
self.pos.y / screen_height() + 0.5,
|
self.pos.y / screen_height() + 0.5,
|
||||||
|
@ -82,7 +86,7 @@ impl Player {
|
||||||
self.vel.y / 11.,
|
self.vel.y / 11.,
|
||||||
self.rot / TAU as f32,
|
self.rot / TAU as f32,
|
||||||
];
|
];
|
||||||
inputs.append(self.proximity_asteroids.as_mut());
|
inputs.append(self.asteroids_data.as_mut());
|
||||||
if let Some(brain) = &self.brain {
|
if let Some(brain) = &self.brain {
|
||||||
keys = brain
|
keys = brain
|
||||||
.feed_forward(inputs)
|
.feed_forward(inputs)
|
||||||
|
@ -105,6 +109,7 @@ impl Player {
|
||||||
if is_key_down(KeyCode::Space) || keys[3] {
|
if is_key_down(KeyCode::Space) || keys[3] {
|
||||||
if self.shot_interval + self.last_shot < get_time() as f32 {
|
if self.shot_interval + self.last_shot < get_time() as f32 {
|
||||||
self.last_shot = get_time() as f32;
|
self.last_shot = get_time() as f32;
|
||||||
|
self.shots += 1;
|
||||||
self.bullets.push(Bullet {
|
self.bullets.push(Bullet {
|
||||||
pos: self.pos + self.dir.rotate(vec2(20., 0.)),
|
pos: self.pos + self.dir.rotate(vec2(20., 0.)),
|
||||||
vel: self.dir.rotate(vec2(8.5, 0.)) + self.vel,
|
vel: self.dir.rotate(vec2(8.5, 0.)) + self.vel,
|
||||||
|
@ -151,7 +156,7 @@ impl Player {
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.debug {
|
if self.debug {
|
||||||
for a in self.proximity_asteroids.chunks(3) {
|
for a in self.asteroids_data.chunks(3) {
|
||||||
draw_circle_lines(a[0], a[1], a[2], 1., GRAY);
|
draw_circle_lines(a[0], a[1], a[2], 1., GRAY);
|
||||||
draw_line(self.pos.x, self.pos.y, a[0], a[1], 1., GRAY)
|
draw_line(self.pos.x, self.pos.y, a[0], a[1], 1., GRAY)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ impl Population {
|
||||||
Self {
|
Self {
|
||||||
size,
|
size,
|
||||||
worlds: (0..size)
|
worlds: (0..size)
|
||||||
.map(|_| World::simulate(NN::new(vec![33, 10, 4])))
|
.map(|_| World::simulate(NN::new(vec![33, 16, 4])))
|
||||||
.collect(),
|
.collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ impl Population {
|
||||||
}
|
}
|
||||||
if !alive {
|
if !alive {
|
||||||
self.gen += 1;
|
self.gen += 1;
|
||||||
|
println!("{}", self.gen);
|
||||||
self.next_gen();
|
self.next_gen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,18 +51,19 @@ impl Population {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_gen(&mut self) {
|
pub fn next_gen(&mut self) {
|
||||||
let total = self.worlds.iter().fold(0, |acc, x| acc + x.score);
|
let total = self.worlds.iter().fold(0., |acc, x| acc + x.fitness());
|
||||||
self.worlds.sort_by(|a, b| b.score.cmp(&a.score));
|
// self.worlds.sort_by(|a, b| b.fitness().cmp(&a.fitness()));
|
||||||
let mut new_worlds = (0..self.size / 10)
|
let mut new_worlds = Vec::new();
|
||||||
.map(|i| World::simulate(self.worlds[i].see_brain().to_owned()))
|
// (0..self.size / 10)
|
||||||
.collect::<Vec<_>>();
|
// .map(|i| World::simulate(self.worlds[i].see_brain().to_owned()))
|
||||||
|
// .collect::<Vec<_>>();
|
||||||
|
|
||||||
while new_worlds.len() < self.size {
|
while new_worlds.len() < self.size {
|
||||||
let rands = (gen_range(0, total + 1), gen_range(0, total + 1));
|
let rands = (gen_range(0., total), gen_range(0., total));
|
||||||
let mut sum = 0;
|
let mut sum = 0.;
|
||||||
let (mut a, mut b) = (None, None);
|
let (mut a, mut b) = (None, None);
|
||||||
for world in &self.worlds {
|
for world in &self.worlds {
|
||||||
sum += world.score;
|
sum += world.fitness();
|
||||||
if sum >= rands.0 {
|
if sum >= rands.0 {
|
||||||
a = Some(world.see_brain());
|
a = Some(world.see_brain());
|
||||||
}
|
}
|
||||||
|
|
10
src/world.rs
10
src/world.rs
|
@ -35,6 +35,16 @@ impl World {
|
||||||
self.player.brain.as_ref().unwrap()
|
self.player.brain.as_ref().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fitness(&self) -> f32 {
|
||||||
|
self.score as f32
|
||||||
|
+ self.player.lifespan as f32 * 0.01
|
||||||
|
+ if self.player.shots > 0 {
|
||||||
|
self.score as f32 / self.player.shots as f32 * 10.
|
||||||
|
} else {
|
||||||
|
0.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update(&mut self) {
|
pub fn update(&mut self) {
|
||||||
self.player.update();
|
self.player.update();
|
||||||
let mut to_add: Vec<Asteroid> = Vec::new();
|
let mut to_add: Vec<Asteroid> = Vec::new();
|
||||||
|
|
Loading…
Reference in New Issue