Learning how to play Flappy Bird using ANN and genetic algorithm

I decided to try creating a self-learning algorithm on a simple problem. I know that the solution is an overkill, but nonetheless I wanted to explore the possibilities connected to using GA with ANN.

 

The plan was simple:
1. Capture the screen using OpenCV.
2. Get the X,Y of the bird and columns. Let algorithm know if it’s even playing.
3. Put it into an ANN to make a “decision”
4. Score the ANN basing on the total time played
5. Breed new ANNs using GA on the best parent ANNs
6. Repeat

 

Step zero was finding the right game version to use. I opted for this one. It was mainly due to the fact that you can jump with space and that I was able to slow the game down a little bit by editing its JS script.

  1. Capture the screen using OpenCV.

Capturing the screen using Python’s OpenCV is fairly easy. I put the webbrowser of the left side of the screen, so that the game windows had always the same coordinates (612,162,1090,781). The code:

This gave me the access to the screen, which was saved as an numpy array. Because of that I could apply some logic to find the bird and columns, and also to let the algorithm know if it’s playing or not.

  • Get the X,Y of the bird and columns. Let algorithm know if it’s even playing.

Finding column was done by finding a template column on the screen. I uploaded the column template and read its height and width:

To find a moving and animated bird I could not use template matching, which is a very basic technique. I decided to find the bird by locating the colors that only appear on the bird. It was more of a trial and error approach, but gave me satisfactory results.

To check if algorithm is playing or not, I was looking for the number of points rendered above the bird. If they vanish, it means that the game ended. You can also see the whole algorithm here:

Put it into an ANN to make a “decision”

Ok, so I have X,Y of the bird and columns. I then calculate the distance between the bird and the column in both dimensions. Those will be inputs of our ANNs. I create random ANNs using this and this script.

This line creates 10 ANNs, which make the first population:

Then I play the game in a loop, with i being the counter for iterations. To make a decision I feed the ANN our inputs and act basing on the result:

Score the ANN basing on the total time played

To score an ANN I calculate the time between a start and an end of a game. The clock starts ticking, when the algorithm clicks space in menu and stops when the bird dies. Ranking_sieci is a list with both ANNs and their scores. When sorted by scores it is the list of best parents, that will breed.

Breed new ANNs using GA on the best parent ANNs

Basing on the best scores, I use crossover and mutate methods by invoking create_new_pop method from evolution.py file:

If less than 2 ANNs passed minimum requirements, I create a new random list of ANNs and insert into it mutations of the best ANN from the previous population. This is done to not lose on the previous learnings.

Repeat

After creating a new population, I set the i to 0, to make the loop run again.

The results are surprisingly good. After only a few generations the algorithm became “good enough” being able to play for as long as I cared to wait 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *