Make flappy bird with Python Play
Demo and Code 👨💻
Flappy bird is one of the classics - and as you'll see, super easy to create, especially when you use the Python Play library developed at repl.it!
If you haven't played flappy bird before, try it out on 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 - 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:
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
:
🌎 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!
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
@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.
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.
# 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()
@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!
for box in boxes:
# make the box move to the left
box.x -= 1
This is what you should see when you hit run!
🤔 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:
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:
if(box.x < (play.screen.left-50)):
boxes.remove(box)
box.remove()
We're just preventing memory leaks 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 😄
Top comments (2)
Awesome! I hadn't seen Python Play before. Looks neat, I'll give it a try. Thanks!
Very nice. I am falling in love with Python more and more.