139 lines
3.9 KiB
JavaScript
139 lines
3.9 KiB
JavaScript
|
class Player {
|
||
|
constructor(position) {
|
||
|
this.position = position;
|
||
|
this.rays = [];
|
||
|
this.rawDistances = [];
|
||
|
this.distances = [];
|
||
|
this.fov = 90;
|
||
|
this.angle = 0;
|
||
|
this.acceleration = 2;
|
||
|
this.momentum = createVector(0, 0, 0);
|
||
|
this.velocity = createVector(0, 0, 0);
|
||
|
this.sight = 300;
|
||
|
this.frontalVelocity = 0;
|
||
|
this.maxVel = 12;
|
||
|
this.dead = false;
|
||
|
this.nn = new NeuralNetwork();
|
||
|
this.predictions = [];
|
||
|
this.slow = 0;
|
||
|
this.fitness = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
show(best) {
|
||
|
let width = 10;
|
||
|
let length = 15;
|
||
|
for (let r of this.rays) {
|
||
|
//r.show();
|
||
|
}
|
||
|
push();
|
||
|
if (!best)
|
||
|
fill(255, 73, 86);
|
||
|
else
|
||
|
fill(66, 129, 255);
|
||
|
noStroke();
|
||
|
translate(this.position.x, this.position.y);
|
||
|
rotate(radians(this.angle));
|
||
|
rect(-width / 2, -length / 2, width, length);
|
||
|
pop();
|
||
|
}
|
||
|
|
||
|
update(vk, hk) {
|
||
|
if (this.distances.length == 9) {
|
||
|
tf.tidy(() => {
|
||
|
this.predictions = this.nn.drive(this.distances);
|
||
|
});
|
||
|
|
||
|
if (this.predictions[0] >= 0) {
|
||
|
hk = '1';
|
||
|
} else {
|
||
|
hk = '0';
|
||
|
}
|
||
|
|
||
|
if (this.predictions[1] >= 0) {
|
||
|
vk = '1';
|
||
|
} else if (this.predictions[1] < 0.25 && this.predictions[1] > -0.25) {
|
||
|
vk = null;
|
||
|
} else {
|
||
|
vk = '0';
|
||
|
}
|
||
|
//print('1: '+this.predictions[0]+' 2: ' + this.predictions[1]);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
const rotationSpeed = 2.5;
|
||
|
if (hk === '1') {
|
||
|
this.angle += rotationSpeed;
|
||
|
}
|
||
|
if (hk === '0') {
|
||
|
this.angle -= rotationSpeed;
|
||
|
}
|
||
|
|
||
|
if (vk == '1') {
|
||
|
this.velocity = p5.Vector.fromAngle(radians(this.angle - 90), 1);
|
||
|
this.momentum.mult(0.975);
|
||
|
} else if (vk == '0') {
|
||
|
this.velocity = createVector(0, 0, 0);
|
||
|
this.momentum.mult(0.9);
|
||
|
} else {
|
||
|
this.velocity = createVector(0, 0, 0);
|
||
|
this.momentum.mult(0.95);
|
||
|
}
|
||
|
|
||
|
if (this.momentum.mag() < 0.1) {
|
||
|
this.slow++;
|
||
|
}
|
||
|
if (this.slow > 15) {
|
||
|
this.dead = true;
|
||
|
}
|
||
|
if (!this.dead) {
|
||
|
this.fitness++;
|
||
|
}
|
||
|
//this.momentum = (this.momentum.sub(this.momentum.mult(0.00001)));
|
||
|
this.momentum.add(this.velocity.mult(0.12));
|
||
|
this.momentum.limit(this.maxVel);
|
||
|
this.position.add(this.momentum);
|
||
|
|
||
|
this.rays = [];
|
||
|
for (let i = -180; i < 180; i += 45) {
|
||
|
this.rays.push(new Ray(this.position.x, this.position.y, radians(i + this.angle), this.sight));
|
||
|
}
|
||
|
|
||
|
for (let r of this.rays) {
|
||
|
for (let w of walls) {
|
||
|
r.cast(w);
|
||
|
}
|
||
|
//r.show();
|
||
|
}
|
||
|
this.rawDistances = [];
|
||
|
for (let i = 0; i < this.rays.length; i++) {
|
||
|
this.rawDistances[i] = this.rays[i].cast();
|
||
|
if (this.rawDistances[i] != null && this.rawDistances[i] < 10)
|
||
|
this.dead = true;
|
||
|
}
|
||
|
this.frontalVelocity = map(this.momentum.mag(), 0, 5, 0, 1);
|
||
|
|
||
|
this.distances = getDistances(this.rawDistances, this.rawDistances.length, this.sight);
|
||
|
this.distances.push(this.frontalVelocity);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
function angleToVector(xCoord, yCoord, angle, length) {
|
||
|
length = typeof length != 'undefined' ? length : 10;
|
||
|
angle = angle * Math.PI / 180; // if you're using degrees instead of radians
|
||
|
return createVector(length * Math.cos(angle) + xCoord, length * Math.sin(angle) + yCoord);
|
||
|
}
|
||
|
|
||
|
function getDistances(distances, l, sight) {
|
||
|
let array = [];
|
||
|
let length = l;
|
||
|
for (let i = 0; i < length; i++) {
|
||
|
if (distances[i] == null)
|
||
|
array[i] = 0;
|
||
|
else
|
||
|
array[i] = map(distances[i], 10, sight, 1, 0);
|
||
|
}
|
||
|
return array;
|
||
|
}
|