player visual
This commit is contained in:
parent
7dea9e0406
commit
7e3acb4d57
|
@ -1 +1 @@
|
|||
{"config":[6,9,9,4],"weights":[[[0.3488082,-0.09199099,-0.11929926,-1.0631673,-0.23543529,0.12705088,-1.0842022,-1.1801648,1.3452269,-0.105297334,0.7070266,-0.49821422,-0.9919794,-0.4586555,0.38327622,1.2620807,-0.8927275,0.72946376,0.36548716,0.3453985,0.24704376,1.1178607,-0.73745847,-0.36780706,0.5647091,-0.29108286,1.710524,1.0728852,-0.8066526,-0.28913066,0.14346941,-1.0912626,0.36901304,0.7923526,-0.51800287,-0.72875357,0.8539478,-1.473583,0.68293977,0.18473642,0.0003245327,-0.58371824,0.48150238,0.3494165,-0.23288698,-1.0439657,-0.26875693,0.5452296],8,6],[[-2.3292994,-0.26192483,-0.90176463,2.324304,-1.9353858,-0.14891693,-0.52935755,0.76884156,0.1082592,-0.9176799,0.6898619,0.7002196,0.19165382,-0.00026388586,-2.0727108,-0.43361717,0.4825783,0.5469626,1.5679779,1.6802235,0.5569048,0.2322176,-1.2066526,0.7200245,-0.54737276,-0.15166411,0.19801892,0.040810376,1.3895321,-0.08859847,-1.2233515,-0.063391574,0.10386248,-1.1793425,0.47050527,-1.7380185,-1.7678633,0.42901033,-0.017297065,0.4843002,-1.3651237,-0.24331652,0.2636839,0.7167474,-1.2047871,2.1309357,-1.3384317,2.6571567,0.044456493,-1.8444118,-0.52083886,0.32806322,0.088446766,-0.009452653,0.20716749,-0.911177,-0.74860054,0.16590308,0.46789008,0.9035914,0.64725244,-0.30468005,0.27064824,0.39474502,2.02378,-1.4614658,-0.84020156,0.69931465,-0.51446456,0.24423209,1.2651527,-0.45960972],8,9],[[-0.585348,0.5383882,-0.97360545,0.032165576,-0.049561385,0.24148509,-0.8100511,-0.6426556,1.059696,0.85932785,0.6353762,-0.9978614,1.9525132,-0.10112733,-0.5321224,0.443344,-0.37738746,-0.99622214,-1.3957877,0.6381588,-0.47502336,1.0980062,0.047556207,-0.008916257,-0.8662841,-0.45772696,1.6571641,0.9795985,0.098027825,-1.6333683,0.58037895,1.2487193,-1.0500598,-0.44345784,-2.4462621,0.5654464],4,9]],"activ_func":"ReLU","mut_rate":0.05}
|
||||
{"config":[6,7,7,4],"weights":[[[-0.63086957,-0.53742135,-0.9276433,-0.34575018,0.7992718,-1.715718,-0.73926973,-1.0049589,0.8922695,-0.89036644,-1.9465111,1.1345955,0.16628692,0.35796213,-0.19456862,1.2559475,-1.4939085,0.7122434,-0.35949436,0.59764737,1.3104885,-0.23108178,1.1664017,-0.562161,-1.0272486,0.71920836,-0.48468617,1.9857628,-1.5419438,0.7855448,0.7199551,-0.055748053,0.89273596,-1.5976299,0.67290825,1.321863],6,6],[[0.96074045,-1.3427482,-0.34363145,-0.467356,0.40982306,1.6549394,-0.98944664,1.3190286,1.114854,-1.9362743,1.4953789,-0.92963094,2.176349,-0.6917859,0.4418182,-0.578999,0.28320304,0.047711473,0.9644473,-0.27468953,-0.6578115,-1.835753,1.0188148,0.4024565,-0.283786,1.7134846,0.6505742,-0.47571746,-0.2544604,2.5863714,-0.3020923,1.8471942,-0.7066354,0.4471431,0.2741386,-1.7216014,-0.32693514,1.760901,0.20739792,-1.222214,1.7166008,2.3254254],6,7],[[-0.8019232,0.43523917,0.45905063,-1.0787292,0.94543713,1.4523034,1.061355,-0.3872152,-1.3330262,1.1092484,0.40466794,0.8725662,-0.5520403,-0.095518686,-0.03717842,0.44755453,-2.0717077,2.0572546,0.6617041,0.019890757,-0.9302492,-0.38139746,0.22157091,-1.4106625,-0.8257789,0.054379098,0.927862,1.8578752],4,7]],"activ_func":"ReLU","mut_rate":0.05}
|
163
src/main.rs
163
src/main.rs
|
@ -4,8 +4,6 @@ mod player;
|
|||
mod population;
|
||||
mod world;
|
||||
|
||||
use std::borrow::BorrowMut;
|
||||
|
||||
use macroquad::{
|
||||
prelude::*,
|
||||
ui::{hash, root_ui, widgets, Skin},
|
||||
|
@ -38,7 +36,7 @@ async fn main() {
|
|||
offset: vec2((2. * th + WIDTH) / screen_width() - 1., 0.),
|
||||
..Default::default()
|
||||
};
|
||||
let maincam = Camera2D {
|
||||
let netcam = Camera2D {
|
||||
zoom: vec2(2. / screen_width(), -2. / screen_height()),
|
||||
offset: vec2(
|
||||
(th + WIDTH) / screen_width(),
|
||||
|
@ -46,25 +44,23 @@ async fn main() {
|
|||
),
|
||||
..Default::default()
|
||||
};
|
||||
// let mut cam = Camera2D::from_display_rect(Rect {
|
||||
// x: 0.,
|
||||
// y: 0.,
|
||||
// w: 1600.,
|
||||
// h: 1200.,
|
||||
// });
|
||||
// cam.offset = vec2(1., -1.);
|
||||
// // {
|
||||
// zoom: vec2(2. / 800., -2. / 600.),
|
||||
// // offset: vec2(-19. / 60., 0.),
|
||||
// ..Default::default()
|
||||
// };
|
||||
let mut pop = Population::new(100);
|
||||
let statcam = Camera2D {
|
||||
zoom: vec2(2. / screen_width(), -2. / screen_height()),
|
||||
offset: vec2(
|
||||
(th + WIDTH) / screen_width(),
|
||||
((th + HEIGHT) * 0.5) / screen_height(),
|
||||
),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut speedup = false;
|
||||
let mut paused = false;
|
||||
let mut checkbox = false;
|
||||
let mut combobox = 0;
|
||||
let mut text = String::new();
|
||||
let mut number = 0.0;
|
||||
let mut bias = false;
|
||||
let mut showall = false;
|
||||
let mut size = 100;
|
||||
let mut pop = Population::new(size as usize);
|
||||
|
||||
let ui_thick = 34.;
|
||||
|
||||
let skin = {
|
||||
let boxed = root_ui()
|
||||
|
@ -88,6 +84,7 @@ async fn main() {
|
|||
bytes: vec![0; 4],
|
||||
})
|
||||
.background_margin(RectOffset::new(0., 0., 0., 0.))
|
||||
.color_inactive(WHITE)
|
||||
.build();
|
||||
let button_style = boxed
|
||||
.color_hovered(RED)
|
||||
|
@ -96,18 +93,26 @@ async fn main() {
|
|||
.text_color_hovered(WHITE)
|
||||
.text_color_clicked(WHITE)
|
||||
.margin(RectOffset::new(10., 10., 8., 8.))
|
||||
.color_inactive(WHITE)
|
||||
.build();
|
||||
let label_style = root_ui()
|
||||
.style_builder()
|
||||
.text_color(WHITE)
|
||||
.font_size(24)
|
||||
.margin(RectOffset::new(5., 5., 4., 4.))
|
||||
.color_inactive(WHITE)
|
||||
.build();
|
||||
let group_style = root_ui()
|
||||
.style_builder()
|
||||
.color(Color::new(0., 0., 0., 0.))
|
||||
.build();
|
||||
|
||||
Skin {
|
||||
window_style,
|
||||
button_style,
|
||||
label_style,
|
||||
group_style,
|
||||
|
||||
margin: 0.,
|
||||
..root_ui().default_skin()
|
||||
}
|
||||
|
@ -116,6 +121,7 @@ async fn main() {
|
|||
root_ui().push_skin(&skin);
|
||||
loop {
|
||||
clear_background(BLACK);
|
||||
set_camera(&gamecam);
|
||||
if is_key_pressed(KeyCode::S) {
|
||||
speedup = !speedup;
|
||||
}
|
||||
|
@ -136,89 +142,82 @@ async fn main() {
|
|||
WIDTH * 0.5 + th,
|
||||
-HEIGHT * 0.5,
|
||||
screen_width() - WIDTH - 3. * th,
|
||||
34.,
|
||||
ui_thick,
|
||||
2.,
|
||||
WHITE,
|
||||
);
|
||||
draw_rectangle_lines(
|
||||
WIDTH * 0.5 + th,
|
||||
-HEIGHT * 0.5 + (screen_height() - 3. * th) * 0.5 - 34.,
|
||||
-HEIGHT * 0.5 + (screen_height() - 3. * th) * 0.5 - ui_thick,
|
||||
screen_width() - WIDTH - 3. * th,
|
||||
34.,
|
||||
ui_thick,
|
||||
2.,
|
||||
WHITE,
|
||||
);
|
||||
|
||||
set_camera(&maincam);
|
||||
// draw_circle(0., 0., 20., RED);
|
||||
set_camera(&netcam);
|
||||
pop.worlds[0].player.draw_brain(
|
||||
screen_width() - WIDTH - 3. * th,
|
||||
(screen_height() - 3. * th) * 0.5,
|
||||
bias,
|
||||
);
|
||||
set_camera(&statcam);
|
||||
pop.worlds[0].draw_stats(
|
||||
screen_width() - WIDTH - 3. * th,
|
||||
(screen_height() - 7. * th) * 0.5 - 2. * ui_thick,
|
||||
);
|
||||
|
||||
set_camera(&gamecam);
|
||||
let ui_width = screen_width() - WIDTH - 3. * th + 1.;
|
||||
let ui_height = (screen_height() - 3. * th) * 0.5;
|
||||
root_ui().window(
|
||||
hash!(),
|
||||
vec2(WIDTH + 2. * th, th),
|
||||
vec2(screen_width() - WIDTH - 3. * th + 1., 34.),
|
||||
vec2(ui_width, ui_height),
|
||||
|ui| {
|
||||
ui.label(None, &format!("Generation: {}", pop.gen));
|
||||
ui.same_line(278.);
|
||||
widgets::Button::new("Load Model").ui(ui);
|
||||
ui.same_line(0.);
|
||||
widgets::Button::new("Save Model").ui(ui);
|
||||
ui.same_line(0.);
|
||||
if widgets::Button::new(fast).ui(ui) {
|
||||
speedup = !speedup;
|
||||
};
|
||||
ui.same_line(0.);
|
||||
if widgets::Button::new(restart).ui(ui) {
|
||||
pop = Population::new(100);
|
||||
};
|
||||
ui.same_line(0.);
|
||||
if widgets::Button::new(if paused { play } else { pause }).ui(ui) {
|
||||
paused = !paused;
|
||||
};
|
||||
widgets::Group::new(hash!(), Vec2::new(ui_width, ui_thick))
|
||||
.position(Vec2::new(0., 0.))
|
||||
.ui(ui, |ui| {
|
||||
ui.label(None, &format!("Generation: {}", pop.gen));
|
||||
ui.same_line(314.);
|
||||
widgets::Button::new("Load Model").ui(ui);
|
||||
ui.same_line(0.);
|
||||
widgets::Button::new("Save Model").ui(ui);
|
||||
ui.same_line(0.);
|
||||
if widgets::Button::new(fast).ui(ui) {
|
||||
speedup = !speedup;
|
||||
};
|
||||
ui.same_line(0.);
|
||||
if widgets::Button::new(if paused { play } else { pause }).ui(ui) {
|
||||
paused = !paused;
|
||||
};
|
||||
});
|
||||
widgets::Group::new(hash!(), Vec2::new(ui_width, ui_thick))
|
||||
.position(Vec2::new(0., ui_height - ui_thick))
|
||||
.ui(ui, |ui| {
|
||||
ui.label(Some(vec2(0., 2.)), "«Population»");
|
||||
widgets::Group::new(hash!(), Vec2::new(100., ui_thick))
|
||||
.position(Vec2::new(140., 0.))
|
||||
.ui(ui, |ui| {
|
||||
ui.drag(hash!(), "", Some((2, 500)), &mut size);
|
||||
});
|
||||
ui.same_line(364.);
|
||||
if widgets::Button::new(if bias { "Hide Bias" } else { "Show Bias" }).ui(ui)
|
||||
{
|
||||
bias = !bias;
|
||||
};
|
||||
ui.same_line(0.);
|
||||
if widgets::Button::new(if !pop.best { "Show Best" } else { "Show All " })
|
||||
.ui(ui)
|
||||
{
|
||||
pop.best = !pop.best;
|
||||
};
|
||||
ui.same_line(0.);
|
||||
if widgets::Button::new(restart).ui(ui) {
|
||||
pop = Population::new(size as usize);
|
||||
};
|
||||
});
|
||||
},
|
||||
);
|
||||
root_ui().window(
|
||||
hash!(),
|
||||
vec2(WIDTH + 2. * th, (screen_height() - th) * 0.5 - 34.),
|
||||
vec2(screen_width() - WIDTH - 3. * th + 1., 34.),
|
||||
|ui| {
|
||||
ui.label(None, &format!("Generation: {}", pop.gen));
|
||||
ui.same_line(278.);
|
||||
widgets::Button::new("Load Model").ui(ui);
|
||||
ui.same_line(0.);
|
||||
widgets::Button::new("Save Model").ui(ui);
|
||||
ui.same_line(0.);
|
||||
if widgets::Button::new(fast).ui(ui) {
|
||||
speedup = !speedup;
|
||||
};
|
||||
ui.same_line(0.);
|
||||
if widgets::Button::new(restart).ui(ui) {
|
||||
pop = Population::new(100);
|
||||
};
|
||||
ui.same_line(0.);
|
||||
if widgets::Button::new(if paused { play } else { pause }).ui(ui) {
|
||||
paused = !paused;
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
// set_camera(&maincam);
|
||||
// draw_texture_ex(
|
||||
// target.texture,
|
||||
// 0.,
|
||||
// 0.,
|
||||
// Color::new(1., 1., 1., 0.3),
|
||||
// DrawTextureParams {
|
||||
// flip_y: true,
|
||||
// ..Default::default()
|
||||
// },
|
||||
// );
|
||||
// set_camera(&cam);
|
||||
|
||||
next_frame().await;
|
||||
}
|
||||
}
|
||||
|
|
52
src/nn.rs
52
src/nn.rs
|
@ -81,7 +81,7 @@ impl NN {
|
|||
pub fn feed_forward(&self, inputs: &Vec<f32>) -> Vec<f32> {
|
||||
// println!("inputs: {:?}", inputs);
|
||||
let mut y = DMatrix::from_vec(inputs.len(), 1, inputs.to_vec());
|
||||
for i in 0..self.config.len() - 2 {
|
||||
for i in 0..self.config.len() - 1 {
|
||||
y = (&self.weights[i] * y.insert_row(self.config[i] - 1, 1.)).map(|x| {
|
||||
match self.activ_func {
|
||||
ActivationFunc::ReLU => x.max(0.),
|
||||
|
@ -90,13 +90,10 @@ impl NN {
|
|||
}
|
||||
});
|
||||
}
|
||||
let i = self.config.len() - 2;
|
||||
y = (&self.weights[i] * y.insert_row(self.config[i] - 1, 1.))
|
||||
.map(|x| 1. / (1. + (-x).exp()));
|
||||
y.column(0).data.into_slice().to_vec()
|
||||
}
|
||||
|
||||
pub fn draw(&self, width: f32, height: f32, inputs: &Vec<f32>) {
|
||||
pub fn draw(&self, width: f32, height: f32, inputs: &Vec<f32>, outputs: &Vec<f32>, bias: bool) {
|
||||
draw_rectangle_lines(-width * 0.5, -height * 0.5, width, height, 2., WHITE);
|
||||
|
||||
let width = width * 0.8;
|
||||
|
@ -107,14 +104,14 @@ impl NN {
|
|||
for (i, layer) in self
|
||||
.config
|
||||
.iter()
|
||||
// .take(self.config.len() - 1)
|
||||
// .map(|x| x - 1)
|
||||
// .chain(self.config.last().map(|&x| x))
|
||||
.take(self.config.len() - 1)
|
||||
.map(|x| x - if bias { 0 } else { 1 })
|
||||
.chain(self.config.last().map(|&x| x))
|
||||
.enumerate()
|
||||
{
|
||||
p1s = p2s;
|
||||
p2s = Vec::new();
|
||||
for neuron in 0..*layer {
|
||||
for neuron in 0..layer {
|
||||
p2s.push((
|
||||
i as f32 * width / (self.config.len() - 1) as f32 - width * 0.5,
|
||||
neuron as f32 * vspace - (vspace * (layer - 1) as f32) * 0.5,
|
||||
|
@ -122,7 +119,14 @@ impl NN {
|
|||
}
|
||||
for (k, j, p1, p2) in p1s.iter().enumerate().flat_map(|(k, x)| {
|
||||
p2s.iter()
|
||||
.take(p2s.len() - if i == self.config.len() - 1 { 0 } else { 1 })
|
||||
.take(
|
||||
p2s.len()
|
||||
- if i == self.config.len() - 1 || !bias {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
},
|
||||
)
|
||||
.enumerate()
|
||||
.map(move |(j, y)| (k, j, *x, *y))
|
||||
}) {
|
||||
|
@ -133,18 +137,36 @@ impl NN {
|
|||
p1.1,
|
||||
p2.0,
|
||||
p2.1,
|
||||
1.,
|
||||
1.5,
|
||||
Color::new(1., c, c, weight.abs()),
|
||||
);
|
||||
}
|
||||
for p in &p1s {
|
||||
|
||||
let mut inputs = inputs.to_vec();
|
||||
inputs.push(1.);
|
||||
|
||||
for (j, p) in p1s.iter().enumerate() {
|
||||
draw_circle(p.0, p.1, 10., WHITE);
|
||||
draw_circle(p.0, p.1, 9., BLACK);
|
||||
draw_circle(p.0, p.1, 8., BLACK);
|
||||
draw_circle(
|
||||
p.0,
|
||||
p.1,
|
||||
8.,
|
||||
if i == 1 && inputs.len() > 1 {
|
||||
let c = if inputs[j] < 0. { 0. } else { 1. };
|
||||
Color::new(1., c, c, inputs[j].abs())
|
||||
} else {
|
||||
BLACK
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
for p in &p2s {
|
||||
for (j, p) in p2s.iter().enumerate() {
|
||||
draw_circle(p.0, p.1, 10., WHITE);
|
||||
draw_circle(p.0, p.1, 9., BLACK);
|
||||
draw_circle(p.0, p.1, 8., BLACK);
|
||||
if !outputs.is_empty() {
|
||||
draw_circle(p.0, p.1, 8., Color::new(1., 1., 1., outputs[j]));
|
||||
}
|
||||
}
|
||||
draw_rectangle(width * 0.45, height * 0.45, 10., 10., RED);
|
||||
draw_text("-ve", width * 0.45 + 20., height * 0.45 + 10., 20., WHITE);
|
||||
|
|
|
@ -14,7 +14,7 @@ pub struct Player {
|
|||
bullets: Vec<Bullet>,
|
||||
asteroid: Option<Asteroid>,
|
||||
inputs: Vec<f32>,
|
||||
outputs: Vec<bool>,
|
||||
pub outputs: Vec<f32>,
|
||||
// asteroid_data: Vec<(f32, f32, f32)>,
|
||||
last_shot: u8,
|
||||
shot_interval: u8,
|
||||
|
@ -38,7 +38,7 @@ impl Player {
|
|||
alive: true,
|
||||
debug: false,
|
||||
shots: 4,
|
||||
outputs: vec![false; 4],
|
||||
outputs: vec![0.; 4],
|
||||
|
||||
..Default::default()
|
||||
}
|
||||
|
@ -120,13 +120,13 @@ impl Player {
|
|||
self.lifespan += 1;
|
||||
self.last_shot += 1;
|
||||
self.acc = 0.;
|
||||
self.outputs = vec![false; 4];
|
||||
self.outputs = vec![0.; 4];
|
||||
if let Some(ast) = self.asteroid.as_ref() {
|
||||
self.inputs = vec![
|
||||
(ast.pos - self.pos).length() / WIDTH,
|
||||
(ast.pos - self.pos).length() / HEIGHT,
|
||||
self.dir.angle_between(ast.pos - self.pos),
|
||||
(ast.vel - self.vel).x / 11.,
|
||||
(ast.vel - self.vel).y / 11.,
|
||||
(ast.vel - self.vel).x * 0.6,
|
||||
(ast.vel - self.vel).y * 0.6,
|
||||
self.rot / TAU as f32,
|
||||
];
|
||||
|
||||
|
@ -143,25 +143,22 @@ impl Player {
|
|||
// );
|
||||
|
||||
if let Some(brain) = &self.brain {
|
||||
self.outputs = brain
|
||||
.feed_forward(&self.inputs)
|
||||
.iter()
|
||||
.map(|&x| x > 0.85)
|
||||
.collect();
|
||||
self.outputs = brain.feed_forward(&self.inputs);
|
||||
}
|
||||
}
|
||||
if is_key_down(KeyCode::Right) && self.debug || self.outputs[0] {
|
||||
let keys: Vec<bool> = self.outputs.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;
|
||||
self.dir = vec2(self.rot.cos(), self.rot.sin());
|
||||
}
|
||||
if is_key_down(KeyCode::Left) && self.debug || self.outputs[1] {
|
||||
if is_key_down(KeyCode::Left) && self.debug || keys[1] {
|
||||
self.rot = (self.rot - 0.1 + TAU as f32) % TAU as f32;
|
||||
self.dir = vec2(self.rot.cos(), self.rot.sin());
|
||||
}
|
||||
if is_key_down(KeyCode::Up) && self.debug || self.outputs[2] {
|
||||
if is_key_down(KeyCode::Up) && self.debug || keys[2] {
|
||||
self.acc = 0.14;
|
||||
}
|
||||
if is_key_down(KeyCode::Space) && self.debug || self.outputs[3] {
|
||||
if is_key_down(KeyCode::Space) && self.debug || keys[3] {
|
||||
if self.last_shot > self.shot_interval {
|
||||
self.last_shot = 0;
|
||||
self.shots += 1;
|
||||
|
@ -251,9 +248,9 @@ impl Player {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn draw_brain(&self, width: f32, height: f32) {
|
||||
pub fn draw_brain(&self, width: f32, height: f32, bias: bool) {
|
||||
if let Some(brain) = &self.brain {
|
||||
brain.draw(width, height, &self.inputs);
|
||||
brain.draw(width, height, &self.inputs, &self.outputs, bias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::{nn::NN, world::World, HEIGHT, WIDTH};
|
|||
pub struct Population {
|
||||
size: usize,
|
||||
pub gen: i32,
|
||||
best: bool,
|
||||
pub best: bool,
|
||||
pub worlds: Vec<World>,
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ impl Population {
|
|||
println!("Fitness: {}", i.fitness);
|
||||
}
|
||||
println!("Gen: {}, Fitness: {}", self.gen, self.worlds[0].fitness);
|
||||
let mut new_worlds = (0..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())))
|
||||
.collect::<Vec<_>>();
|
||||
new_worlds[0].set_best();
|
||||
|
|
66
src/world.rs
66
src/world.rs
|
@ -82,10 +82,10 @@ impl World {
|
|||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
self.fitness =
|
||||
(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.retain(|asteroid| asteroid.alive);
|
||||
|
@ -120,4 +120,66 @@ impl World {
|
|||
WHITE,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn draw_stats(&self, width: f32, height: f32) {
|
||||
draw_rectangle_lines(-width * 0.5, -height * 0.5, width, height, 2., WHITE);
|
||||
|
||||
let scale = 2.5;
|
||||
let offset = vec2(-width * 0.3, -height * 0.1);
|
||||
let p1 = scale * vec2(0., -20.) + offset;
|
||||
let p2 = scale * vec2(-12.667, 18.) + offset;
|
||||
let p3 = scale * vec2(12.667, 18.) + offset;
|
||||
let p4 = scale * vec2(-10., 10.) + offset;
|
||||
let p5 = scale * vec2(10., 10.) + offset;
|
||||
let p6 = scale * vec2(0., 25.) + offset;
|
||||
let p7 = scale * vec2(-6., 10.) + offset;
|
||||
let p8 = scale * vec2(6., 10.) + offset;
|
||||
|
||||
draw_line(p1.x, p1.y, p2.x, p2.y, 2., WHITE);
|
||||
draw_line(p1.x, p1.y, p3.x, p3.y, 2., WHITE);
|
||||
draw_line(p4.x, p4.y, p5.x, p5.y, 2., WHITE);
|
||||
if self.player.outputs[2] > 0. && (gen_range(0., 1.) < 0.4 || self.over) {
|
||||
draw_triangle_lines(p6, p7, p8, 2., WHITE);
|
||||
}
|
||||
let l1 = scale * vec2(30., 0.) + offset;
|
||||
let l2 = scale * vec2(25., -5.) + offset;
|
||||
let l3 = scale * vec2(25., 5.) + offset;
|
||||
if self.player.outputs[0] > 0. {
|
||||
draw_line(l1.x, l1.y, l2.x, l2.y, 2., WHITE);
|
||||
draw_line(l1.x, l1.y, l3.x, l3.y, 2., WHITE);
|
||||
}
|
||||
let l1 = -scale * vec2(30., 0.) + offset;
|
||||
let l2 = -scale * vec2(25., -5.) + offset;
|
||||
let l3 = -scale * vec2(25., 5.) + offset;
|
||||
if self.player.outputs[1] > 0. {
|
||||
draw_line(l1.x, l1.y, l2.x, l2.y, 2., WHITE);
|
||||
draw_line(l1.x, l1.y, l3.x, l3.y, 2., WHITE);
|
||||
}
|
||||
let l1 = -scale * vec2(0., 35.) + offset;
|
||||
if self.player.outputs[3] > 0. {
|
||||
draw_circle(l1.x, l1.y, 5., WHITE);
|
||||
draw_circle(l1.x, l1.y, 3.5, BLACK);
|
||||
}
|
||||
draw_text(
|
||||
if self.over { "DEAD" } else { "ALIVE" },
|
||||
-width * 0.5 + 20.,
|
||||
75.,
|
||||
24.,
|
||||
if self.over { RED } else { GREEN },
|
||||
);
|
||||
draw_text(
|
||||
&format!("Score: {}", self.score),
|
||||
-width * 0.5 + 20.,
|
||||
100.,
|
||||
24.,
|
||||
WHITE,
|
||||
);
|
||||
draw_text(
|
||||
&format!("Fitness: {:.2}", self.fitness),
|
||||
-width * 0.5 + 20.,
|
||||
125.,
|
||||
24.,
|
||||
WHITE,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue