mrm8488 commited on
Commit
b34b125
1 Parent(s): 04b84ba

First commit

Browse files
Files changed (10) hide show
  1. background.png +0 -0
  2. bird.js +77 -0
  3. ga.js +37 -0
  4. index.html +17 -22
  5. nn.js +85 -0
  6. pipe.js +40 -0
  7. screenshots/nn.png +0 -0
  8. screenshots/sc1.png +0 -0
  9. screenshots/sc2.png +0 -0
  10. sketch.js +101 -0
background.png ADDED
bird.js ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Neuro-Evolution Flappy Bird with TensorFlow.js
2
+ // http://thecodingtrain.com
3
+ // https://youtu.be/cdUNkwXx-I4
4
+
5
+ class Bird {
6
+ constructor(brain) {
7
+ this.y = height / 2;
8
+ this.x = 64;
9
+
10
+ this.gravity = 0.8;
11
+ this.lift = -12;
12
+ this.velocity = 0;
13
+
14
+ this.score = 0;
15
+ this.fitness = 0;
16
+ if (brain) {
17
+ this.brain = brain.copy();
18
+ } else {
19
+ this.brain = new NeuralNetwork(5, 8, 2);
20
+ }
21
+ }
22
+
23
+ dispose() {
24
+ this.brain.dispose();
25
+ }
26
+
27
+ show() {
28
+ stroke(255);
29
+ fill(251, 236, 93);
30
+ ellipse(this.x, this.y, 32, 32);
31
+ }
32
+
33
+ up() {
34
+ this.velocity += this.lift;
35
+ }
36
+
37
+ mutate() {
38
+ this.brain.mutate(0.1);
39
+ }
40
+
41
+ think(pipes) {
42
+ // Find the closest pipe
43
+ let closest = null;
44
+ let closestD = Infinity;
45
+ for (let i = 0; i < pipes.length; i++) {
46
+ let d = pipes[i].x + pipes[i].w - this.x;
47
+ if (d < closestD && d > 0) {
48
+ closest = pipes[i];
49
+ closestD = d;
50
+ }
51
+ }
52
+
53
+ let inputs = [];
54
+ inputs[0] = this.y / height;
55
+ inputs[1] = closest.top / height;
56
+ inputs[2] = closest.bottom / height;
57
+ inputs[3] = closest.x / width;
58
+ inputs[4] = this.velocity / 10;
59
+ let output = this.brain.predict(inputs);
60
+ //if (output[0] > output[1] && this.velocity >= 0) {
61
+ if (output[0] > output[1]) {
62
+ this.up();
63
+ }
64
+ }
65
+
66
+ offScreen() {
67
+ return this.y > height || this.y < 0;
68
+ }
69
+
70
+ update() {
71
+ this.score++;
72
+
73
+ this.velocity += this.gravity;
74
+ //this.velocity *= 0.9;
75
+ this.y += this.velocity;
76
+ }
77
+ }
ga.js ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Neuro-Evolution Flappy Bird
2
+
3
+ function nextGeneration() {
4
+ console.log("next generation");
5
+ calculateFitness();
6
+ for (let i = 0; i < TOTAL; i++) {
7
+ birds[i] = pickOne();
8
+ }
9
+ for (let i = 0; i < TOTAL; i++) {
10
+ savedBirds[i].dispose();
11
+ }
12
+ savedBirds = [];
13
+ }
14
+
15
+ function pickOne() {
16
+ let index = 0;
17
+ let r = random(1);
18
+ while (r > 0) {
19
+ r = r - savedBirds[index].fitness;
20
+ index++;
21
+ }
22
+ index--;
23
+ let bird = savedBirds[index];
24
+ let child = new Bird(bird.brain);
25
+ child.mutate();
26
+ return child;
27
+ }
28
+
29
+ function calculateFitness() {
30
+ let sum = 0;
31
+ for (let bird of savedBirds) {
32
+ sum += bird.score;
33
+ }
34
+ for (let bird of savedBirds) {
35
+ bird.fitness = bird.score / sum;
36
+ }
37
+ }
index.html CHANGED
@@ -1,24 +1,19 @@
1
  <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>
