cleanup
This commit is contained in:
parent
edf1db25e0
commit
b9cfedc00d
|
@ -72,7 +72,6 @@ impl Asteroid {
|
|||
}
|
||||
|
||||
pub fn update(&mut self) {
|
||||
// if self.alive {
|
||||
self.pos += self.vel;
|
||||
self.rot += self.omega;
|
||||
if self.pos.x.abs() > screen_width() * 0.5 + self.radius {
|
||||
|
@ -81,9 +80,6 @@ impl Asteroid {
|
|||
if self.pos.y.abs() > screen_height() * 0.5 + self.radius {
|
||||
self.pos.y *= -1.;
|
||||
}
|
||||
// self.alive = self.pos.y.abs() < screen_height() * 0.51 + self.radius
|
||||
// && self.pos.x.abs() < screen_width() * 0.51 + self.radius;
|
||||
// }
|
||||
}
|
||||
|
||||
pub fn draw(&self) {
|
||||
|
|
13
src/main.rs
13
src/main.rs
|
@ -6,7 +6,6 @@ mod world;
|
|||
|
||||
use macroquad::prelude::*;
|
||||
use population::Population;
|
||||
use world::World;
|
||||
|
||||
#[macroquad::main("Camera")]
|
||||
async fn main() {
|
||||
|
@ -18,9 +17,6 @@ async fn main() {
|
|||
set_camera(&cam);
|
||||
let mut pop = Population::new(100);
|
||||
let mut speedup = false;
|
||||
// for _ in 0..10000 * 10 {
|
||||
// pop.update();
|
||||
// }
|
||||
loop {
|
||||
clear_background(BLACK);
|
||||
if is_key_pressed(KeyCode::S) {
|
||||
|
@ -36,13 +32,4 @@ async fn main() {
|
|||
}
|
||||
next_frame().await
|
||||
}
|
||||
// let mut world = World::new();
|
||||
// loop {
|
||||
// clear_background(BLACK);
|
||||
// if !world.over {
|
||||
// world.update();
|
||||
// }
|
||||
// world.draw();
|
||||
// next_frame().await
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -39,9 +39,6 @@ impl NN {
|
|||
.zip(config.iter().skip(1))
|
||||
.map(|(&curr, &last)| {
|
||||
// DMatrix::from_fn(last, curr + 1, |_, _| gen_range(-1., 1.))
|
||||
// DMatrix::<f32>::new_random(last, curr + 1)
|
||||
// println!("{}", a);
|
||||
// a
|
||||
DMatrix::<f32>::from_distribution(last, curr + 1, &StandardNormal, &mut rng)
|
||||
* (2. / last as f32).sqrt()
|
||||
})
|
||||
|
@ -75,7 +72,6 @@ impl NN {
|
|||
// *ele += gen_range(-1., 1.);
|
||||
*ele = gen_range(-1., 1.);
|
||||
// *ele = r::thread_rng().sample::<f32, StandardNormal>(StandardNormal);
|
||||
// *ele = r::thread_rng().sample::<f32, StandardNormal>(StandardNormal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
140
src/player.rs
140
src/player.rs
|
@ -1,7 +1,6 @@
|
|||
use std::{f32::consts::PI, f64::consts::TAU, iter};
|
||||
|
||||
use macroquad::{prelude::*, rand::gen_range};
|
||||
use nalgebra::{max, partial_max, partial_min};
|
||||
|
||||
use crate::{asteroids::Asteroid, nn::NN};
|
||||
#[derive(Default)]
|
||||
|
@ -58,35 +57,29 @@ impl Player {
|
|||
}
|
||||
|
||||
pub fn check_player_collision(&mut self, asteroid: &Asteroid) -> bool {
|
||||
// let directions = [
|
||||
// vec2(0., -screen_height()),
|
||||
// vec2(0., screen_height()),
|
||||
// vec2(-screen_width(), 0.),
|
||||
// vec2(screen_width(), 0.),
|
||||
// ];
|
||||
// let mut nearest = asteroid.pos - self.pos;
|
||||
// for dir in directions {
|
||||
// if (asteroid.pos - self.pos + dir).length_squared() < nearest.length_squared() {
|
||||
// nearest = asteroid.pos - self.pos + dir;
|
||||
// }
|
||||
// }
|
||||
self.asteroid_data.push((
|
||||
((asteroid.pos - self.pos).length() - asteroid.radius) / screen_width(),
|
||||
self.dir.angle_between(asteroid.pos - self.pos),
|
||||
(asteroid.vel - self.vel).length(),
|
||||
));
|
||||
// if self.asteroid.is_none()
|
||||
// || (asteroid.pos).distance_squared(self.pos)
|
||||
// < self
|
||||
// .asteroid
|
||||
// .as_ref()
|
||||
// .unwrap()
|
||||
// .pos
|
||||
// .distance_squared(self.pos)
|
||||
// {
|
||||
// self.asteroid = Some(asteroid.clone());
|
||||
// }
|
||||
// ]);
|
||||
// To give more near asteroids data:
|
||||
|
||||
// self.asteroid_data.push((
|
||||
// ((asteroid.pos - self.pos).length() - asteroid.radius) / screen_width(),
|
||||
// self.dir.angle_between(asteroid.pos - self.pos),
|
||||
// (asteroid.vel - self.vel).length(),
|
||||
// ));
|
||||
|
||||
// Single asteroid data:
|
||||
if self.asteroid.is_none()
|
||||
|| (asteroid.pos).distance_squared(self.pos)
|
||||
< self
|
||||
.asteroid
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.pos
|
||||
.distance_squared(self.pos)
|
||||
{
|
||||
self.asteroid = Some(asteroid.clone());
|
||||
}
|
||||
|
||||
// Try raycasting below:
|
||||
|
||||
// let v = asteroid.pos - self.pos;
|
||||
// for i in 0..4 {
|
||||
// let dir = Vec2::from_angle(PI / 4. * i as f32).rotate(self.dir);
|
||||
|
@ -125,35 +118,29 @@ impl Player {
|
|||
self.last_shot += 1;
|
||||
self.acc = 0.;
|
||||
let mut keys = vec![false, false, false, false];
|
||||
let mut inputs = vec![
|
||||
// (self.asteroid.as_ref().unwrap().pos - self.pos).length() / screen_width(),
|
||||
// self.dir
|
||||
// .angle_between(self.asteroid.as_ref().unwrap().pos - self.pos),
|
||||
// self.vel.x / 11.,
|
||||
// self.vel.y / 11.,
|
||||
self.rot / TAU as f32,
|
||||
// self.rot.sin(),
|
||||
// self.rot.cos(),
|
||||
];
|
||||
if let Some(ast) = self.asteroid.as_ref() {
|
||||
let inputs = vec![
|
||||
(ast.pos - self.pos).length() / screen_width(),
|
||||
self.dir.angle_between(ast.pos - self.pos),
|
||||
(ast.vel - self.vel).length(),
|
||||
self.rot / TAU as f32,
|
||||
];
|
||||
|
||||
self.asteroid_data
|
||||
.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
|
||||
self.asteroid_data.resize(1, (0., 0., 0.));
|
||||
inputs.append(
|
||||
&mut self
|
||||
.asteroid_data
|
||||
.iter()
|
||||
.map(|(d, a, h)| vec![*d, *a, *h])
|
||||
.flatten()
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
// println!("{:?}", inputs);
|
||||
// let inputs = self.raycasts.clone();
|
||||
// inputs.append(self.asteroids_data.as_mut());
|
||||
if let Some(brain) = &self.brain {
|
||||
// println!("{:?}", brain.feed_forward(inputs.clone()));
|
||||
// self.asteroid_data
|
||||
// .sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
|
||||
// self.asteroid_data.resize(1, (0., 0., 0.));
|
||||
// inputs.append(
|
||||
// &mut self
|
||||
// .asteroid_data
|
||||
// .iter()
|
||||
// .map(|(d, a, h)| vec![*d, *a, *h])
|
||||
// .flatten()
|
||||
// .collect::<Vec<_>>(),
|
||||
// );
|
||||
|
||||
keys = brain.feed_forward(inputs).iter().map(|&x| x > 0.).collect();
|
||||
if let Some(brain) = &self.brain {
|
||||
keys = brain.feed_forward(inputs).iter().map(|&x| x > 0.).collect();
|
||||
}
|
||||
}
|
||||
if is_key_down(KeyCode::Right) && self.debug || keys[0] {
|
||||
self.rot = (self.rot + 0.1 + TAU as f32) % TAU as f32;
|
||||
|
@ -164,7 +151,6 @@ impl Player {
|
|||
self.dir = vec2(self.rot.cos(), self.rot.sin());
|
||||
}
|
||||
if is_key_down(KeyCode::Up) && self.debug || keys[2] {
|
||||
// Change scaling when passing inputs if this is changed
|
||||
self.acc = 0.14;
|
||||
}
|
||||
if is_key_down(KeyCode::Space) && self.debug || keys[3] {
|
||||
|
@ -182,6 +168,9 @@ impl Player {
|
|||
if is_key_pressed(KeyCode::D) {
|
||||
self.debug = !self.debug;
|
||||
}
|
||||
if is_key_pressed(KeyCode::S) {
|
||||
self.debug = false;
|
||||
}
|
||||
|
||||
self.vel += self.acc * self.dir - self.drag * self.vel.length() * self.vel;
|
||||
self.pos += self.vel;
|
||||
|
@ -198,9 +187,11 @@ impl Player {
|
|||
self.bullets.retain(|b| {
|
||||
b.alive && b.pos.x.abs() * 2. < screen_width() && b.pos.y.abs() * 2. < screen_height()
|
||||
});
|
||||
// self.draw();
|
||||
if self.debug {
|
||||
self.draw();
|
||||
}
|
||||
self.asteroid = None;
|
||||
self.asteroid_data.clear();
|
||||
// self.asteroid_data.clear();
|
||||
}
|
||||
|
||||
pub fn draw(&self) {
|
||||
|
@ -223,25 +214,16 @@ impl Player {
|
|||
draw_triangle_lines(p6, p7, p8, 2., color);
|
||||
}
|
||||
if self.debug {
|
||||
// if self.asteroid.is_some() {
|
||||
// draw_circle_lines(
|
||||
// self.asteroid.as_ref().unwrap().pos.x,
|
||||
// self.asteroid.as_ref().unwrap().pos.y,
|
||||
// self.asteroid.as_ref().unwrap().radius,
|
||||
// 1.,
|
||||
// GRAY,
|
||||
// );
|
||||
// }
|
||||
let p = self.pos
|
||||
+ self.dir.rotate(Vec2::from_angle(self.asteroid_data[0].1))
|
||||
* self.asteroid_data[0].0
|
||||
* screen_width();
|
||||
draw_line(
|
||||
self.pos.x, self.pos.y,
|
||||
// self.asteroid.as_ref().unwrap().pos.x,
|
||||
// self.asteroid.as_ref().unwrap().pos.y,
|
||||
p.x, p.y, 1., GRAY,
|
||||
);
|
||||
if let Some(ast) = self.asteroid.as_ref() {
|
||||
draw_circle_lines(ast.pos.x, ast.pos.y, ast.radius, 1., GRAY);
|
||||
// let p = self.pos
|
||||
// + self.dir.rotate(Vec2::from_angle(self.asteroid_data[0].1))
|
||||
// * self.asteroid_data[0].0
|
||||
// * screen_width();
|
||||
draw_line(self.pos.x, self.pos.y, ast.pos.x, ast.pos.y, 1., GRAY);
|
||||
}
|
||||
|
||||
// Draw raycasts
|
||||
|
||||
// for (i, r) in self.raycasts.iter().enumerate() {
|
||||
// let dir = Vec2::from_angle(PI / 4. * i as f32).rotate(self.dir);
|
||||
|
|
|
@ -63,22 +63,12 @@ impl Population {
|
|||
println!("Fitness: {}", i.fitness);
|
||||
}
|
||||
println!("Gen: {}, Fitness: {}", self.gen, self.worlds[0].fitness);
|
||||
// let mut new_worlds = vec![World::simulate(Some(self.worlds[0].see_brain().to_owned()))];
|
||||
let mut new_worlds = (0..self.size / 20)
|
||||
.map(|i| World::simulate(Some(self.worlds[i].see_brain().to_owned())))
|
||||
.collect::<Vec<_>>();
|
||||
// if is_key_down(KeyCode::K) {
|
||||
new_worlds[0].set_best();
|
||||
// }
|
||||
// println!(
|
||||
// "Total fitness: {} {} {}",
|
||||
// total,
|
||||
// self.worlds[0].fitness(),
|
||||
// self.worlds[1].fitness()
|
||||
// );
|
||||
while new_worlds.len() < self.size {
|
||||
let rands = (gen_range(0., total), gen_range(0., total));
|
||||
// println!("rands: {} {} {}", rands.0, rands.1, total);
|
||||
let mut sum = 0.;
|
||||
let (mut a, mut b) = (None, None);
|
||||
for world in &self.worlds {
|
||||
|
@ -90,8 +80,6 @@ impl Population {
|
|||
b = Some(world.see_brain());
|
||||
}
|
||||
}
|
||||
// println!("{}", &a.unwrap().weights[0]);
|
||||
// println!("{}", &b.unwrap().weights[0]);
|
||||
if a.is_none() {
|
||||
a = Some(self.worlds.last().unwrap().see_brain());
|
||||
}
|
||||
|
@ -99,10 +87,7 @@ impl Population {
|
|||
b = Some(self.worlds.last().unwrap().see_brain());
|
||||
}
|
||||
let mut new_brain = NN::crossover(a.unwrap(), b.unwrap());
|
||||
// println!("{}", &a.unwrap().weights[0]);
|
||||
// println!("{}", &b.unwrap().weights[0]);
|
||||
new_brain.mutate();
|
||||
// println!("{}", &new_brain.weights[0]);
|
||||
new_worlds.push(World::simulate(Some(new_brain)));
|
||||
}
|
||||
self.worlds = new_worlds;
|
||||
|
|
44
src/world.rs
44
src/world.rs
|
@ -11,24 +11,13 @@ pub struct World {
|
|||
asteroids: Vec<Asteroid>,
|
||||
pub score: f32,
|
||||
pub over: bool,
|
||||
max_asteroids: usize,
|
||||
pub fitness: f32,
|
||||
}
|
||||
|
||||
impl World {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
player: Player::new(),
|
||||
max_asteroids: 28,
|
||||
score: 1.,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn simulate(brain: Option<NN>) -> Self {
|
||||
Self {
|
||||
player: Player::simulate(brain),
|
||||
max_asteroids: 28,
|
||||
score: 1.,
|
||||
asteroids: vec![
|
||||
Asteroid::new_to(vec2(0., 0.), 1.5, AsteroidSize::Large),
|
||||
|
@ -49,30 +38,7 @@ impl World {
|
|||
self.player.brain.as_ref().unwrap()
|
||||
}
|
||||
|
||||
// fn calc_fitness(&mut self) {
|
||||
// println!(
|
||||
// "{} {} {}",
|
||||
// self.score as f32,
|
||||
// self.player.lifespan as f32 * 0.001,
|
||||
// if self.player.shots > 0 {
|
||||
// self.score as f32 / self.player.shots as f32 * 5.
|
||||
// } else {
|
||||
// 0.
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
|
||||
pub fn update(&mut self) {
|
||||
// if self.player.lifespan > 150 {
|
||||
// self.fitness = 1.
|
||||
// / ((self.player.pos * vec2(2. / screen_width(), 2. / screen_height()))
|
||||
// .distance_squared(vec2(0., -1.))
|
||||
// + self.player.vel.length_squared()
|
||||
// * self.player.vel.length_squared()
|
||||
// * 0.00006830134554
|
||||
// + 1.);
|
||||
// self.over = true;
|
||||
// }
|
||||
let mut to_add: Vec<Asteroid> = Vec::new();
|
||||
for asteroid in &mut self.asteroids {
|
||||
asteroid.update();
|
||||
|
@ -108,19 +74,15 @@ impl World {
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
for asteroid in self.asteroids.iter() {
|
||||
if self.player.check_player_collision(&*asteroid) {
|
||||
if self.player.check_player_collision(asteroid) {
|
||||
self.over = true;
|
||||
self.fitness =
|
||||
(self.score / self.player.shots as f32).powi(2) * self.player.lifespan as f32;
|
||||
|
||||
// println!("{} {} {}", self.score, self.player.lifespan, self.fitness);
|
||||
}
|
||||
}
|
||||
self.player.update();
|
||||
self.asteroids.append(&mut to_add);
|
||||
self.asteroids.retain(|asteroid| asteroid.alive);
|
||||
self.player.update();
|
||||
// if self.asteroids.iter().fold(0, |acc, x| {
|
||||
// acc + match x.size {
|
||||
// AsteroidSize::Large => 4,
|
||||
|
@ -146,8 +108,6 @@ impl World {
|
|||
"{}",
|
||||
(self.score / self.player.shots as f32).powi(2) * self.player.lifespan as f32
|
||||
),
|
||||
// 20. - screen_width() * 0.5,
|
||||
// 30. - screen_height() * 0.5,
|
||||
self.player.pos.x - 20.,
|
||||
self.player.pos.y - 20.,
|
||||
12.,
|
||||
|
|
Loading…
Reference in New Issue