Phát triển game với Pygame - Part 1: Map

Tiếp tục bài viết về lập trình game với python mà cụ thể ở đây là pygame, ta sẽ bắt tay vào phát triển game Mario. Để bắt đầu, ta sẽ tạo map cho game.

Để tạo map cho một game platform, có rất nhiều phương pháp nhưng phương pháp được dùng chủ yếu hiện nay là sử dụng TMX (tilemap XML). Để tạo được tile map thì đầu tiên ta cần có tileset, nói đơn giản thì tileset là những viên gạch đủ các loại, đủ các kích cỡ (thường là kích cỡ giống nhau) và dùng các viên gạch là và chương trình Tiled (http://www.mapeditor.org/), ta có thể xây dựng được 1 map dựa trên các tile đó. Với game Mario, chúng tôi sử dụng tileset được tạo bởi black squirrel như hình dưới đây:

Sau khi download Tiled về, ta sẽ tạo một map mới: map1.tmx với chiều rộng là 43 tile, chiều cao là 40 tile. Sau đó, ta import file tileset ở trên vào (New Tileset), chọn kích thước cho mỗi tile (20px x 14px)và margin tương ứng (0px). Sau khi đã load xong. Ta có thể bắt đầu tạo map bằng cách đặt từng tile lên trên map.

Với một Map, ta có thể chia thành nhiều layer khác nhau.

  • Background Layer: các lớp cảnh vật đằng sau như bầu trời, cây cỏ phía xa, dòng sông, ...
  • Midground Layer: các lớp cảnh vật ở giữa, cùng độ sâu với các sprite của game
  • Foreground Layer: các lớp cảnh vật đăng trước như các ống nước Ta sắp xếp các layer theo thứ tự z-order tăng dần như minh họa dưới đây:

map_layers.png

Ta tạo một map như sau:

all_map.png

Bạn có thể checkout file map.tmx từ repo https://github.com/vigov5/mario_game/ để tham khảo thêm.

Để load map vào trong pygame, ta sẽ sử dụng thư viện TMX Library được viết bởi Richard Jones. Bạn có thể lấy source-code mới nhất từ link sau: https://bitbucket.org/r1chardj0n3s/pygame-tutorial/src/a383dd24790d/tmx.py Ta chỉnh sửa lại code của chương trình Hello world lần trước để load map.

import pygame
import tmx
import sys

if not pygame.font: print 'Warning, fonts disabled'
if not pygame.mixer: print 'Warning, sound disabled'

pygame.init()
size = width, height = 640, 480
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()

tilemap = tmx.load("map.tmx", screen.get_size())

while True:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit(0)

    screen.fill((95, 183, 229)) # sky color
    if pygame.font:
        font = pygame.font.Font(None, 36)
        text = font.render("Hello World !", 1, (255, 0, 0))
        textpos = text.get_rect(centerx=width/2)
        screen.blit(text, textpos)

    tilemap.set_focus(0, 480)
    tilemap.draw(screen)

    pygame.display.flip()

Với thư viện TMX, việc load map vào game chỉ đơn giản dùng một dòng code: tilemap = tmx.load("map.tmx", screen.get_size()) Sau khi load xong thì biến tilemap đã chứa toàn bộ thông tin của map.tmx gồm kích thước, các tile, vị trí các tile trên map, các properties tùy biến của map. Việc vẽ map lên màn hình cũng rất đơn giản. Ta chỉ cần tilemap.draw(screen) việc vẽ các tile ở đúng các vị trí sẽ do tmx lib đảm nhận.

Tuy nhiên, trước khi vẽ map lên trên màn hình, ta cần set forcus cho map bằng lệnh tilemap.set_focus(0, 480), tham số truyền vào chính là tọa độ trên màn hình,, như ở trên là góc dưới bên trái của màn hình. Ta có thể hình dung là cửa sổ game là 1 cửa sổ có kích thước 640 x 480 và ta đang nhìn qua cửa sổ đó lên toàn bộ tilemap (do đó với tilemap có kích thước lớn hơn 640 x 480, ta sẽ chỉ nhìn thấy một phần nhỏ của map). Việc set_focus sẽ giúp cho thư viện tmx biết ta đang muốn nhìn vào điểm nào trên map để tmx lib sẽ chỉnh lại vị trí tương ứng. Với việc thay đổi tọa độ của tham số truyền vào (ví dụ: trở thành tọa độ của Mario) sẽ tạo cảm giác như lia camera chạy theo nhân vật, tức là nhân vật sẽ luôn ở trung tâm của map còn map thì di chuyển về sau khi nhân vật tiến lên phía trước.

Và đây là kết quả:

render_map.png

Phần tiếp theo: Phát triển game với Pygame - Part 2: Sprite