13
- You can modify this app directly by editing <i>index.html</i> in the
14
- Files and versions tab.
15
- </p>
16
- <p>
17
- Also don't forget to check the
18
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank"
19
- >Spaces documentation</a
20
- >.
21
- </p>
22
- </div>
23
- </body>
24
  </html>
 
1
  <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta http-equiv="X-UA-Compatible" content="ie=edge" />
7
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.min.js"></script>
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/addons/p5.dom.min.js"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.0.4/dist/tf.min.js"></script>
10
+ <title>NeuroEvolution with tf.js</title>
11
+ </head>
12
+ <body>
13
+ <script src="nn.js"></script>
14
+ <script src="bird.js"></script>
15
+ <script src="pipe.js"></script>
16
+ <script src="ga.js"></script>
17
+ <script src="sketch.js"></script>
18
+ </body>
 
 
 
 
 
19
  </html>
nn.js ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Neuro-Evolution Flappy Bird with TensorFlow.js
2
+
3
+ class NeuralNetwork {
4
+ constructor(a, b, c, d) {
5
+ if (a instanceof tf.Sequential) {
6
+ this.model = a;
7
+ this.input_nodes = b;
8
+ this.hidden_nodes = c;
9
+ this.output_nodes = d;
10
+ } else {
11
+ this.input_nodes = a;
12
+ this.hidden_nodes = b;
13
+ this.output_nodes = c;
14
+ this.model = this.createModel();
15
+ }
16
+ }
17
+
18
+ copy() {
19
+ return tf.tidy(() => {
20
+ const modelCopy = this.createModel();
21
+ const weights = this.model.getWeights();
22
+ const weightCopies = [];
23
+ for (let i = 0; i < weights.length; i++) {
24
+ weightCopies[i] = weights[i].clone();
25
+ }
26
+ modelCopy.setWeights(weightCopies);
27
+ return new NeuralNetwork(
28
+ modelCopy,
29
+ this.input_nodes,
30
+ this.hidden_nodes,
31
+ this.output_nodes
32
+ );
33
+ });
34
+ }
35
+
36
+ mutate(rate) {
37
+ tf.tidy(() => {
38
+ const weights = this.model.getWeights();
39
+ const mutatedWeights = [];
40
+ for (let i = 0; i < weights.length; i++) {
41
+ let tensor = weights[i];
42
+ let shape = weights[i].shape;
43
+ let values = tensor.dataSync().slice();
44
+ for (let j = 0; j < values.length; j++) {
45
+ if (random(1) < rate) {
46
+ let w = values[j];
47
+ values[j] = w + randomGaussian();
48
+ }
49
+ }
50
+ let newTensor = tf.tensor(values, shape);
51
+ mutatedWeights[i] = newTensor;
52
+ }
53
+ this.model.setWeights(mutatedWeights);
54
+ });
55
+ }
56
+
57
+ dispose() {
58
+ this.model.dispose();
59
+ }
60
+
61
+ predict(inputs) {
62
+ return tf.tidy(() => {
63
+ const xs = tf.tensor2d([inputs]);
64
+ const ys = this.model.predict(xs);
65
+ const outputs = ys.dataSync();
66
+ return outputs;
67
+ });
68
+ }
69
+
70
+ createModel() {
71
+ const model = tf.sequential();
72
+ const hidden = tf.layers.dense({
73
+ units: this.hidden_nodes,
74
+ inputShape: [this.input_nodes],
75
+ activation: "sigmoid"
76
+ });
77
+ model.add(hidden);
78
+ const output = tf.layers.dense({
79
+ units: this.output_nodes,
80
+ activation: "softmax"
81
+ });
82
+ model.add(output);
83
+ return model;
84
+ }
85
+ }
pipe.js ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Neuro-Evolution Flappy Bird with TensorFlow.js
2
+
3
+ class Pipe {
4
+ constructor() {
5
+ this.spacing = 125;
6
+ this.top = random(height / 6, (3 / 4) * height);
7
+ this.bottom = height - (this.top + this.spacing);
8
+ this.x = width;
9
+ this.w = 80;
10
+ this.speed = 6;
11
+ }
12
+
13
+ hits(bird) {
14
+ if (bird.y < this.top || bird.y > height - this.bottom) {
15
+ if (bird.x > this.x && bird.x < this.x + this.w) {
16
+ return true;
17
+ }
18
+ }
19
+ return false;
20
+ }
21
+
22
+ show() {
23
+ fill(75, 127, 83);
24
+ rectMode(CORNER);
25
+ rect(this.x, 0, this.w, this.top);
26
+ rect(this.x, height - this.bottom, this.w, this.bottom);
27
+ }
28
+
29
+ update() {
30
+ this.x -= this.speed;
31
+ }
32
+
33
+ offscreen() {
34
+ if (this.x < -this.w) {
35
+ return true;
36
+ } else {
37
+ return false;
38
+ }
39
+ }
40
+ }
screenshots/nn.png ADDED
screenshots/sc1.png ADDED
screenshots/sc2.png ADDED
sketch.js ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Daniel Shiffman & Manuel Romero
2
+ // Neuro-Evolution Flappy Bird with TensorFlow.js
3
+ // http://thecodingtrain.com
4
+ // https://youtu.be/cdUNkwXx-I4
5
+
6
+ const TOTAL = 250;
7
+ let birds = [];
8
+ let savedBirds = [];
9
+ let pipes = [];
10
+ let counter = 0;
11
+
12
+ let bg;
13
+ let slider;
14
+ let displayGeneration;
15
+ let displaySpeed;
16
+ let generationNumber = 1;
17
+
18
+ function keyPressed() {
19
+ if (key === "S" || key === "s") {
20
+ let bird = birds[0];
21
+ saveJSON(bird.brain, "bird.json");
22
+ }
23
+ }
24
+
25
+ function setup() {
26
+ bg = loadImage("background.png");
27
+ createCanvas(640, 480);
28
+ displayGeneration = createP("Generation");
29
+ displaySpeed = createP("Speed");
30
+ slider = createSlider(1, 10, 1);
31
+ for (let i = 0; i < TOTAL; i++) {
32
+ birds[i] = new Bird();
33
+ }
34
+
35
+ tf.setBackend('cpu');
36
+ }
37
+
38
+ function draw() {
39
+ for (let n = 0; n < slider.value(); n++) {
40
+ if (counter % 75 == 0) {
41
+ pipes.push(new Pipe());
42
+ }
43
+ counter++;
44
+
45
+ for (let i = pipes.length - 1; i >= 0; i--) {
46
+ pipes[i].update();
47
+
48
+ for (let j = birds.length - 1; j >= 0; j--) {
49
+ if (pipes[i].hits(birds[j])) {
50
+ savedBirds.push(birds.splice(j, 1)[0]);
51
+ }
52
+ }
53
+
54
+ if (pipes[i].offscreen()) {
55
+ pipes.splice(i, 1);
56
+ }
57
+ }
58
+
59
+ for (let i = birds.length - 1; i >= 0; i--) {
60
+ if (birds[i].offScreen()) {
61
+ savedBirds.push(birds.splice(i, 1)[0]);
62
+ }
63
+ }
64
+
65
+ for (let bird of birds) {
66
+ bird.think(pipes);
67
+ bird.update();
68
+ }
69
+
70
+ if (birds.length === 0) {
71
+ counter = 0;
72
+ generationNumber++;
73
+ nextGeneration();
74
+ pipes = [];
75
+ }
76
+ }
77
+
78
+ // All the drawing stuff
79
+ background(bg);
80
+
81
+ displayGeneration.html(
82
+ `Generation Number: <strong>${generationNumber}</strong>`
83
+ );
84
+
85
+ displaySpeed.html(`Speed:`);
86
+
87
+ for (let bird of birds) {
88
+ bird.show();
89
+ }
90
+
91
+ for (let pipe of pipes) {
92
+ pipe.show();
93
+ }
94
+ }
95
+
96
+ // function keyPressed() {
97
+ // if (key == ' ') {
98
+ // bird.up();
99
+ // //console.log("SPACE");
100
+ // }
101
+ // }