Ở phần trước ta đã biết cách thay đổi sprite của Mario thông qua các trạng thái.
def handle[self, event]:
self.my_mario.handle[event]
pass
8 is the vertical status. đang nhảy [ def handle[self, event]:
self.my_mario.handle[event]
pass
9] và theo chiều ngang def handle[self, event]:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
if self.v_state == "resting":
self.jump[]
elif event.key == pygame.K_RIGHT:
self.move_right[]
elif event.key == pygame.K_LEFT:
self.move_left[]
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or \
event.key == pygame.K_LEFT:
self.vx = 0
self.h_state = "standing"
0. đang đứng yên [ def handle[self, event]:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
if self.v_state == "resting":
self.jump[]
elif event.key == pygame.K_RIGHT:
self.move_right[]
elif event.key == pygame.K_LEFT:
self.move_left[]
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or \
event.key == pygame.K_LEFT:
self.vx = 0
self.h_state = "standing"
1] hay đang chạy [ def handle[self, event]:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
if self.v_state == "resting":
self.jump[]
elif event.key == pygame.K_RIGHT:
self.move_right[]
elif event.key == pygame.K_LEFT:
self.move_left[]
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or \
event.key == pygame.K_LEFT:
self.vx = 0
self.h_state = "standing"
2] cùng với đó là các trạng thái đang quay mặt về phía nào [_______23]. left or must. Tuy nhiên, ta không thể tương tác với Mario. Ta sẽ thực hiện công việc tương tác này thông qua các phím di chuyển. up [nhảy lên], left [di chuyển sang trái], must [di chuyển sang phải] Kèm theo là quay mặt nếu cần thiếtĐể xử lý các sự kiện phím ấn mà người dùng nhập vào, ta định nghĩa thêm hàm xử lý trong lớp Mario để xử lý các sự kiện. Như ở bài trước, tại hàm
def handle[self, event]:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
if self.v_state == "resting":
self.jump[]
elif event.key == pygame.K_RIGHT:
self.move_right[]
elif event.key == pygame.K_LEFT:
self.move_left[]
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or \
event.key == pygame.K_LEFT:
self.vx = 0
self.h_state = "standing"
4, vòng lặp chính của trò chơi, sau mỗi lần đánh dấu đồng hồ ta lấy ra các sự kiện diễn ra trong trò chơi và đưa ra từng đối tượng trong trò chơi để xử lý một cách phù hợp def run[self]:
# main game loop
while True:
# hold frame rate at 60 fps
dt = self.clock.tick[60]
self.time_step += 1
# enumerate event
for event in pygame.event.get[]:
if event.type == pygame.QUIT:
sys.exit[0]
# sprite handle event
self.handle[event]
self.update[dt / 1000.]
# re-draw screen
self.draw[self.screen]
Tại hàm
def handle[self, event]:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
if self.v_state == "resting":
self.jump[]
elif event.key == pygame.K_RIGHT:
self.move_right[]
elif event.key == pygame.K_LEFT:
self.move_left[]
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or \
event.key == pygame.K_LEFT:
self.vx = 0
self.h_state = "standing"
5 của vòng lặp của trò chơi, ta tiến hành gọi hàm def handle[self, event]:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
if self.v_state == "resting":
self.jump[]
elif event.key == pygame.K_RIGHT:
self.move_right[]
elif event.key == pygame.K_LEFT:
self.move_left[]
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or \
event.key == pygame.K_LEFT:
self.vx = 0
self.h_state = "standing"
5 của mario để xử lý def handle[self, event]:
self.my_mario.handle[event]
pass
Trong phần này, chúng ta sẽ tiến hành triển khai hàm xử lý cho Mario
def handle[self, event]:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
if self.v_state == "resting":
self.jump[]
elif event.key == pygame.K_RIGHT:
self.move_right[]
elif event.key == pygame.K_LEFT:
self.move_left[]
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or \
event.key == pygame.K_LEFT:
self.vx = 0
self.h_state = "standing"
Như trong phần mã ở phía trên, tham số truyền vào là biến
def handle[self, event]:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
if self.v_state == "resting":
self.jump[]
elif event.key == pygame.K_RIGHT:
self.move_right[]
elif event.key == pygame.K_LEFT:
self.move_left[]
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or \
event.key == pygame.K_LEFT:
self.vx = 0
self.h_state = "standing"
7, từ biến này ta có thể kiểm tra xem sự kiện đó được nhấn 1 phím xuống hay không [ def handle[self, event]:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
if self.v_state == "resting":
self.jump[]
elif event.key == pygame.K_RIGHT:
self.move_right[]
elif event.key == pygame.K_LEFT:
self.move_left[]
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or \
event.key == pygame.K_LEFT:
self.vx = 0
self.h_state = "standing"
8], tại đây ta sẽ thực hiện các hành động. if nhấn phím sang phải sẽ thực hiện hành động chuyển sang phải. Dưới đây là chi tiết của hàn def handle[self, event]:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
if self.v_state == "resting":
self.jump[]
elif event.key == pygame.K_RIGHT:
self.move_right[]
elif event.key == pygame.K_LEFT:
self.move_left[]
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or \
event.key == pygame.K_LEFT:
self.vx = 0
self.h_state = "standing"
9. Đối với hàm def handle[self, event]:
self.my_mario.handle[event]
pass
50, chúng ta làm hoàn toàn tương tự. Hàm def handle[self, event]:
self.my_mario.handle[event]
pass
51 chúng ta sẽ nói kỹ hơn khi thực hiện cuộc phỏng vấn nghiêm túc def handle[self, event]:
self.my_mario.handle[event]
pass
5Đó là logic khi chúng ta nhấn một phím xuống. Việc cần làm tiếp theo đó là xử lý khi ta giải phóng phím ra, lúc này ta sẽ cập nhật lại các trạng thái của Mario về trạng thái đứng yên như ở đoạn mã phía trên
Lệnh di chuyển sang bên phải, đơn giản là thiết lập vận tốc theo chiều x, thay đổi các trạng thái tương ứng với hướng di chuyển. sau khi thực hiện các bước này, chạy thử ta thấy mario đã di chuyển theo đúng các hướng bên trái mà ta chỉ định
Mô phỏng lực lượngChúng ta cũng xem qua một chút logic về phần chuyển động của Mario. Thứ luôn kéo chúng ta về với mặt đất, khiến ta không thể bay lượn như chim mà chính là lực lượng quan trọng. Hãy mô phỏng lượng lớn trong trò chơi như sau. Đầu tiên là định nghĩa một số tham số
def handle[self, event]:
self.my_mario.handle[event]
pass
8 def handle[self, event]:
self.my_mario.handle[event]
pass
9Ở đây ta cần có chút kiến thức về vật lý. Giả lập quan trọng như sau
- cứ mỗi bước trò chơi ta tính toán lại vận tốc của Mario, cộng thêm vào vận tốc theo chiều y một lượng là GRAVITY
- Mức độ mà các vật thể di chuyển được thực hiện sau mỗi bước trò chơi sẽ chính là vận tốc của vật chất theo các chiều x, y
- Tính toán lại các vận tốc tối đa để tránh việc nhân vật của họ rơi quá nhanh
Khi đó công việc thực hiện nhảy lên chỉ đơn giản là di chuyển với vận tốc âm thanh theo phương y
def handle[self, event]:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
if self.v_state == "resting":
self.jump[]
elif event.key == pygame.K_RIGHT:
self.move_right[]
elif event.key == pygame.K_LEFT:
self.move_left[]
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or \
event.key == pygame.K_LEFT:
self.vx = 0
self.h_state = "standing"
0Ta init position of Mario as after at hàm
def handle[self, event]:
self.my_mario.handle[event]
pass
52 của main def handle[self, event]:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
if self.v_state == "resting":
self.jump[]
elif event.key == pygame.K_RIGHT:
self.move_right[]
elif event.key == pygame.K_LEFT:
self.move_left[]
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or \
event.key == pygame.K_LEFT:
self.vx = 0
self.h_state = "standing"
2Như vậy các vật thể sẽ ngày càng chuyển xuống bên dưới và ngày càng nhanh hơn theo đúng mô phỏng trọng lực
Để có thể thực hiện phần va chạm với platformer ta cần chỉnh sửa lại Map trong Tiled một chút. Như nó đã được sơ lược thông qua trong bài đầu tiên của sê-ri. Map được chia thành các lớp layer background, midground layer, foreground layer, các layer này sẽ là phần hiển thị. Nhưng phần sẽ tương tác với các đối tượng của trò chơi sẽ là lớp kích hoạt, phần này chứa các đối tượng nhưng lại không hiển thị, làm cho ta có cảm giác là các đối tượng đang tương tác với lớp gạch
Trong lớp kích hoạt của tệp bản đồ, ta bổ sung các đối tượng hình chữ nhật với các thuộc tính như sau
Ta set value for properties is "tlbr" có nghĩa là chặn theo tất cả các hướng trên [t] trái [l] dưới [b] phải [r] cho
def handle[self, event]:
self.my_mario.handle[event]
pass
53. Và tương tự cho các đối tượng def handle[self, event]:
self.my_mario.handle[event]
pass
54 được sử dụng để ngăn người chơi rời khỏi màn hình. Tất cả các đối tượng này đều nằm trong lớp kích hoạt của bản đồTiếp theo đó ta cần phải xử lý va chạm giữa người chơi với các đối tượng thuộc loại
def handle[self, event]:
self.my_mario.handle[event]
pass
55 này. Khi đó toàn bộ mã của hàm def handle[self, event]:
self.my_mario.handle[event]
pass
56 sẽ như sau def handle[self, event]:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
if self.v_state == "resting":
self.jump[]
elif event.key == pygame.K_RIGHT:
self.move_right[]
elif event.key == pygame.K_LEFT:
self.move_left[]
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or \
event.key == pygame.K_LEFT:
self.vx = 0
self.h_state = "standing"
7- Đầu tiên ta tính toán vị trí của Mario theo tác động của trọng lực
- Tiếp đến là tính toán va chạm với
55. Nguyên lý rất đơn giản. lấy ra cácdef handle[self, event]: self.my_mario.handle[event] pass
55, kiểm tra xem phần bao bên ngoài của chúng có giao tiếp với phần bao bên ngoài của Mario hay không. Nếu có giao nhau ta sẽ thiết lập lại bao ngoài mới [def handle[self, event]: self.my_mario.handle[event] pass
59] cho Mario để chúng ta không còn giao nhau nữadef handle[self, event]: self.my_mario.handle[event] pass
Hình demo khi hiển thị lớp
def handle[self, event]:
self.my_mario.handle[event]
pass
80and when does not display the
def handle[self, event]:
self.my_mario.handle[event]
pass
80 layerVì vậy ta đã có một nhân vật Mario có thể di chuyển trên một địa hình cơ bản rồi. Phần tiếp theo sẽ là cách sử dụng bản đồ nâng cao tương tự với Tiled