debug, selection
This commit is contained in:
parent
7110d063b4
commit
b9bc8ae08d
|
@ -17,6 +17,7 @@ pub struct Asteroid {
|
||||||
rot: f32,
|
rot: f32,
|
||||||
omega: f32,
|
omega: f32,
|
||||||
pub alive: bool,
|
pub alive: bool,
|
||||||
|
pub color: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Asteroid {
|
impl Asteroid {
|
||||||
|
@ -47,6 +48,7 @@ impl Asteroid {
|
||||||
omega: gen_range(0.8, 3.5) * if gen_range(0., 1.) > 0.5 { -1. } else { 1. },
|
omega: gen_range(0.8, 3.5) * if gen_range(0., 1.) > 0.5 { -1. } else { 1. },
|
||||||
rot: 0.,
|
rot: 0.,
|
||||||
alive: true,
|
alive: true,
|
||||||
|
color: Color::new(1., 1., 1., 0.2),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,8 +93,7 @@ impl Asteroid {
|
||||||
AsteroidSize::Medium => 1.2,
|
AsteroidSize::Medium => 1.2,
|
||||||
AsteroidSize::Small => 0.8,
|
AsteroidSize::Small => 0.8,
|
||||||
},
|
},
|
||||||
// WHITE,
|
self.color,
|
||||||
Color::new(1., 1., 1., 0.4),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
28
src/main.rs
28
src/main.rs
|
@ -128,7 +128,9 @@ async fn main() {
|
||||||
set_camera(&gamecam);
|
set_camera(&gamecam);
|
||||||
if is_key_pressed(KeyCode::S) {
|
if is_key_pressed(KeyCode::S) {
|
||||||
speedup = (speedup * 10) % 9999;
|
speedup = (speedup * 10) % 9999;
|
||||||
println!("Speedup: {}", speedup);
|
}
|
||||||
|
if is_key_pressed(KeyCode::P) {
|
||||||
|
paused = !paused;
|
||||||
}
|
}
|
||||||
if !paused {
|
if !paused {
|
||||||
for _ in 0..speedup {
|
for _ in 0..speedup {
|
||||||
|
@ -165,6 +167,20 @@ async fn main() {
|
||||||
screen_width() - WIDTH - 3. * th,
|
screen_width() - WIDTH - 3. * th,
|
||||||
(screen_height() - 7. * th) * 0.5 - 2. * ui_thick,
|
(screen_height() - 7. * th) * 0.5 - 2. * ui_thick,
|
||||||
);
|
);
|
||||||
|
if is_mouse_button_pressed(MouseButton::Left) && mouse_position().0 < WIDTH + th {
|
||||||
|
let (x, y) = mouse_position();
|
||||||
|
for i in 0..pop.worlds.len() {
|
||||||
|
if (pop.worlds[i].player.pos - vec2(x - th - WIDTH * 0.5, y - th - HEIGHT * 0.5))
|
||||||
|
.length_squared()
|
||||||
|
< 256.
|
||||||
|
{
|
||||||
|
pop.worlds.swap(0, i);
|
||||||
|
pop.worlds[0].track(true);
|
||||||
|
pop.worlds[i].track(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let ui_width = screen_width() - WIDTH - 3. * th + 1.;
|
let ui_width = screen_width() - WIDTH - 3. * th + 1.;
|
||||||
let ui_height = (screen_height() - 3. * th) * 0.5;
|
let ui_height = (screen_height() - 3. * th) * 0.5;
|
||||||
|
@ -216,20 +232,22 @@ async fn main() {
|
||||||
widgets::Group::new(hash!(), Vec2::new(100., ui_thick))
|
widgets::Group::new(hash!(), Vec2::new(100., ui_thick))
|
||||||
.position(Vec2::new(140., 0.))
|
.position(Vec2::new(140., 0.))
|
||||||
.ui(ui, |ui| {
|
.ui(ui, |ui| {
|
||||||
ui.drag(hash!(), "", Some((1, 500)), &mut size);
|
ui.drag(hash!(), "", Some((1, 300)), &mut size);
|
||||||
});
|
});
|
||||||
ui.same_line(307.);
|
ui.same_line(307.);
|
||||||
widgets::Button::new("Debug").ui(ui);
|
if widgets::Button::new("Debug").ui(ui) {
|
||||||
|
pop.debug = !pop.debug;
|
||||||
|
};
|
||||||
ui.same_line(0.);
|
ui.same_line(0.);
|
||||||
if widgets::Button::new(if bias { "Hide Bias" } else { "Show Bias" }).ui(ui)
|
if widgets::Button::new(if bias { "Hide Bias" } else { "Show Bias" }).ui(ui)
|
||||||
{
|
{
|
||||||
bias = !bias;
|
bias = !bias;
|
||||||
};
|
};
|
||||||
ui.same_line(0.);
|
ui.same_line(0.);
|
||||||
if widgets::Button::new(if !pop.best { "Show Best" } else { "Show All " })
|
if widgets::Button::new(if !pop.focus { "Show Best" } else { "Show All " })
|
||||||
.ui(ui)
|
.ui(ui)
|
||||||
{
|
{
|
||||||
pop.best = !pop.best;
|
pop.focus = !pop.focus;
|
||||||
};
|
};
|
||||||
ui.same_line(0.);
|
ui.same_line(0.);
|
||||||
if widgets::Button::new(restart).ui(ui) {
|
if widgets::Button::new(restart).ui(ui) {
|
||||||
|
|
13
src/nn.rs
13
src/nn.rs
|
@ -184,10 +184,15 @@ impl NN {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
draw_rectangle(width * 0.45, height * 0.45, 10., 10., RED);
|
draw_rectangle(width * 0.47, height * 0.47, 10., 10., RED);
|
||||||
draw_text("-ve", width * 0.45 + 20., height * 0.45 + 10., 20., WHITE);
|
let params = TextParams {
|
||||||
draw_rectangle(width * 0.45, height * 0.45 + 20., 10., 10., WHITE);
|
font_size: 40,
|
||||||
draw_text("+ve", width * 0.45 + 20., height * 0.45 + 30., 20., WHITE);
|
font_scale: 0.5,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
draw_text_ex("-ve", width * 0.47 + 20., height * 0.47 + 10., params);
|
||||||
|
draw_rectangle(width * 0.47, height * 0.47 + 20., 10., 10., WHITE);
|
||||||
|
draw_text_ex("+ve", width * 0.47 + 20., height * 0.47 + 30., params);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn export(&self) -> String {
|
pub fn export(&self) -> String {
|
||||||
|
|
|
@ -19,7 +19,6 @@ pub struct Player {
|
||||||
last_shot: u8,
|
last_shot: u8,
|
||||||
shot_interval: u8,
|
shot_interval: u8,
|
||||||
pub brain: Option<NN>,
|
pub brain: Option<NN>,
|
||||||
debug: bool,
|
|
||||||
alive: bool,
|
alive: bool,
|
||||||
pub color: Option<Color>,
|
pub color: Option<Color>,
|
||||||
pub lifespan: u32,
|
pub lifespan: u32,
|
||||||
|
@ -36,7 +35,6 @@ impl Player {
|
||||||
drag: 0.001,
|
drag: 0.001,
|
||||||
shot_interval: 18,
|
shot_interval: 18,
|
||||||
alive: true,
|
alive: true,
|
||||||
debug: false,
|
|
||||||
shots: 4,
|
shots: 4,
|
||||||
outputs: vec![0.; 4],
|
outputs: vec![0.; 4],
|
||||||
|
|
||||||
|
@ -147,18 +145,21 @@ impl Player {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let keys: Vec<bool> = self.outputs.iter().map(|&x| x > 0.).collect();
|
let keys: Vec<bool> = self.outputs.iter().map(|&x| x > 0.).collect();
|
||||||
if is_key_down(KeyCode::Right) && self.debug || keys[0] {
|
if keys[0] {
|
||||||
|
// RIGHT
|
||||||
self.rot = (self.rot + 0.1 + TAU as f32) % TAU as f32;
|
self.rot = (self.rot + 0.1 + TAU as f32) % TAU as f32;
|
||||||
self.dir = vec2(self.rot.cos(), self.rot.sin());
|
self.dir = vec2(self.rot.cos(), self.rot.sin());
|
||||||
}
|
}
|
||||||
if is_key_down(KeyCode::Left) && self.debug || keys[1] {
|
if keys[1] {
|
||||||
|
// LEFT
|
||||||
self.rot = (self.rot - 0.1 + TAU as f32) % TAU as f32;
|
self.rot = (self.rot - 0.1 + TAU as f32) % TAU as f32;
|
||||||
self.dir = vec2(self.rot.cos(), self.rot.sin());
|
self.dir = vec2(self.rot.cos(), self.rot.sin());
|
||||||
}
|
}
|
||||||
if is_key_down(KeyCode::Up) && self.debug || keys[2] {
|
if is_key_down(KeyCode::Up) || keys[2] {
|
||||||
|
// THROTTLE
|
||||||
self.acc = 0.14;
|
self.acc = 0.14;
|
||||||
}
|
}
|
||||||
if is_key_down(KeyCode::Space) && self.debug || keys[3] {
|
if is_key_down(KeyCode::Space) || keys[3] {
|
||||||
if self.last_shot > self.shot_interval {
|
if self.last_shot > self.shot_interval {
|
||||||
self.last_shot = 0;
|
self.last_shot = 0;
|
||||||
self.shots += 1;
|
self.shots += 1;
|
||||||
|
@ -170,12 +171,12 @@ impl Player {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_key_pressed(KeyCode::D) {
|
// if is_key_pressed(KeyCode::D) {
|
||||||
self.debug = !self.debug;
|
// self.debug = !self.debug;
|
||||||
}
|
// }
|
||||||
if is_key_pressed(KeyCode::S) {
|
// if is_key_pressed(KeyCode::S) {
|
||||||
self.debug = false;
|
// self.debug = false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
self.vel += self.acc * self.dir - self.drag * self.vel.length() * self.vel;
|
self.vel += self.acc * self.dir - self.drag * self.vel.length() * self.vel;
|
||||||
self.pos += self.vel;
|
self.pos += self.vel;
|
||||||
|
@ -191,14 +192,11 @@ impl Player {
|
||||||
}
|
}
|
||||||
self.bullets
|
self.bullets
|
||||||
.retain(|b| b.alive && b.pos.x.abs() * 2. < WIDTH && b.pos.y.abs() * 2. < HEIGHT);
|
.retain(|b| b.alive && b.pos.x.abs() * 2. < WIDTH && b.pos.y.abs() * 2. < HEIGHT);
|
||||||
if self.debug {
|
|
||||||
self.draw();
|
|
||||||
}
|
|
||||||
self.asteroid = None;
|
self.asteroid = None;
|
||||||
// self.asteroid_data.clear();
|
// self.asteroid_data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(&self) {
|
pub fn draw(&self, debug: bool) {
|
||||||
let color = match self.color {
|
let color = match self.color {
|
||||||
Some(c) => c,
|
Some(c) => c,
|
||||||
// None => WHITE,
|
// None => WHITE,
|
||||||
|
@ -218,14 +216,14 @@ impl Player {
|
||||||
if self.acc > 0. && gen_range(0., 1.) < 0.4 {
|
if self.acc > 0. && gen_range(0., 1.) < 0.4 {
|
||||||
draw_triangle_lines(p6, p7, p8, 2., color);
|
draw_triangle_lines(p6, p7, p8, 2., color);
|
||||||
}
|
}
|
||||||
if self.debug {
|
if debug {
|
||||||
if let Some(ast) = self.asteroid.as_ref() {
|
if let Some(ast) = self.asteroid.as_ref() {
|
||||||
draw_circle_lines(ast.pos.x, ast.pos.y, ast.radius, 1., GRAY);
|
draw_circle_lines(ast.pos.x, ast.pos.y, ast.radius, 1., DARKBLUE);
|
||||||
// let p = self.pos
|
// let p = self.pos
|
||||||
// + self.dir.rotate(Vec2::from_angle(self.asteroid_data[0].1))
|
// + self.dir.rotate(Vec2::from_angle(self.asteroid_data[0].1))
|
||||||
// * self.asteroid_data[0].0
|
// * self.asteroid_data[0].0
|
||||||
// * WIDTH;
|
// * WIDTH;
|
||||||
draw_line(self.pos.x, self.pos.y, ast.pos.x, ast.pos.y, 1., GRAY);
|
draw_line(self.pos.x, self.pos.y, ast.pos.x, ast.pos.y, 1., DARKBLUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw raycasts
|
// Draw raycasts
|
||||||
|
@ -244,7 +242,7 @@ impl Player {
|
||||||
}
|
}
|
||||||
|
|
||||||
for bullet in &self.bullets {
|
for bullet in &self.bullets {
|
||||||
bullet.draw();
|
bullet.draw(color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,7 +263,7 @@ impl Bullet {
|
||||||
fn update(&mut self) {
|
fn update(&mut self) {
|
||||||
self.pos += self.vel;
|
self.pos += self.vel;
|
||||||
}
|
}
|
||||||
fn draw(&self) {
|
fn draw(&self, color: Color) {
|
||||||
draw_circle(self.pos.x, self.pos.y, 2., WHITE);
|
draw_circle(self.pos.x, self.pos.y, 2., color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,8 @@ use crate::{nn::NN, world::World, HEIGHT, WIDTH};
|
||||||
pub struct Population {
|
pub struct Population {
|
||||||
size: usize,
|
size: usize,
|
||||||
pub gen: i32,
|
pub gen: i32,
|
||||||
pub best: bool,
|
pub focus: bool,
|
||||||
|
pub debug: bool,
|
||||||
pub worlds: Vec<World>,
|
pub worlds: Vec<World>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,27 +33,23 @@ impl Population {
|
||||||
self.next_gen();
|
self.next_gen();
|
||||||
}
|
}
|
||||||
if is_key_pressed(KeyCode::Z) {
|
if is_key_pressed(KeyCode::Z) {
|
||||||
self.best = !self.best;
|
self.focus = !self.focus;
|
||||||
|
}
|
||||||
|
if is_key_pressed(KeyCode::D) {
|
||||||
|
self.debug = !self.debug;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(&self) {
|
pub fn draw(&self) {
|
||||||
for world in self.worlds.iter().rev() {
|
for world in self.worlds.iter().rev() {
|
||||||
if self.best {
|
if self.focus {
|
||||||
if world.player.color.is_some() {
|
if world.track {
|
||||||
world.draw();
|
world.draw(self.debug);
|
||||||
}
|
}
|
||||||
} else if !world.over {
|
} else if !world.over {
|
||||||
world.draw();
|
world.draw(self.debug);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// draw_text(
|
|
||||||
// &format!("Gen: {}", self.gen),
|
|
||||||
// -150. + WIDTH * 0.5,
|
|
||||||
// 30. - HEIGHT * 0.5,
|
|
||||||
// 32.,
|
|
||||||
// WHITE,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// draw black background outside the screen
|
// draw black background outside the screen
|
||||||
let th = (screen_height() - HEIGHT) * 0.5;
|
let th = (screen_height() - HEIGHT) * 0.5;
|
||||||
|
@ -85,8 +82,7 @@ impl Population {
|
||||||
let mut new_worlds = (0..std::cmp::max(1, self.size / 20))
|
let mut new_worlds = (0..std::cmp::max(1, self.size / 20))
|
||||||
.map(|i| World::simulate(Some(self.worlds[i].see_brain().to_owned())))
|
.map(|i| World::simulate(Some(self.worlds[i].see_brain().to_owned())))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
new_worlds[0].set_best();
|
new_worlds[0].track(true);
|
||||||
// new_worlds[0].export_brian();
|
|
||||||
while new_worlds.len() < self.size {
|
while new_worlds.len() < self.size {
|
||||||
let rands = (gen_range(0., total), gen_range(0., total));
|
let rands = (gen_range(0., total), gen_range(0., total));
|
||||||
let mut sum = 0.;
|
let mut sum = 0.;
|
||||||
|
|
47
src/world.rs
47
src/world.rs
|
@ -12,6 +12,7 @@ pub struct World {
|
||||||
pub score: f32,
|
pub score: f32,
|
||||||
pub over: bool,
|
pub over: bool,
|
||||||
pub fitness: f32,
|
pub fitness: f32,
|
||||||
|
pub track: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl World {
|
impl World {
|
||||||
|
@ -30,8 +31,15 @@ impl World {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_best(&mut self) {
|
pub fn track(&mut self, track: bool) {
|
||||||
self.player.color = Some(RED);
|
self.player.color = if track { Some(RED) } else { None };
|
||||||
|
for asteroid in &mut self.asteroids {
|
||||||
|
asteroid.color = if track {
|
||||||
|
Color::new(1., 0., 0., 0.8)
|
||||||
|
} else {
|
||||||
|
Color::new(1., 1., 1., 0.2)
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn see_brain(&self) -> &NN {
|
pub fn see_brain(&self) -> &NN {
|
||||||
|
@ -44,6 +52,7 @@ impl World {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self) {
|
pub fn update(&mut self) {
|
||||||
|
self.player.update();
|
||||||
let mut to_add: Vec<Asteroid> = Vec::new();
|
let mut to_add: Vec<Asteroid> = Vec::new();
|
||||||
for asteroid in &mut self.asteroids {
|
for asteroid in &mut self.asteroids {
|
||||||
asteroid.update();
|
asteroid.update();
|
||||||
|
@ -85,7 +94,6 @@ impl World {
|
||||||
}
|
}
|
||||||
self.fitness =
|
self.fitness =
|
||||||
(self.score / self.player.shots as f32).powi(2) * self.player.lifespan as f32;
|
(self.score / self.player.shots as f32).powi(2) * self.player.lifespan as f32;
|
||||||
self.player.update();
|
|
||||||
self.asteroids.append(&mut to_add);
|
self.asteroids.append(&mut to_add);
|
||||||
self.asteroids.retain(|asteroid| asteroid.alive);
|
self.asteroids.retain(|asteroid| asteroid.alive);
|
||||||
// if self.asteroids.iter().fold(0, |acc, x| {
|
// if self.asteroids.iter().fold(0, |acc, x| {
|
||||||
|
@ -103,8 +111,8 @@ impl World {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(&self) {
|
pub fn draw(&self, debug: bool) {
|
||||||
self.player.draw();
|
self.player.draw(debug);
|
||||||
for asteroid in &self.asteroids {
|
for asteroid in &self.asteroids {
|
||||||
asteroid.draw();
|
asteroid.draw();
|
||||||
}
|
}
|
||||||
|
@ -156,33 +164,38 @@ impl World {
|
||||||
draw_circle(l1.x, l1.y, 5., WHITE);
|
draw_circle(l1.x, l1.y, 5., WHITE);
|
||||||
draw_circle(l1.x, l1.y, 3.5, BLACK);
|
draw_circle(l1.x, l1.y, 3.5, BLACK);
|
||||||
}
|
}
|
||||||
draw_text(
|
let params = TextParams {
|
||||||
|
font_size: 48,
|
||||||
|
font_scale: 0.5,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
draw_text_ex(
|
||||||
if self.over { "DEAD" } else { "ALIVE" },
|
if self.over { "DEAD" } else { "ALIVE" },
|
||||||
-width * 0.5 + 20.,
|
-width * 0.5 + 20.,
|
||||||
70.,
|
70.,
|
||||||
24.,
|
{
|
||||||
if self.over { RED } else { GREEN },
|
let mut p = params.clone();
|
||||||
|
p.color = if self.over { RED } else { GREEN };
|
||||||
|
p
|
||||||
|
},
|
||||||
);
|
);
|
||||||
draw_text(
|
draw_text_ex(
|
||||||
&format!("Hits: {}", self.score),
|
&format!("Hits: {}", self.score),
|
||||||
-width * 0.5 + 20.,
|
-width * 0.5 + 20.,
|
||||||
90.,
|
90.,
|
||||||
24.,
|
params,
|
||||||
WHITE,
|
|
||||||
);
|
);
|
||||||
draw_text(
|
draw_text_ex(
|
||||||
&format!("Fired: {}", self.player.shots),
|
&format!("Fired: {}", self.player.shots),
|
||||||
-width * 0.5 + 20.,
|
-width * 0.5 + 20.,
|
||||||
110.,
|
110.,
|
||||||
24.,
|
params,
|
||||||
WHITE,
|
|
||||||
);
|
);
|
||||||
draw_text(
|
draw_text_ex(
|
||||||
&format!("Fitness: {:.2}", self.fitness),
|
&format!("Fitness: {:.2}", self.fitness),
|
||||||
-width * 0.5 + 20.,
|
-width * 0.5 + 20.,
|
||||||
130.,
|
130.,
|
||||||
24.,
|
params,
|
||||||
WHITE,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue