Skip to content

Commit 5194722

Browse files
committed
working on flappy bird example
1 parent 89465e1 commit 5194722

File tree

4 files changed

+159
-0
lines changed

4 files changed

+159
-0
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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+
}

0 commit comments

Comments
 (0)