File tree Expand file tree Collapse file tree 4 files changed +159
-0
lines changed
examples/NeuroEvolution-flappy-bird Expand file tree Collapse file tree 4 files changed +159
-0
lines changed Original file line number Diff line number Diff line change
1
+ class Bird {
2
+ constructor ( ) {
3
+ // A bird's brain receives 5 inputs and classifies them into one of two labels
4
+ this . brain = ml5 . neuralNetwork ( {
5
+ inputs : 5 ,
6
+ outputs : [ "flap" , "no flap" ] ,
7
+ task : "classification" ,
8
+ neuroEvolution : true ,
9
+ } ) ;
10
+
11
+ // The bird's position (x will be constant)
12
+ this . x = 50 ;
13
+ this . y = 120 ;
14
+
15
+ // Velocity and forces are scalar since the bird only moves along the y-axis
16
+ this . velocity = 0 ;
17
+ this . gravity = 0.5 ;
18
+ this . flapForce = - 10 ;
19
+ }
20
+
21
+ think ( pipes ) {
22
+ let nextPipe = null ;
23
+ for ( let pipe of pipes ) {
24
+ if ( pipe . x > this . x ) {
25
+ nextPipe = pipe ;
26
+ break ;
27
+ }
28
+ }
29
+
30
+ let inputs = [
31
+ this . y / height ,
32
+ this . velocity / height ,
33
+ nextPipe . top / height ,
34
+ nextPipe . bottom / height ,
35
+ ( nextPipe . x - this . x ) / width ,
36
+ ] ;
37
+
38
+ let results = this . brain . classifySync ( inputs ) ;
39
+ if ( results [ 0 ] . label == "flap" ) {
40
+ this . flap ( ) ;
41
+ }
42
+ }
43
+
44
+ // The bird flaps its wings
45
+ flap ( ) {
46
+ this . velocity += this . flapForce ;
47
+ }
48
+
49
+ update ( ) {
50
+ // Add gravity
51
+ this . velocity += this . gravity ;
52
+ this . y += this . velocity ;
53
+ // Dampen velocity
54
+ this . velocity *= 0.9 ;
55
+
56
+ // Handle the "floor"
57
+ if ( this . y > height ) {
58
+ this . y = height ;
59
+ this . velocity = 0 ;
60
+ }
61
+ }
62
+
63
+ show ( ) {
64
+ strokeWeight ( 2 ) ;
65
+ stroke ( 0 ) ;
66
+ fill ( 127 ) ;
67
+ circle ( this . x , this . y , 16 ) ;
68
+ }
69
+ }
Original file line number Diff line number Diff line change
1
+ <!DOCTYPE html>
2
+ < html lang ="en ">
3
+ < head >
4
+ < meta charset ="UTF-8 " />
5
+ < meta http-equiv ="X-UA-Compatible " content ="IE=edge " />
6
+ < meta name ="viewport " content ="width=device-width, initial-scale=1.0 " />
7
+ < title > ml5.js NeuroEvolution Flappy Bird</ title >
8
+ < script src ="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js "> </ script >
9
+ < script src ="../../dist/ml5.js "> </ script >
10
+ </ head >
11
+ < body >
12
+ < script src ="bird.js "> </ script >
13
+ < script src ="pipe.js "> </ script >
14
+ < script src ="sketch.js "> </ script >
15
+ </ body >
16
+ </ html >
Original file line number Diff line number Diff line change
1
+ class Pipe {
2
+ constructor ( ) {
3
+ this . spacing = 75 ;
4
+ this . top = random ( height - this . spacing ) ;
5
+ this . bottom = this . top + this . spacing ;
6
+ this . x = width ;
7
+ this . w = 20 ;
8
+ this . speed = 2 ;
9
+ }
10
+
11
+ collides ( bird ) {
12
+ // Is the bird within the vertical range of the top or bottom pipe?
13
+ let verticalCollision = bird . y < this . top || bird . y > this . bottom ;
14
+ // Is the bird within the horizontal range of the pipes?
15
+ let horizontalCollision = bird . x > this . x && bird . x < this . x + this . w ;
16
+ // If it's both a vertical and horizontal hit, it's a hit!
17
+ return verticalCollision && horizontalCollision ;
18
+ }
19
+
20
+ show ( ) {
21
+ fill ( 0 ) ;
22
+ noStroke ( ) ;
23
+ rect ( this . x , 0 , this . w , this . top ) ;
24
+ rect ( this . x , this . bottom , this . w , height - this . bottom ) ;
25
+ }
26
+
27
+ update ( ) {
28
+ this . x -= this . speed ;
29
+ }
30
+
31
+ offscreen ( ) {
32
+ return this . x < - this . w ;
33
+ }
34
+ }
Original file line number Diff line number Diff line change
1
+ let birds = [ ] ;
2
+ let pipes = [ ] ;
3
+
4
+ function setup ( ) {
5
+ createCanvas ( 640 , 240 ) ;
6
+ for ( let i = 0 ; i < 100 ; i ++ ) {
7
+ birds [ i ] = new Bird ( ) ;
8
+ }
9
+ pipes . push ( new Pipe ( ) ) ;
10
+ ml5 . tf . setBackend ( "cpu" ) ;
11
+ }
12
+
13
+ function draw ( ) {
14
+ background ( 255 ) ;
15
+
16
+ for ( let i = pipes . length - 1 ; i >= 0 ; i -- ) {
17
+ pipes [ i ] . show ( ) ;
18
+ pipes [ i ] . update ( ) ;
19
+
20
+ for ( let bird of birds ) {
21
+ if ( pipes [ i ] . collides ( bird ) ) {
22
+ // text("OOPS!", pipes[i].x, pipes[i].top + 20);
23
+ }
24
+ }
25
+
26
+ if ( pipes [ i ] . offscreen ( ) ) {
27
+ pipes . splice ( i , 1 ) ;
28
+ }
29
+ }
30
+
31
+ for ( let bird of birds ) {
32
+ bird . think ( pipes ) ;
33
+ bird . update ( ) ;
34
+ bird . show ( ) ;
35
+ }
36
+
37
+ if ( frameCount % 75 == 0 ) {
38
+ pipes . push ( new Pipe ( ) ) ;
39
+ }
40
+ }
You can’t perform that action at this time.
0 commit comments