Flappy Bird là một trò chơi quen thuộc và từng tạo nên cơn sốt ở nhiều nơi trên toàn thế giới. Trong trò chơi này, mục tiêu chính của người chơi là đạt được càng nhiều càng tốt, bằng cách bảo vệ chú chim khỏi va chạm vào các chướng ngại vật. Bài viết này sẽ hướng dẫn cách tạo trò chơi Flappy Bird bằng Python, sử dụng thư viện Pygame.
Pygame là một thư viện mã nguồn mở được thiết kế để tạo các trò chơi điện tử. Nó giúp người dùng tạo các trò chơi và chương trình đa phương tiện đầy đủ chức năng trong Python.
Bước 1: Tạo tên dự án.
Đầu tiên, khi hoàn tất cài đặt Pycharm IDE trong máy tính của mình, hãy mở nó, tạo một dự án, nhập tên và nhấn vào nút Create.
Bước 2: Tạo tệp Python.
Sau khi tạo dự án, hãy nhấp chuột phải vào tên dự án của mình, chọn New và nhấn Python file.
Bước 3: Đặt tên cho tệp Python và chọn Enter.
Bước 1: Cài đặt thư viện Pygame bằng lệnh:
pip install pygame
Bước 2: Thiết lập chiều cao và chiều rộng của màn hình trò chơi. Sau đó, xác định một số hình ảnh sẽ sử dụng trong trò chơi của mình như đường ống làm chướng ngại vật, hình ảnh những con chim và hình nền bối cảnh.
# For generating random height of pipes
import random
import sys
import pygame
from pygame.locals import *
# Global Variables for the game
window_width = 600
window_height = 499
# set height and width of window
window = pygame.display.set_mode((window_width, window_height))
elevation = window_height * 0.8
game_images = {}
framepersecond = 32
pipeimage = 'images/pipe.png'
background_image = 'images/background.jpg'
birdplayer_image = '/images/bird.png'
sealevel_image = '/images/base.jfif'
Mọi người có thể tải xuống thư mục hình ảnh đầy đủ cần có cho Flappy Bird trong link này.
Bước 3: Sau khi khai báo các biến trò chơi và nhập thư viện, đã đến lúc khởi tạo Pygame.
Khởi tạo chương trình bằng pygame.init () và đặt chú thích của cửa sổ. Ở đây pygame.time.Clock () sẽ được sử dụng thêm trong vòng lặp chính của trò chơi để thay đổi tốc độ của chú chim. Tải hình ảnh từ hệ thống trong Pygame bằng cách sử dụng pygame.image.load ().
# program where the game starts
if __name__ == "__main__":
# For initializing modules of pygame library
pygame.init()
framepersecond_clock = pygame.time.Clock()
# Sets the title on top of game window
pygame.display.set_caption('Flappy Bird Game')
# Load all the images which we will use in the game
# images for displaying score
game_images['scoreimages'] = (
pygame.image.load('images/0.png').convert_alpha(),
pygame.image.load('images/1.png').convert_alpha(),
pygame.image.load('images/2.png').convert_alpha(),
pygame.image.load('images/3.png').convert_alpha(),
pygame.image.load('images/4.png').convert_alpha(),
pygame.image.load('images/5.png').convert_alpha(),
pygame.image.load('images/6.png').convert_alpha(),
pygame.image.load('images/7.png').convert_alpha(),
pygame.image.load('images/8.png').convert_alpha(),
pygame.image.load('images/9.png').convert_alpha()
)
game_images['flappybird'] = pygame.image.load(birdplayer_image).convert_alpha()
game_images['sea_level'] = pygame.image.load(sealevel_image).convert_alpha()
game_images['background'] = pygame.image.load(background_image).convert_alpha()
game_images['pipeimage'] = (pygame.transform.rotate(pygame.image.load(pipeimage)
.convert_alpha(),
180),
pygame.image.load(pipeimage).convert_alpha())
print("WELCOME TO THE FLAPPY BIRD GAME")
print("Press space or enter to start the game")
Bước 4: Khởi tạo vị trí của chú chim và bắt đầu vòng lặp trò chơi
Khởi tạo vị trí của chim và mực nước biển so với mặt đất. Thêm điều kiện trong vòng lặp xác định các điều kiện trò chơi. Biến chiều ngang và chiều dọc được sử dụng để đặt vị trí của con chim. Chương trình phải chạy cho đến khi người dùng dừng hoặc thoát (sử dụng sys.exit ()) và tạo một vòng lặp while vô hạn.
while True:
# sets the coordinates of flappy bird
horizontal = int(window_width/5)
vertical = int((window_height - game_images['flappybird'].get_height())/2)
# for selevel
ground = 0
while True:
for event in pygame.event.get():
# if user clicks on cross button, close the game
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
# Exit the program
sys.exit()
# If the user presses space or up key,
# start the game for them
elif event.type == KEYDOWN and (event.key == K_SPACE or event.key == K_UP):
flappygame()
# if user doesn't press anykey Nothing happen
else:
window.blit(game_images['background'], (0, 0))
window.blit(game_images['flappybird'], (horizontal, vertical))
window.blit(game_images['sea_level'], (ground, elevation))
# Just Refresh the screen
pygame.display.update()
# set the rate of frame per second
framepersecond_clock.tick(framepersecond)
Bước 5: Tạo một hàm tạo để thiết lập đường ống mới có chiều cao ngẫu nhiên.
Trước hết, phải đặt chiều cao của đường ống bằng cách sử dụng hàm getheight (). Sau đó, tạo ra một số ngẫu nhiên từ 0 đến một số bất kỳ (sao cho chiều cao của đường ống có thể điều chỉnh được theo chiều cao cửa sổ trò chơi). Sau đó, tạo một danh sách các từ điển có chứa tọa độ của các đường ống trên và dưới và return nó.
def createPipe():
offset = window_height/3
pipeHeight = game_images['pipeimage'][0].get_height()
# generating random height of pipes
y2 = offset + random.randrange(
0, int(window_height - game_images['sea_level'].get_height() - 1.2 * offset))
pipeX = window_width + 10
y1 = pipeHeight - y2 + offset
pipe = [
# upper Pipe
{'x': pipeX, 'y': -y1},
# lower Pipe
{'x': pipeX, 'y': y2}
]
return pipe
Bước 6: Tạo một hàm GameOver () đại diện cho việc con chim đã rơi trúng ống hay rơi xuống biển.
# Checking if bird is above the sealevel.
def isGameOver(horizontal, vertical, up_pipes, down_pipes):
if vertical > elevation - 25 or vertical < 0:
return True
# Checking if bird hits the upper pipe or not
for pipe in up_pipes:
pipeHeight = game_images['pipeimage'][0].get_height()
if(vertical < pipeHeight + pipe['y']
and abs(horizontal - pipe['x']) < game_images['pipeimage'][0].get_width()):
return True
# Checking if bird hits the lower pipe or not
for pipe in down_pipes:
if (vertical + game_images['flappybird'].get_height() > pipe['y'])
and abs(horizontal - pipe['x']) < game_images['pipeimage'][0].get_width():
return True
return False
Bước 7: Tạo hàm chính (flappygame ()).
Khởi tạo các biến và tạo 2 đường ống bằng hàm createPipe (). Tạo 2 danh sách đầu tiên là các đường ống thấp hơn. Xác định vận tốc chú chim tối đa và tối thiểu.
Xử lý các sự kiện quan trọng bằng cách sử dụng pygame.event.get () và kiểm tra xem trò chơi đã kết thúc hay chưa nếu nó quá thời gian trả về từ hàm. Cập nhật điểm số và hình ảnh trò chơi như nền, đường ống và chim trên cửa sổ.
def flappygame():
your_score = 0
horizontal = int(window_width/5)
vertical = int(window_width/2)
ground = 0
mytempheight = 100
# Generating two pipes for blitting on window
first_pipe = createPipe()
second_pipe = createPipe()
# List containing lower pipes
down_pipes = [
{'x': window_width+300-mytempheight,
'y': first_pipe[1]['y']},
{'x': window_width+300-mytempheight+(window_width/2),
'y': second_pipe[1]['y']},
]
# List Containing upper pipes
up_pipes = [
{'x': window_width+300-mytempheight,
'y': first_pipe[0]['y']},
{'x': window_width+200-mytempheight+(window_width/2),
'y': second_pipe[0]['y']},
]
pipeVelX = -4 #pipe velocity along x
bird_velocity_y = -9 # bird velocity
bird_Max_Vel_Y = 10
bird_Min_Vel_Y = -8
birdAccY = 1
# velocity while flapping
bird_flap_velocity = -8
# It is true only when the bird is flapping
bird_flapped = False
while True:
# Handling the key pressing events
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
if event.type == KEYDOWN and (event.key == K_SPACE or event.key == K_UP):
if vertical > 0:
bird_velocity_y = bird_flap_velocity
bird_flapped = True
# This function will return true if the flappybird is crashed
game_over = isGameOver(horizontal, vertical, up_pipes, down_pipes)
if game_over:
return
# check for your_score
playerMidPos = horizontal + game_images['flappybird'].get_width()/2
for pipe in up_pipes:
pipeMidPos = pipe['x'] + game_images['pipeimage'][0].get_width()/2
if pipeMidPos <= playerMidPos < pipeMidPos + 4:
# Printing the score
your_score += 1
print(f"Your your_score is {your_score}")
if bird_velocity_y < bird_Max_Vel_Y and not bird_flapped:
bird_velocity_y += birdAccY
if bird_flapped:
bird_flapped = False
playerHeight = game_images['flappybird'].get_height()
vertical = vertical + min(bird_velocity_y, elevation - vertical - playerHeight)
# move pipes to the left
for upperPipe, lowerPipe in zip(up_pipes, down_pipes):
upperPipe['x'] += pipeVelX
lowerPipe['x'] += pipeVelX
# Add a new pipe when the first is about
# to cross the leftmost part of the screen
if 0 < up_pipes[0]['x'] < 5:
newpipe = createPipe()
up_pipes.append(newpipe[0])
down_pipes.append(newpipe[1])
# if the pipe is out of the screen, remove it
if up_pipes[0]['x'] < -game_images['pipeimage'][0].get_width():
up_pipes.pop(0)
down_pipes.pop(0)
# Lets blit our game images now
window.blit(game_images['background'], (0, 0))
for upperPipe, lowerPipe in zip(up_pipes, down_pipes):
window.blit(game_images['pipeimage'][0],
(upperPipe['x'], upperPipe['y']))
window.blit(game_images['pipeimage'][1],
(lowerPipe['x'], lowerPipe['y']))
window.blit(game_images['sea_level'], (ground, elevation))
window.blit(game_images['flappybird'], (horizontal, vertical))
# Fetching the digits of score.
numbers = [int(x) for x in list(str(your_score))]
width = 0
# finding the width of score images from numbers.
for num in numbers:
width += game_images['scoreimages'][num].get_width()
Xoffset = (window_width - width)/1.1
# Blitting the images on the window.
for num in numbers:
window.blit(game_images['scoreimages'][num], (Xoffset, window_width*0.02))
Xoffset += game_images['scoreimages'][num].get_width()
# Refreshing the game window and displaying the score.
pygame.display.update()
# Set the framepersecond
framepersecond_clock.tick(framepersecond)
Dưới đây là cách triển khai code game Flappy Bird đầy đủ trong Python bằng Pygame.
# Import module
import random
import sys
import pygame
from pygame.locals import *
# All the Game Variables
window_width = 600
window_height = 499
# set height and width of window
window = pygame.display.set_mode((window_width, window_height))
elevation = window_height * 0.8
game_images = {}
framepersecond = 32
pipeimage = 'images/pipe.png'
background_image = 'images/background.jpg'
birdplayer_image = 'images/bird.png'
sealevel_image = 'images/base.jfif'
def flappygame():
your_score = 0
horizontal = int(window_width/5)
vertical = int(window_width/2)
ground = 0
mytempheight = 100
# Generating two pipes for blitting on window
first_pipe = createPipe()
second_pipe = createPipe()
# List containing lower pipes
down_pipes = [
{'x': window_width+300-mytempheight,
'y': first_pipe[1]['y']},
{'x': window_width+300-mytempheight+(window_width/2),
'y': second_pipe[1]['y']},
]
# List Containing upper pipes
up_pipes = [
{'x': window_width+300-mytempheight,
'y': first_pipe[0]['y']},
{'x': window_width+200-mytempheight+(window_width/2),
'y': second_pipe[0]['y']},
]
# pipe velocity along x
pipeVelX = -4
# bird velocity
bird_velocity_y = -9
bird_Max_Vel_Y = 10
bird_Min_Vel_Y = -8
birdAccY = 1
bird_flap_velocity = -8
bird_flapped = False
while True:
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
if event.type == KEYDOWN and (event.key == K_SPACE or event.key == K_UP):
if vertical > 0:
bird_velocity_y = bird_flap_velocity
bird_flapped = True
# This function will return true
# if the flappybird is crashed
game_over = isGameOver(horizontal,
vertical,
up_pipes,
down_pipes)
if game_over:
return
# check for your_score
playerMidPos = horizontal + game_images['flappybird'].get_width()/2
for pipe in up_pipes:
pipeMidPos = pipe['x'] + game_images['pipeimage'][0].get_width()/2
if pipeMidPos <= playerMidPos < pipeMidPos + 4:
your_score += 1
print(f"Your your_score is {your_score}")
if bird_velocity_y < bird_Max_Vel_Y and not bird_flapped:
bird_velocity_y += birdAccY
if bird_flapped:
bird_flapped = False
playerHeight = game_images['flappybird'].get_height()
vertical = vertical + \
min(bird_velocity_y, elevation - vertical - playerHeight)
# move pipes to the left
for upperPipe, lowerPipe in zip(up_pipes, down_pipes):
upperPipe['x'] += pipeVelX
lowerPipe['x'] += pipeVelX
# Add a new pipe when the first is
# about to cross the leftmost part of the screen
if 0 < up_pipes[0]['x'] < 5:
newpipe = createPipe()
up_pipes.append(newpipe[0])
down_pipes.append(newpipe[1])
# if the pipe is out of the screen, remove it
if up_pipes[0]['x'] < -game_images['pipeimage'][0].get_width():
up_pipes.pop(0)
down_pipes.pop(0)
# Lets blit our game images now
window.blit(game_images['background'], (0, 0))
for upperPipe, lowerPipe in zip(up_pipes, down_pipes):
window.blit(game_images['pipeimage'][0],
(upperPipe['x'], upperPipe['y']))
window.blit(game_images['pipeimage'][1],
(lowerPipe['x'], lowerPipe['y']))
window.blit(game_images['sea_level'], (ground, elevation))
window.blit(game_images['flappybird'], (horizontal, vertical))
# Fetching the digits of score.
numbers = [int(x) for x in list(str(your_score))]
width = 0
# finding the width of score images from numbers.
for num in numbers:
width += game_images['scoreimages'][num].get_width()
Xoffset = (window_width - width)/1.1
# Blitting the images on the window.
for num in numbers:
window.blit(game_images['scoreimages'][num],
(Xoffset, window_width*0.02))
Xoffset += game_images['scoreimages'][num].get_width()
# Refreshing the game window and displaying the score.
pygame.display.update()
framepersecond_clock.tick(framepersecond)
def isGameOver(horizontal, vertical, up_pipes, down_pipes):
if vertical > elevation - 25 or vertical < 0:
return True
for pipe in up_pipes:
pipeHeight = game_images['pipeimage'][0].get_height()
if(vertical < pipeHeight + pipe['y'] and\
abs(horizontal - pipe['x']) < game_images['pipeimage'][0].get_width()):
return True
for pipe in down_pipes:
if (vertical + game_images['flappybird'].get_height() > pipe['y']) and\
abs(horizontal - pipe['x']) < game_images['pipeimage'][0].get_width():
return True
return False
def createPipe():
offset = window_height/3
pipeHeight = game_images['pipeimage'][0].get_height()
y2 = offset + \
random.randrange(
0, int(window_height - game_images['sea_level'].get_height() - 1.2 * offset))
pipeX = window_width + 10
y1 = pipeHeight - y2 + offset
pipe = [
# upper Pipe
{'x': pipeX, 'y': -y1},
# lower Pipe
{'x': pipeX, 'y': y2}
]
return pipe
# program where the game starts
if __name__ == "__main__":
# For initializing modules of pygame library
pygame.init()
framepersecond_clock = pygame.time.Clock()
# Sets the title on top of game window
pygame.display.set_caption('Flappy Bird Game')
# Load all the images which we will use in the game
# images for displaying score
game_images['scoreimages'] = (
pygame.image.load('images/0.png').convert_alpha(),
pygame.image.load('images/1.png').convert_alpha(),
pygame.image.load('images/2.png').convert_alpha(),
pygame.image.load('images/3.png').convert_alpha(),
pygame.image.load('images/4.png').convert_alpha(),
pygame.image.load('images/5.png').convert_alpha(),
pygame.image.load('images/6.png').convert_alpha(),
pygame.image.load('images/7.png').convert_alpha(),
pygame.image.load('images/8.png').convert_alpha(),
pygame.image.load('images/9.png').convert_alpha()
)
game_images['flappybird'] = pygame.image.load(
birdplayer_image).convert_alpha()
game_images['sea_level'] = pygame.image.load(
sealevel_image).convert_alpha()
game_images['background'] = pygame.image.load(
background_image).convert_alpha()
game_images['pipeimage'] = (pygame.transform.rotate(pygame.image.load(
pipeimage).convert_alpha(), 180), pygame.image.load(
pipeimage).convert_alpha())
print("WELCOME TO THE FLAPPY BIRD GAME")
print("Press space or enter to start the game")
# Here starts the main game
while True:
# sets the coordinates of flappy bird
horizontal = int(window_width/5)
vertical = int(
(window_height - game_images['flappybird'].get_height())/2)
ground = 0
while True:
for event in pygame.event.get():
# if user clicks on cross button, close the game
if event.type == QUIT or (event.type == KEYDOWN and \
event.key == K_ESCAPE):
pygame.quit()
sys.exit()
# If the user presses space or
# up key, start the game for them
elif event.type == KEYDOWN and (event.key == K_SPACE or\
event.key == K_UP):
flappygame()
# if user doesn't press anykey Nothing happen
else:
window.blit(game_images['background'], (0, 0))
window.blit(game_images['flappybird'],
(horizontal, vertical))
window.blit(game_images['sea_level'], (ground, elevation))
pygame.display.update()
framepersecond_clock.tick(framepersecond)