Flappy Bird, in a new, super easy game framework 🐦
Tags: gamedev, python
Published: 2019-08-24 08:04:20

# Make flappy bird with Python Play

![](https://storage.googleapis.com/replit/images/1566633312709_d7fd16ea4dac17d138efb5825222e7e4.gif)

[Demo and Code](https://repl.it/@jajoosam/flappy-bird) 👨‍💻

Flappy bird is one of the classics - and as you'll see, super easy to create, especially when you use the [Python Play](https://github.com/replit/play) library developed at [repl.it](https://repl.it)! 

If you haven't played flappy bird before, try it out on [flappybird.io](https://flappybird.io/)!

## 🎓 So, how exactly does flappy bird work?

There are two objects which matter in the game - the bird and the pipes. In the demo above, the bird is the yellow circle, while the pipes are the blue rectangles.

**The bird** remains in the same `x` position for the entire game, but can move up when the player presses a key, and continues to fall due to gravity.

**The pipes** are two rectangles with a gap between them - the bird needs to get through the pipes without touching them.

## 🛣️ Get started

Let's begin by forking [repl.it/@jajoosam/play-start](https://repl.it/@jajoosam/play-start) - Which is just a python environment with the `play` dependency installed.

Let's start off creating flappy bird by creating a yellow circle to represent the bird:

```python
bird = play.new_circle(
    color='yellow',
    x=play.screen.left + 100,
    y=play.screen.top - 40,
    radius=30,
)
```

Running that code will result in a `yellow` circle, close to the `top` `left` corner of the screen with a radius of `30`:

![](https://storage.googleapis.com/replit/images/1566633408040_02c2a37f0f00bccc75ba7bfabffe1e41.png)

## 🌎 Physics is... easy!

We want our bird to be affected by gravity, and bounce back up when it falls to the bottom of the screen. So let's create a whole physics engine to do that!

lol jk, just add this one line to your code: `bird.start_physics()`

yep, that's it. really!

![](https://media.giphy.com/media/3oKIPlifLxdigaD2Y8/giphy.gif)

If you run your code now, you'd see a yellow circle falling down, and bouncing back up! We want to be able to make our bird flap though - make it jump when we want to.

We can use `play.repeat_forever` to run a function every frame of our game - and in this case, if the `up` arrow key is pressed, our `bird`'s `y` coordinate increases by `7.5`

```python
@play.repeat_forever
def do():
    if play.key_is_pressed('up'):
        bird.y += 7.5
```

## 🚬 Let's roll the pipes

We're going to create pipes in sets of two, for blocking our birds - and store all of them in a list.

Near the top of your code, add a new line to create this empty list.

```python
boxes = [] 
```

We want the two pipes we generate each time to have different height, and a gap in the middle. We also want to generate the next pair of pipes after a random duration, to make the game more unpredictable.

It'll be very useful for us to use python play's `random_number` function here.

```python
# Returns a integer between 300 and 500
play.random_number(lowest=300, highest=500)

# Returns a float between 1.0 and 3.0
play.random_number(1.0, 4.0)
```

Add this entire block of code, just before `play.start_program()`

```python
@play.repeat_forever
async def block():

    # height of the top block
    top = play.random_number(lowest=300, highest=500)
    # height of the bottom block
    bottom = play.random_number(lowest=300, highest=500)

    # creating the top box of width 50, emerging from behind the current screen
    boxes.append(play.new_box(color="blue", y=play.screen.top,
                              x=play.screen.right+50, width=50, height=top))

    # creating the bottom box of width 50, emerging from behind the current screen
    boxes.append(play.new_box(color="blue", y=play.screen.bottom,
                              x=play.screen.right+50, width=50, height=bottom))

    # creating the next box after a random duration between 1 and 4 seconds
    await play.timer(seconds=play.random_number(1.0, 4.0))
```

This code is inside an `async` function - which is why we can use the `await` keyword to delay each call by a particular duration, with `play.timer` - this lets us create new boxes at an interval! 

With `play.new_box` - we create a new pipe and then append it to the `boxes` list too. Try playing around with the parameters we supply to this function. they should be understandable!

But if you run the code now, you'll notice that everything is the same as before 😕

## 🖥️ Bring the pipes to the screen

Since all our pipes are in the same `boxes` list, we can move all of them pretty easily, by looping over the list.

Adding this block to your code, under `def do():` makes the boxes move through the screen!

```python
for box in boxes:
        # make the box move to the left
        box.x -= 1
```

This is what you should see when you hit run!

![](https://storage.googleapis.com/replit/images/1566633365697_de64ae43d0249c4bf844465aef5aa4e9.gif)

## 🤔 But... when do you lose?!

I'm really going to sell you on python play by explaining how we can detect collisions.

`bird.is_touching(box)` - that's it. No cap 🧢

In our same loop, where we're moving the pipes to the left, just add this condition block:

```python
if bird.is_touching(box):
            box.color = "red"
```

If the bird ever touches the pipe, it's color shall be red!

Also add this block in the loop:

```python
if(box.x < (play.screen.left-50)):
            boxes.remove(box)
            box.remove()
```

We're just preventing [memory leaks](https://en.wikipedia.org/wiki/Memory_leak) with this - if our pipe is out of the screen, let's just remove it!

## 🔮 Things to hack on

- Use pixel art of a bird instead of the yellow circle 👨‍🎨
- Restart the game when the bird touches the pipe ☠️
- Add power-ups to the game 💪
- Add a live score to the screen 💯

Be sure to put down any questions or improvements down in the comments 💬 

And here's all the code for you to go over again - I've annotated it for you too 😄

{% replit @jajoosam/flappy-bird %}