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.
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.
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)
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é.