|
|
|
@ -0,0 +1,224 @@
|
|
|
|
|
# Imports
|
|
|
|
|
import pygame
|
|
|
|
|
from pygame.locals import *
|
|
|
|
|
import random
|
|
|
|
|
|
|
|
|
|
# Font
|
|
|
|
|
pygame.font.init()
|
|
|
|
|
font = pygame.font.SysFont("Bauhaus 93", 60)
|
|
|
|
|
|
|
|
|
|
# Setup
|
|
|
|
|
clock = pygame.time.Clock()
|
|
|
|
|
fps = 60
|
|
|
|
|
screen_width = 864
|
|
|
|
|
screen_height = 936
|
|
|
|
|
screen = pygame.display.set_mode((screen_width, screen_height))
|
|
|
|
|
pygame.display.set_caption("Flappy Bird")
|
|
|
|
|
|
|
|
|
|
# Load Images
|
|
|
|
|
image_background = pygame.image.load("assets/background.png")
|
|
|
|
|
image_ground = pygame.image.load("assets/ground.png")
|
|
|
|
|
image_button = pygame.image.load("assets/restart.png")
|
|
|
|
|
|
|
|
|
|
# Colors
|
|
|
|
|
white = (255, 255, 255)
|
|
|
|
|
|
|
|
|
|
# Game Variables
|
|
|
|
|
scroll = 0
|
|
|
|
|
scroll_speed = 3
|
|
|
|
|
game_over = False
|
|
|
|
|
flying = False
|
|
|
|
|
make_pipes = False
|
|
|
|
|
passed_pipe = False
|
|
|
|
|
pipe_gap = 160
|
|
|
|
|
pipe_frequency = 1500
|
|
|
|
|
last_pipe = pygame.time.get_ticks() - pipe_frequency
|
|
|
|
|
score = 0
|
|
|
|
|
|
|
|
|
|
# Draw Text
|
|
|
|
|
def draw_text(text, x, y):
|
|
|
|
|
image = font.render(text, True, white)
|
|
|
|
|
screen.blit(image, (x, y))
|
|
|
|
|
|
|
|
|
|
# Bird
|
|
|
|
|
class Bird(pygame.sprite.Sprite):
|
|
|
|
|
# Init
|
|
|
|
|
def __init__(self):
|
|
|
|
|
# Variables
|
|
|
|
|
pygame.sprite.Sprite.__init__(self)
|
|
|
|
|
self.images = []
|
|
|
|
|
self.index = 1
|
|
|
|
|
self.counter = 0
|
|
|
|
|
# Images
|
|
|
|
|
for number in range(1, 4):
|
|
|
|
|
image = pygame.image.load(f"assets/bird{number}.png")
|
|
|
|
|
self.images.append(image)
|
|
|
|
|
# Set Position
|
|
|
|
|
self.image = self.images[self.index]
|
|
|
|
|
self.rect = self.image.get_rect()
|
|
|
|
|
self.rect.center = [100, screen_height / 2]
|
|
|
|
|
self.vel = 0
|
|
|
|
|
self.clicked = False
|
|
|
|
|
# Update
|
|
|
|
|
def update(self, game_over):
|
|
|
|
|
# Gravity
|
|
|
|
|
self.vel += 0.5
|
|
|
|
|
if self.vel > 10:
|
|
|
|
|
self.vel = 10
|
|
|
|
|
if self.rect.bottom < 768:
|
|
|
|
|
self.rect.y += int(self.vel)
|
|
|
|
|
elif self.rect.top > 0:
|
|
|
|
|
self.vel = 0
|
|
|
|
|
# Jump
|
|
|
|
|
if game_over == False:
|
|
|
|
|
if pygame.mouse.get_pressed()[0] == 1 and self.clicked == False:
|
|
|
|
|
self.clicked = True
|
|
|
|
|
self.vel = - 10
|
|
|
|
|
elif pygame.mouse.get_pressed()[0] == 0:
|
|
|
|
|
self.clicked = False
|
|
|
|
|
# Animation
|
|
|
|
|
self.counter += 1
|
|
|
|
|
flap_cooldown = 10
|
|
|
|
|
if self.counter > flap_cooldown:
|
|
|
|
|
self.counter = 0
|
|
|
|
|
self.index += 1
|
|
|
|
|
if self.index >= len(self.images):
|
|
|
|
|
self.index = 0
|
|
|
|
|
self.image = self.images[self.index]
|
|
|
|
|
# Rotate Bird
|
|
|
|
|
self.image = pygame.transform.rotate(self.images[self.index], self.vel * - 2)
|
|
|
|
|
|
|
|
|
|
# Pipe
|
|
|
|
|
class Pipe(pygame.sprite.Sprite):
|
|
|
|
|
# Init
|
|
|
|
|
def __init__(self, x, y, position):
|
|
|
|
|
# Variables
|
|
|
|
|
pygame.sprite.Sprite.__init__(self)
|
|
|
|
|
self.image = pygame.image.load("assets/pipe.png")
|
|
|
|
|
self.rect = self.image.get_rect()
|
|
|
|
|
# Create Pipe
|
|
|
|
|
if position == 1:
|
|
|
|
|
self.image = pygame.transform.flip(self.image, False, True)
|
|
|
|
|
self.rect.bottomleft = [x, y - int(pipe_gap / 2)]
|
|
|
|
|
elif position == - 1:
|
|
|
|
|
self.rect.topleft = [x, y + int(pipe_gap / 2)]
|
|
|
|
|
# Update
|
|
|
|
|
def update(self):
|
|
|
|
|
# Scroll Pipes
|
|
|
|
|
self.rect.x -= scroll_speed
|
|
|
|
|
# Delete Pipes
|
|
|
|
|
if self.rect.right < 0:
|
|
|
|
|
self.kill()
|
|
|
|
|
|
|
|
|
|
# Button
|
|
|
|
|
class Button():
|
|
|
|
|
# Init
|
|
|
|
|
def __init__(self):
|
|
|
|
|
# Variables
|
|
|
|
|
self.image = image_button
|
|
|
|
|
self.image = pygame.transform.scale(self.image, (250, 90))
|
|
|
|
|
self.rect = self.image.get_rect()
|
|
|
|
|
self.rect.topleft = (screen_width // 2 - 125, screen_height - 120)
|
|
|
|
|
# Draw
|
|
|
|
|
def draw(self):
|
|
|
|
|
# Mouse Position
|
|
|
|
|
pos = pygame.mouse.get_pos()
|
|
|
|
|
# Display Button
|
|
|
|
|
screen.blit(self.image, (self.rect.x, self.rect.y))
|
|
|
|
|
# When Clicked
|
|
|
|
|
if self.rect.collidepoint(pos):
|
|
|
|
|
if pygame.mouse.get_pressed()[0] == 1:
|
|
|
|
|
return True
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
# Sprite Groups
|
|
|
|
|
bird_group = pygame.sprite.Group()
|
|
|
|
|
pipe_group = pygame.sprite.Group()
|
|
|
|
|
|
|
|
|
|
# Create Bird
|
|
|
|
|
flappy = Bird()
|
|
|
|
|
bird_group.add(flappy)
|
|
|
|
|
|
|
|
|
|
# Create Restart Button
|
|
|
|
|
button = Button()
|
|
|
|
|
|
|
|
|
|
# Initialise Pygame
|
|
|
|
|
pygame.init()
|
|
|
|
|
|
|
|
|
|
# Game Loop
|
|
|
|
|
run = True
|
|
|
|
|
while run:
|
|
|
|
|
# Tick
|
|
|
|
|
clock.tick(fps)
|
|
|
|
|
# Display Background
|
|
|
|
|
screen.blit(image_background, (0, 0))
|
|
|
|
|
pipe_group.draw(screen)
|
|
|
|
|
screen.blit(image_ground, (scroll, 768))
|
|
|
|
|
# Check Score
|
|
|
|
|
if len(pipe_group) > 0:
|
|
|
|
|
if bird_group.sprites()[0].rect.left > pipe_group.sprites()[0].rect.left\
|
|
|
|
|
and bird_group.sprites()[0].rect.right < pipe_group.sprites()[0].rect.right\
|
|
|
|
|
and passed_pipe == False:
|
|
|
|
|
passed_pipe = True
|
|
|
|
|
if passed_pipe == True:
|
|
|
|
|
try:
|
|
|
|
|
if bird_group.sprites()[0].rect.left > pipe_group.sprites()[0].rect.right:
|
|
|
|
|
score += 1
|
|
|
|
|
passed_pipe = False
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
# Game Over
|
|
|
|
|
if game_over == False:
|
|
|
|
|
# Create Pipes
|
|
|
|
|
time_now = pygame.time.get_ticks()
|
|
|
|
|
if time_now - last_pipe > pipe_frequency and make_pipes:
|
|
|
|
|
pipe_height = random.randint(-180, 180)
|
|
|
|
|
bottom_pipe = Pipe(screen_width, int(screen_height / 2) + pipe_height, - 1)
|
|
|
|
|
top_pipe = Pipe(screen_width, int(screen_height / 2) + pipe_height, 1)
|
|
|
|
|
pipe_group.add(bottom_pipe)
|
|
|
|
|
pipe_group.add(top_pipe)
|
|
|
|
|
last_pipe = time_now
|
|
|
|
|
# Scroll
|
|
|
|
|
scroll -= scroll_speed
|
|
|
|
|
pipe_group.update()
|
|
|
|
|
if abs(scroll) > 35:
|
|
|
|
|
scroll = 0
|
|
|
|
|
else:
|
|
|
|
|
# Reset Game
|
|
|
|
|
if button.draw():
|
|
|
|
|
game_over = False
|
|
|
|
|
flying = False
|
|
|
|
|
make_pipes = False
|
|
|
|
|
score = 0
|
|
|
|
|
last_pipe = pygame.time.get_ticks() - pipe_frequency
|
|
|
|
|
bird_group.empty()
|
|
|
|
|
pipe_group.empty()
|
|
|
|
|
flappy.rect.x = 100
|
|
|
|
|
flappy.rect.y = int(screen_height // 2)
|
|
|
|
|
flappy = Bird()
|
|
|
|
|
bird_group.add(flappy)
|
|
|
|
|
# Update Bird
|
|
|
|
|
if pygame.sprite.groupcollide(bird_group, pipe_group, False, False) or flappy.rect.top < 0:
|
|
|
|
|
game_over = True
|
|
|
|
|
if flappy.rect.bottom >= 768:
|
|
|
|
|
game_over = True
|
|
|
|
|
flying = False
|
|
|
|
|
if flying:
|
|
|
|
|
bird_group.update(game_over)
|
|
|
|
|
# Display Bird
|
|
|
|
|
bird_group.draw(screen)
|
|
|
|
|
draw_text(str(score), int(screen_width / 2) - 10, 20)
|
|
|
|
|
# Event Handler
|
|
|
|
|
for event in pygame.event.get():
|
|
|
|
|
# QUIT
|
|
|
|
|
if event.type == pygame.QUIT:
|
|
|
|
|
run = False
|
|
|
|
|
# Start
|
|
|
|
|
if event.type == pygame.MOUSEBUTTONDOWN:
|
|
|
|
|
flying = True
|
|
|
|
|
make_pipes = True
|
|
|
|
|
# Update Display
|
|
|
|
|
pygame.display.update()
|
|
|
|
|
|
|
|
|
|
# Close Window
|
|
|
|
|
pygame.quit()
|