Hướng Dẫn Lập Trình Game Flappy Bird Với Python

Lập trình game Flappy Bird

Flappy Bird từng là tựa game được đông đảo người chơi ở Việt nam cũng như thế giới đón nhận trong năm 2013. Đây là dòng game phiêu lưu khá đơn giản và dễ tiếp cận. Tuy nhiên để đạt điểm cao thì không hề dễ dàng. Cũng chính vì tính lý thú của trò chơi này mà các bạn lập trình có thể sẽ rất tò mò làm sao để tạo ra nó trong tương lai. Hãy theo chúng tôi tìm hiểu cách lập trình game Flappy Bird với Python nhé.

Game Flappy Bird là gì?

Flappy Bird là một trò chơi trên nền tảng di động ra đời vào năm 2013. Người phát triển tựa game này là Nguyễn Hà Đông. Yêu cầu của tựa game này là người chơi điều khiển con chim di chuyển qua hết các ống mà không chạm vào chúng.

Khi chơi game, chúng ta chỉ việc chạm vào màn hình để làm con chim đập cánh cũng như bay lên. Trong trường hợp con chim chạm đất, hay các ống nào; game sẽ kết thúc. Lúc này điểm được tính khi con chim bay qua mỗi ống.

Ngay khi ra mắt game đã nhận đươc sự quan tâm của cộng đồng vì sự thích thú lẫn lối chơi đơn giản. Nhưng qua khoảng thời gian sau thì bị ít nhiều ảnh hưởng tiêu cực vì quá khó chơi và đồ họa không quá ấn tượng.

Tới tháng 2 năm 2014, Nguyễn Hà Đông đã gỡ bỏ game Flappy Bird ra khỏi cửa hàng ứng dụng. Mặc dù tựa game này không còn tồn tại nhưng nó đã mang lại cảm hứng thú vị cho nhiều thế hệ sau này.

Game Flappy Bird
Hình 1. Game Flappy Bird

Hướng dẫn lập trình game Flappy Bird với Python

Để làm game Flappy Bird trong Python, chúng ta cần sử dụng Pygame. Đây là một thư viện mã nguồn mở hỗ trợ làm game. Nói cách khác, nó giúp cho nhà phát triển game tạo ra trò chơi và những chương trình đa tiện ích với những chức năng chuyên biệt.

Để cho các bạn dễ hình dung về việc lập trình game Flappy Bird trong Python, chúng tôi xin trình bày các bước cơ bản để tạo ra trò chơi này.

Tạo dự án Python

Phần đầu tiên là tạo dự án Python trước. Hãy thực hiện những bước sau.

1. Tạo tên dự án: Việc đầu tiên bắt buộc phải làm là tạo một dự án và nhập tên dự án. Sau đó ấn nút “Create”.

2. Tạo file Python: Nhấp chuột phải vào tên dự án của bạn sau khi đã khởi tạo dự án ở bước 1. Sau đó, chọn “New” và tiếp đến chọn “Python file”.

3. Đặt tên cho file Python: Các bạn đặt tên cho chính file Python của mình và ấn chọn “Enter”.

Cách tạo game Flappy Bird thông qua thư viện Pygame

Sau khi tạo dự án Python của bạn xong, hãy chuyển qua các bước làm ra trò chơi Flappy Bird.

Sử dụng thư viện Pygame để làm game Flappy Bird
Hình 2. Sử dụng thư viện Pygame để làm game Flappy Bird

1. Cài đặt thư viện Pygame thông qua lệnh sau

pip install pygame

2. Hãy xây dựng kích thước của màn hình game thông qua hai thông số: chiều cao và chiều rộng. Tiếp đến, xác định những hình ảnh cần thiết để phục vụ game như đường ống, con chim, và hình nền.

# 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'

3. Khi đã hoàn thành việc khởi tạo những biến trong game và nhập thư viện thì chúng ta chuyển sang quá trình tạo Pygame. Nói cách khác, dùng pygame.init () để tạo chương trình kèm theo đặt chú thích cho cửa sổ.

Lúc này, pygame.time.Clock () có thể được dùng bổ sung cho vòng lặp chính của game nhằm thay đổi tốc độ của con chim. Cuối cùng, các bạn dùng pygame.image.load () để tải hình ảnh từ thư viện Pygame.

# 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")

4. Bắt đầu tạo vị trí của con chim và thực hiện vòng lặp cho game. Tới bước này, chúng ta cần tạo vị trí của chim cũng như mực nước biển kèm theo. Hãy nhớ đối chiếu cẩn thận mực nước biển so với mặt đất nhé. Sau đó, bổ sung điều kiện trong vòng lặp để xác định những yêu cầu từ game.

Bên cạnh đó, biến chiều dọc và ngang thường dùng để thiết lập vị trí của con chim. Một lưu ý nhỏ là chương trình phải chạy liên tục cho đến khi người dùng dừng hay thoát và có thể phải tạo vòng lặp While vô hạn.

Chú ý: Để thoát chương trình thì các bạn có thể dùng sys.exit ().

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)

5. Khởi tạo một hàm để thực thi việc hình thành đường ống mới với chiều cao ngẫu nhiên. Nói cách khác, chúng ta phải dùng phương thức getheight () để thiết lập chiều cao cho đường ống (chướng ngại vật).

Tiếp đến, hãy tạo một số bất kỳ chạy từ 0 đến số ngẫu nhiên (đảm bảo đường cao của ống sẽ tùy chỉnh được dựa trên chiều cao của cửa sổ trong game). Ngoài ra, khởi tạo một danh sách những từ điển bao gồm tọa độ của những đường ống ở phía trên hay dưới để trả giá trị về cho 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

6. Khởi tạo một hàm GameOver() thể hiện con chim đã va chạm trúng ống hoặc 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

7. Tiếp tục tạo hàm chính (Flappygame()). Lúc đầu, các bạn tạo những biến và hai đường ống thông qua hàm createPipe (). Hãy nhớ tạo ra hai danh sách trước tiên là những ống thấp. Sau này, cần nắm rõ vận tốc chú chim tối thiểu hay tối đa.

Không những vậy, cố gắng xử lý những sự kiện liên quan bằng việc dùng pygame.event.get (). Kiểm tra xem game đã kết thúc chưa nếu nó vượt qua thời gian thì hãy trả về hàm. Cuối cùng, cập nhật điểm số và hình ảnh game như hình nền, con chim và đường ống 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)

Sau đây là toàn bộ việc viết mã và triển khai dự án làm game Flappy Bird trong Python để các bạn tham khảo.

# 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)
Giao diện game Flappy Bird với Python
Hình 3. Giao diện game Flappy Bird với Python

Tổng kết

Trên đây là tất cả những thông tin quan trọng liên quan đến việc tiếp cận và lập trình game Flappy Bird với Python. Một lần nữa xin chân thành cám ơn quý đọc giả đã quan tâm theo dõi và hãy chia sẻ bài viết này đến những người khác để ủng hộ chúng tôi nhé.

 

5/5 - (2 bình chọn)

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *