tracking ui
This commit is contained in:
parent
b7ad50da37
commit
0796eda239
96
src/main.rs
96
src/main.rs
|
@ -11,7 +11,7 @@ use macroquad::{
|
|||
prelude::*,
|
||||
ui::{hash, root_ui, widgets, Skin},
|
||||
};
|
||||
use population::Population;
|
||||
use population::{AutoSwitch, Population};
|
||||
use world::World;
|
||||
|
||||
pub const WIDTH: f32 = 800.;
|
||||
|
@ -76,8 +76,15 @@ async fn main() {
|
|||
ActivationFunc::Sigmoid,
|
||||
ActivationFunc::Tanh,
|
||||
];
|
||||
let mut auto_switch = Some(AutoSwitch::Best);
|
||||
|
||||
let mut pop = Population::new(size as usize, hlayers.clone(), mut_rate, activs[activ]);
|
||||
let mut pop = Population::new(
|
||||
size as usize,
|
||||
auto_switch,
|
||||
hlayers.clone(),
|
||||
mut_rate,
|
||||
activs[activ],
|
||||
);
|
||||
|
||||
let ui_thick = 34.;
|
||||
let nums = &[
|
||||
|
@ -192,15 +199,36 @@ async fn main() {
|
|||
],
|
||||
})
|
||||
.background_margin(RectOffset::new(1., 1., 1., 1.))
|
||||
.color_hovered(RED)
|
||||
.color_clicked(BLUE)
|
||||
.color_hovered(GREEN)
|
||||
.color_clicked(GREEN)
|
||||
.text_color(WHITE)
|
||||
.text_color_hovered(WHITE)
|
||||
.text_color_clicked(WHITE)
|
||||
.text_color_clicked(GREEN)
|
||||
.margin(RectOffset::new(4., 4., 2., 2.))
|
||||
.color_inactive(WHITE)
|
||||
.build();
|
||||
|
||||
let mut skin3 = skin2.clone();
|
||||
skin3.button_style = root_ui()
|
||||
.style_builder()
|
||||
.background(Image {
|
||||
width: 3,
|
||||
height: 3,
|
||||
bytes: vec![
|
||||
0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 0, 0, 255, 0,
|
||||
255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
|
||||
],
|
||||
})
|
||||
.background_margin(RectOffset::new(1., 1., 1., 1.))
|
||||
.color_hovered(GREEN)
|
||||
.color_clicked(GREEN)
|
||||
.text_color(GREEN)
|
||||
.text_color_hovered(GREEN)
|
||||
.text_color_clicked(GREEN)
|
||||
.margin(RectOffset::new(4., 4., 2., 2.))
|
||||
.color_inactive(GREEN)
|
||||
.build();
|
||||
|
||||
root_ui().push_skin(&skin);
|
||||
loop {
|
||||
clear_background(BLACK);
|
||||
|
@ -297,6 +325,7 @@ async fn main() {
|
|||
|
||||
pop = Population::new(
|
||||
size as usize,
|
||||
auto_switch,
|
||||
hlayers.clone(),
|
||||
mut_rate,
|
||||
activs[activ],
|
||||
|
@ -360,6 +389,7 @@ async fn main() {
|
|||
if widgets::Button::new(restart).ui(ui) {
|
||||
pop = Population::new(
|
||||
size as usize,
|
||||
auto_switch,
|
||||
hlayers.clone(),
|
||||
mut_rate,
|
||||
activs[activ],
|
||||
|
@ -371,9 +401,60 @@ async fn main() {
|
|||
hash!(),
|
||||
vec2(ui_width * 0.2, ui_height * 0.8 - 2. * th - 2. * ui_thick),
|
||||
)
|
||||
.position(vec2(ui_width * 0.8 - th, ui_height * 0.2 + ui_thick + th))
|
||||
.position(vec2(ui_width * 0.6, ui_height * 0.23 + ui_thick + th))
|
||||
.ui(ui, |ui| {
|
||||
ui.label(None, "Track Ship:");
|
||||
|
||||
if ui.button(None, "Best Alive") {
|
||||
pop.track_best(false);
|
||||
}
|
||||
if ui.button(None, "Current #1") {
|
||||
pop.track_best(true);
|
||||
}
|
||||
if ui.button(None, "LastGen #1") {
|
||||
pop.track_prev_best();
|
||||
}
|
||||
ui.label(None, " ");
|
||||
ui.label(None, "Auto Switch");
|
||||
ui.label(None, "When Dead to:");
|
||||
|
||||
if auto_switch == Some(AutoSwitch::Best) {
|
||||
ui.push_skin(&skin3);
|
||||
ui.button(None, "Current #1");
|
||||
ui.pop_skin();
|
||||
} else {
|
||||
if ui.button(None, "Current #1") {
|
||||
auto_switch = Some(AutoSwitch::Best);
|
||||
pop.auto_switch = auto_switch;
|
||||
}
|
||||
}
|
||||
if auto_switch == Some(AutoSwitch::BestAlive) {
|
||||
ui.push_skin(&skin3);
|
||||
ui.button(None, "Best Alive");
|
||||
ui.pop_skin();
|
||||
} else {
|
||||
if ui.button(None, "Best Alive") {
|
||||
auto_switch = Some(AutoSwitch::BestAlive);
|
||||
pop.auto_switch = auto_switch;
|
||||
}
|
||||
}
|
||||
if auto_switch.is_none() {
|
||||
ui.push_skin(&skin3);
|
||||
ui.button(None, "Do Nothing");
|
||||
ui.pop_skin();
|
||||
} else {
|
||||
if ui.button(None, "Do Nothing") {
|
||||
auto_switch = None;
|
||||
pop.auto_switch = auto_switch;
|
||||
}
|
||||
}
|
||||
});
|
||||
widgets::Group::new(
|
||||
hash!(),
|
||||
vec2(ui_width * 0.2, ui_height * 0.8 - 2. * th - 2. * ui_thick),
|
||||
)
|
||||
.position(vec2(ui_width * 0.8 - th, ui_height * 0.22 + ui_thick + th))
|
||||
.ui(ui, |ui| {
|
||||
// ui.input_text(hash!(), "vec2(100., 100.)", &mut xy);
|
||||
ui.label(None, "Hidden Layers");
|
||||
ui.label(None, "Neurons Config");
|
||||
|
||||
|
@ -383,6 +464,7 @@ async fn main() {
|
|||
if prev_hlayers != hlayers {
|
||||
pop = Population::new(
|
||||
size as usize,
|
||||
auto_switch,
|
||||
hlayers.clone(),
|
||||
mut_rate,
|
||||
activs[activ],
|
||||
|
|
|
@ -6,6 +6,12 @@ use crate::{
|
|||
HEIGHT, WIDTH,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum AutoSwitch {
|
||||
Best,
|
||||
BestAlive,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Population {
|
||||
size: usize,
|
||||
|
@ -15,16 +21,24 @@ pub struct Population {
|
|||
pub worlds: Vec<World>,
|
||||
pub track: usize,
|
||||
pub hlayers: Vec<usize>,
|
||||
pub auto_switch: Option<AutoSwitch>,
|
||||
}
|
||||
|
||||
impl Population {
|
||||
pub fn new(size: usize, hlayers: Vec<usize>, mut_rate: f32, activ: ActivationFunc) -> Self {
|
||||
pub fn new(
|
||||
size: usize,
|
||||
auto_switch: Option<AutoSwitch>,
|
||||
hlayers: Vec<usize>,
|
||||
mut_rate: f32,
|
||||
activ: ActivationFunc,
|
||||
) -> Self {
|
||||
Self {
|
||||
size,
|
||||
hlayers: hlayers.clone(),
|
||||
worlds: (0..size)
|
||||
.map(|_| World::new(Some(hlayers.clone()), Some(mut_rate), Some(activ)))
|
||||
.collect(),
|
||||
auto_switch,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +51,14 @@ impl Population {
|
|||
world.update();
|
||||
}
|
||||
}
|
||||
if self.worlds[self.track].over {
|
||||
if let Some(auto_switch) = self.auto_switch {
|
||||
match auto_switch {
|
||||
AutoSwitch::Best => self.track_best(true),
|
||||
AutoSwitch::BestAlive => self.track_best(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
if !alive {
|
||||
self.gen += 1;
|
||||
self.next_gen();
|
||||
|
@ -62,6 +84,25 @@ impl Population {
|
|||
}
|
||||
}
|
||||
}
|
||||
pub fn track_best(&mut self, can_be_dead: bool) {
|
||||
self.worlds[self.track].track(false);
|
||||
let i = self
|
||||
.worlds
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, w)| !w.over || can_be_dead)
|
||||
.max_by(|(_, a), (_, b)| a.fitness.total_cmp(&b.fitness))
|
||||
.map(|(i, _)| i);
|
||||
if let Some(i) = i {
|
||||
self.worlds[i].track(true);
|
||||
self.track = i;
|
||||
}
|
||||
}
|
||||
pub fn track_prev_best(&mut self) {
|
||||
self.worlds[self.track].track(false);
|
||||
self.worlds[0].track(true);
|
||||
self.track = 0;
|
||||
}
|
||||
|
||||
pub fn change_mut(&mut self, mut_rate: f32) {
|
||||
for world in &mut self.worlds {
|
||||
|
|
14
src/world.rs
14
src/world.rs
|
@ -181,7 +181,7 @@ impl World {
|
|||
draw_text_ex(
|
||||
if self.over { "DEAD" } else { "ALIVE" },
|
||||
-width * 0.5 + 20.,
|
||||
70.,
|
||||
55.,
|
||||
{
|
||||
let mut p = params.clone();
|
||||
p.color = if self.over { RED } else { GREEN };
|
||||
|
@ -191,19 +191,25 @@ impl World {
|
|||
draw_text_ex(
|
||||
&format!("Hits: {}", self.score),
|
||||
-width * 0.5 + 20.,
|
||||
90.,
|
||||
75.,
|
||||
params,
|
||||
);
|
||||
draw_text_ex(
|
||||
&format!("Fired: {}", self.player.shots),
|
||||
-width * 0.5 + 20.,
|
||||
110.,
|
||||
95.,
|
||||
params,
|
||||
);
|
||||
draw_text_ex(
|
||||
&format!("Fitness: {:.2}", self.fitness),
|
||||
-width * 0.5 + 20.,
|
||||
130.,
|
||||
115.,
|
||||
params,
|
||||
);
|
||||
draw_text_ex(
|
||||
&format!("Lifetime: {:.2}", self.player.lifespan as f32 / 60.),
|
||||
-width * 0.5 + 20.,
|
||||
135.,
|
||||
params,
|
||||
);
|
||||
let str = &format!("RANK #{}", rank);
|
||||
|
|
Loading…
Reference in New Issue