2022-10-08 19:47:47 +00:00
|
|
|
use crate::{
|
|
|
|
asteroids::{Asteroid, AsteroidSize},
|
2022-10-09 20:11:24 +00:00
|
|
|
nn::NN,
|
2022-10-08 19:47:47 +00:00
|
|
|
player::Player,
|
|
|
|
};
|
2022-10-08 15:27:05 +00:00
|
|
|
use macroquad::{prelude::*, rand::gen_range};
|
|
|
|
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct World {
|
|
|
|
player: Player,
|
|
|
|
asteroids: Vec<Asteroid>,
|
2022-10-10 18:36:14 +00:00
|
|
|
pub score: u32,
|
2022-10-09 05:40:56 +00:00
|
|
|
pub over: bool,
|
2022-10-10 18:36:14 +00:00
|
|
|
max_asteroids: usize,
|
2022-10-22 19:40:19 +00:00
|
|
|
pub fitness: f32,
|
2022-10-08 15:27:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl World {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
player: Player::new(),
|
2022-10-10 18:36:14 +00:00
|
|
|
max_asteroids: 28,
|
2022-10-08 15:27:05 +00:00
|
|
|
..Default::default()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-22 19:40:19 +00:00
|
|
|
pub fn simulate(brain: Option<NN>) -> Self {
|
2022-10-09 20:11:24 +00:00
|
|
|
Self {
|
2022-10-10 18:36:14 +00:00
|
|
|
player: Player::simulate(brain, 28),
|
|
|
|
max_asteroids: 28,
|
2022-10-09 20:11:24 +00:00
|
|
|
..Default::default()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-22 19:40:19 +00:00
|
|
|
pub fn set_best(&mut self) {
|
|
|
|
self.player.color = Some(RED);
|
|
|
|
}
|
|
|
|
|
2022-10-10 18:36:14 +00:00
|
|
|
pub fn see_brain(&self) -> &NN {
|
|
|
|
self.player.brain.as_ref().unwrap()
|
|
|
|
}
|
|
|
|
|
2022-10-22 19:40:19 +00:00
|
|
|
// 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.
|
|
|
|
// }
|
|
|
|
// );
|
|
|
|
// }
|
2022-10-10 19:43:05 +00:00
|
|
|
|
2022-10-08 15:27:05 +00:00
|
|
|
pub fn update(&mut self) {
|
|
|
|
self.player.update();
|
2022-10-22 19:40:19 +00:00
|
|
|
// 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;
|
|
|
|
// }
|
2022-10-08 20:17:06 +00:00
|
|
|
let mut to_add: Vec<Asteroid> = Vec::new();
|
2022-10-08 15:27:05 +00:00
|
|
|
for asteroid in &mut self.asteroids {
|
|
|
|
asteroid.update();
|
2022-10-09 05:40:56 +00:00
|
|
|
if self.player.check_player_collision(asteroid) {
|
|
|
|
self.over = true;
|
2022-10-22 19:40:19 +00:00
|
|
|
self.fitness = (self.score as f32 + 1.)
|
|
|
|
* if self.player.shots > 0 {
|
|
|
|
(self.score as f32 / self.player.shots as f32)
|
|
|
|
* (self.score as f32 / self.player.shots as f32)
|
|
|
|
} else {
|
|
|
|
1.
|
|
|
|
}
|
|
|
|
* self.player.lifespan as f32;
|
|
|
|
// self.fitness = self.player.lifespan as f32 * self.player.lifespan as f32 * 0.001;
|
|
|
|
|
|
|
|
// println!("{} {} {}", self.score, self.player.lifespan, self.fitness);
|
2022-10-09 05:40:56 +00:00
|
|
|
}
|
2022-10-08 20:17:06 +00:00
|
|
|
if self.player.check_bullet_collisions(asteroid) {
|
2022-10-09 05:40:56 +00:00
|
|
|
self.score += 1;
|
2022-10-08 20:17:06 +00:00
|
|
|
match asteroid.size {
|
|
|
|
AsteroidSize::Large => {
|
2022-10-10 10:13:06 +00:00
|
|
|
let rand = vec2(gen_range(-0.8, 0.8), gen_range(-0.8, 0.8));
|
2022-10-08 20:17:06 +00:00
|
|
|
to_add.push(Asteroid::new_from(
|
|
|
|
asteroid.pos,
|
|
|
|
asteroid.vel + rand,
|
|
|
|
AsteroidSize::Medium,
|
|
|
|
));
|
|
|
|
to_add.push(Asteroid::new_from(
|
|
|
|
asteroid.pos,
|
|
|
|
asteroid.vel - rand,
|
|
|
|
AsteroidSize::Medium,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
AsteroidSize::Medium => {
|
2022-10-10 10:13:06 +00:00
|
|
|
let rand = vec2(gen_range(-0.6, 0.6), gen_range(-0.6, 0.6));
|
2022-10-08 20:17:06 +00:00
|
|
|
to_add.push(Asteroid::new_from(
|
|
|
|
asteroid.pos,
|
|
|
|
asteroid.vel + rand,
|
|
|
|
AsteroidSize::Small,
|
|
|
|
));
|
|
|
|
to_add.push(Asteroid::new_from(
|
|
|
|
asteroid.pos,
|
|
|
|
asteroid.vel - rand,
|
|
|
|
AsteroidSize::Small,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
2022-10-08 15:27:05 +00:00
|
|
|
}
|
2022-10-08 20:17:06 +00:00
|
|
|
self.asteroids.append(&mut to_add);
|
2022-10-08 19:47:47 +00:00
|
|
|
self.asteroids.retain(|asteroid| asteroid.alive);
|
2022-10-09 05:40:56 +00:00
|
|
|
if self.asteroids.iter().fold(0, |acc, x| {
|
|
|
|
acc + match x.size {
|
|
|
|
AsteroidSize::Large => 4,
|
|
|
|
AsteroidSize::Medium => 2,
|
|
|
|
AsteroidSize::Small => 1,
|
|
|
|
}
|
2022-10-10 18:36:14 +00:00
|
|
|
}) < self.max_asteroids
|
2022-10-09 05:40:56 +00:00
|
|
|
{
|
2022-10-08 19:47:47 +00:00
|
|
|
self.asteroids.push(Asteroid::new(AsteroidSize::Large));
|
2022-10-08 15:27:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn draw(&self) {
|
|
|
|
self.player.draw();
|
|
|
|
for asteroid in &self.asteroids {
|
|
|
|
asteroid.draw();
|
|
|
|
}
|
2022-10-10 18:36:14 +00:00
|
|
|
// draw_text(
|
|
|
|
// &format!("Score {}", self.score),
|
|
|
|
// 20. - screen_width() * 0.5,
|
|
|
|
// 30. - screen_height() * 0.5,
|
|
|
|
// 32.,
|
|
|
|
// WHITE,
|
|
|
|
// );
|
2022-10-08 15:27:05 +00:00
|
|
|
}
|
|
|
|
}
|