import pygame
from pygame.locals import *
import random
import sys
pygame.init()
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('BatBird')
#define font
font = pygame.font.SysFont('Bauhaus 93', 60)
#define colours
white = (255, 255, 255)
#define game variables
ground_scroll = 0
scroll_speed = 4
flying = False
game_over = False
pipe_gap = 150
pipe_frequency = 1500 #milliseconds
last_pipe = pygame.time.get_ticks() - pipe_frequency
score = 0
pass_pipe = False
#load images
bg = pygame.image.load('img/bg1.png')
ground_img = pygame.image.load('img/ground.png')
button_img = pygame.image.load('img/restart.png')
exit_button_img = pygame.image.load('img/exit.png')
start_img = pygame.image.load('img/start.png')
shop_button_img = pygame.image.load('img/shop_button.png')
shop_img = pygame.image.load('img/shop.png')
start_img = pygame.transform.scale(start_img, (screen_width, screen_height))
pygame.mixer.music.load('sounds/theme.mp3')
pygame.mixer.music.set_volume(0.1)
pygame.mixer.music.play(-1)
sndFall = pygame.mixer.Sound('sounds/fall.wav')
#function for outputting text onto the screen
def draw_text(text, font, text_col, x, y):
img = font.render(text, True, text_col)
screen.blit(img, (x, y))
def reset_game():
global score
pipe_group.empty()
flappy.rect.x = 100
flappy.rect.y = int(screen_height / 2)
score = 0
return score
class Bird(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.images = []
self.index = 0
self.counter = 0
for num in range(1, 4):
img = pygame.image.load(f"img/Batbird{num}.png")
self.images.append(img)
self.image = self.images[self.index]
self.rect = self.image.get_rect()
self.rect.center = [x, y]
self.vel = 0
self.clicked = False
def update(self):
if flying == True:
#apply gravity
self.vel += 0.5
if self.vel > 8:
self.vel = 8
if self.rect.bottom < 768:
self.rect.y += int(self.vel)
if game_over == False:
#jump
if pygame.mouse.get_pressed()[0] == 1 and self.clicked == False:
self.clicked = True
self.vel = -10
if pygame.mouse.get_pressed()[0] == 0:
self.clicked = False
#handle the animation
flap_cooldown = 5
self.counter += 1
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 the bird
self.image = pygame.transform.rotate(self.images[self.index], self.vel * -2)
else:
#point the bird at the ground
self.image = pygame.transform.rotate(self.images[self.index], -90)
class Pipe(pygame.sprite.Sprite):
def __init__(self, x, y, position):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("img/pipe.png")
self.rect = self.image.get_rect()
#position variable determines if the pipe is coming from the bottom or top
#position 1 is from the top, -1 is from the bottom
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)]
def update(self):
self.rect.x -= scroll_speed
if self.rect.right < 0:
self.kill()
class Button():
def __init__(self, x, y, image):
self.image = image
self.rect = self.image.get_rect()
self.rect.topleft = (x, y)
def draw(self):
action = False
#get mouse position
pos = pygame.mouse.get_pos()
#check mouseover and clicked conditions
if self.rect.collidepoint(pos):
if pygame.mouse.get_pressed()[0] == 1:
action = True
#draw button
screen.blit(self.image, (self.rect.x, self.rect.y))
return action
class ExitButton():
def __init__(self, x, y, image):
self.image = image
self.rect = self.image.get_rect()
self.rect.topleft = (x, y)
def draw(self):
action = False
#get mouse position
pos = pygame.mouse.get_pos()
#check mouseover and clicked conditions
if self.rect.collidepoint(pos):
if pygame.mouse.get_pressed()[0] == 1:
action = True
#draw button
screen.blit(self.image, (self.rect.x, self.rect.y))
return action
pipe_group = pygame.sprite.Group()
bird_group = pygame.sprite.Group()
flappy = Bird(100, int(screen_height / 2))
bird_group.add(flappy)
#create restart button instance
restart_button = Button(screen_width // 2 - 50, screen_height // 2 -30, button_img)
exit_button = ExitButton(screen_width // 2 - 50, screen_height // 2 +40, exit_button_img)
shop_button = Button(screen_width // 2 - 50, screen_height // 2 - 100, shop_button_img)
# Shop variables
shop_open = False
start = True
while start:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
start = False
screen.blit(bg, (0, +70))
screen.blit(start_img, (0, +70))
pygame.display.update()
run = True
while run:
clock.tick(fps)
#draw background
screen.blit(bg, (0,0))
pipe_group.update()
pipe_group.draw(screen)
bird_group.draw(screen)
bird_group.update()
#draw and scroll the ground
screen.blit(ground_img, (ground_scroll, 768))
#check the score
if len(pipe_group) > 0:
pipe = pipe_group.sprites()[0]
if bird_group.sprites()[0].rect.left > pipe.rect.left and bird_group.sprites()[0].rect.right < pipe.rect.right and not pass_pipe:
pass_pipe = True
if pass_pipe and bird_group.sprites()[0].rect.left > pipe.rect.right:
score += 1
pass_pipe = False
draw_text(str(score), font, white, int(screen_width / 2), 20)
#look for collision
if pygame.sprite.groupcollide(bird_group, pipe_group, False, False) or flappy.rect.top < 0:
game_over = True
# once the bird has hit the ground it's game over
if flappy.rect.bottom >= 768:
game_over = True
flying = False
if game_over == False and flying == True:
#generate new pipes
time_now = pygame.time.get_ticks()
if time_now - last_pipe > pipe_frequency:
pipe_height = random.randint(-100, 100)
btm_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(btm_pipe)
pipe_group.add(top_pipe)
last_pipe = time_now
ground_scroll -= scroll_speed
if abs(ground_scroll) > 35:
ground_scroll = 0
pipe_group.update()
if game_over == True:
if restart_button.draw():
game_over = False
score = reset_game()
if exit_button.draw():
pygame.quit()
sys.exit()
if shop_button.draw():
screen.blit(shop_img, (0, 0))
pygame.display.update()
pygame.time.wait(3000)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# Обработка события нажатия на кнопку магазина
if event.type == pygame.MOUSEBUTTONDOWN and shop_button.draw():
shop_open = True
if shop_open:
# Создание поверхности с прозрачным фоном
shop_surface = pygame.Surface((screen_width, screen_height), pygame.SRCALPHA)
# Задание пользовательских размеров для растяжения
desired_width = int(screen_width * 1)
desired_height = int(screen_height * 0.5)
# Масштабирование изображения магазина с сохранением пропорций
scaled_shop_img = pygame.transform.smoothscale(shop_img, (desired_width, desired_height))
# Определение координат верхнего левого угла изображения магазина
shop_x = int((screen_width - desired_width) / 2)
shop_y = int((screen_height - desired_height) / 2)
# Нарисовать масштабированное изображение магазина на поверхности
shop_surface.blit(scaled_shop_img, (shop_x, shop_y))
# Отрисовка поверхности магазина на основном окне
screen.blit(shop_surface, (0, 0))
pygame.display.update()
pygame.time.wait(3000)
shop_open = False
if event.type == pygame.MOUSEBUTTONDOWN and flying == False and game_over == False:
flying = True
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN and flying == False and game_over == False:
flying = True
pygame.display.update()