Create a Streamlit app which contain a game, the game should be a flappy bird clone, pygame isn't possible to use since it's a webassambly enviroment
Drop files here
or click to upload
import streamlit as st
import numpy as np
import time
from PIL import Image, ImageDraw
import random
class FlappyBird:
def __init__(self):
self.GAME_WIDTH = 400
self.GAME_HEIGHT = 600
self.BIRD_X = 50
self.BIRD_SIZE = 20
self.PIPE_WIDTH = 50
self.PIPE_GAP = 150
self.GRAVITY = 0.5
self.JUMP_FORCE = -8
self.PIPE_SPEED = 3
# Initialize game state
if 'bird_y' not in st.session_state:
self.reset_game()
def reset_game(self):
st.session_state.bird_y = self.GAME_HEIGHT // 2
st.session_state.bird_velocity = 0
st.session_state.pipes = []
st.session_state.score = 0
st.session_state.game_over = False
st.session_state.last_update = time.time()
# Initialize first pipe
self.add_pipe()
def add_pipe(self):
gap_y = random.randint(100, self.GAME_HEIGHT - 100 - self.PIPE_GAP)
pipe = {
'x': self.GAME_WIDTH,
'gap_y': gap_y,
'passed': False
}
st.session_state.pipes.append(pipe)
def update_game_state(self):
if st.session_state.game_over:
return
current_time = time.time()
dt = current_time - st.session_state.last_update
st.session_state.last_update = current_time
# Update bird position
st.session_state.bird_velocity += self.GRAVITY
st.session_state.bird_y += st.session_state.bird_velocity
# Update pipes
for pipe in st.session_state.pipes:
pipe['x'] -= self.PIPE_SPEED
# Check for score
if not pipe['passed'] and pipe['x'] < self.BIRD_X:
pipe['passed'] = True
st.session_state.score += 1
# Remove off-screen pipes
st.session_state.pipes = [p for p in st.session_state.pipes if p['x'] > -self.PIPE_WIDTH]
# Add new pipes
if not st.session_state.pipes or st.session_state.pipes[-1]['x'] < self.GAME_WIDTH - 200:
self.add_pipe()
# Check collisions
if self.check_collision():
st.session_state.game_over = True
def check_collision(self):
# Check if bird hits the ground or ceiling
if st.session_state.bird_y < 0 or st.session_state.bird_y > self.GAME_HEIGHT:
return True
# Check pipe collisions
for pipe in st.session_state.pipes:
if (self.BIRD_X + self.BIRD_SIZE > pipe['x'] and
self.BIRD_X < pipe['x'] + self.PIPE_WIDTH):
if (st.session_state.bird_y < pipe['gap_y'] or
st.session_state.bird_y + self.BIRD_SIZE > pipe['gap_y'] + self.PIPE_GAP):
return True
return False
def draw_game(self):
# Create a new image
image = Image.new('RGB', (self.GAME_WIDTH, self.GAME_HEIGHT), 'skyblue')
draw = ImageDraw.Draw(image)
# Draw pipes
for pipe in st.session_state.pipes:
# Draw top pipe
draw.rectangle([
pipe['x'],
0,
pipe['x'] + self.PIPE_WIDTH,
pipe['gap_y']
], fill='green')
# Draw bottom pipe
draw.rectangle([
pipe['x'],
pipe['gap_y'] + self.PIPE_GAP,
pipe['x'] + self.PIPE_WIDTH,
self.GAME_HEIGHT
], fill='green')
# Draw bird
draw.ellipse([
self.BIRD_X,
st.session_state.bird_y,
self.BIRD_X + self.BIRD_SIZE,
st.session_state.bird_y + self.BIRD_SIZE
], fill='yellow')
return image
def main():
st.set_page_config(page_title="Flappy Bird", layout="centered")
st.title("Streamlit Flappy Bird")
# Initialize game
game = FlappyBird()
# Create columns for game layout
col1, col2 = st.columns([3, 1])
with col1:
# Display game canvas
canvas = st.empty()
# Display score
score_text = st.empty()
with col2:
# Game controls
if st.button("New Game"):
game.reset_game()
if st.button("Jump"):
if not st.session_state.game_over:
st.session_state.bird_velocity = game.JUMP_FORCE
# Game loop
while not st.session_state.game_over:
game.update_game_state()
canvas.image(game.draw_game())
score_text.text(f"Score: {st.session_state.score}")
time.sleep(0.03) # Control game speed
if st.session_state.game_over:
canvas.image(game.draw_game())
st.error(f"Game Over! Final Score: {st.session_state.score}")
if __name__ == "__main__":
main()
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?