Phát hiện va chạm trong PyGame

Category: Pygame

Điều kiện tiên quyết: Giới thiệu về pygame

Phát hiện va chạm  là một khái niệm rất thường gặp và được sử dụng trong hầu hết các trò chơi như trò chơi bóng bàn, trò chơi xâm lược không gian, v.v. Khái niệm đơn giản và dễ hiểu là khớp tọa độ của hai vật thể và đặt điều kiện để xảy ra va chạm.

Trong bài viết này, chúng ta sẽ phát hiện va chạm giữa hai vật thể, trong đó một vật thể sẽ di chuyển xuống dưới và vật thể còn lại sẽ được di chuyển sang trái và phải bằng cách điều khiển phím. Điều này tương tự như việc thoát khỏi khối hộp rơi trúng người chơi, và nếu khối hộp va chạm với người chơi, va chạm sẽ được phát hiện.

Chúng ta hãy xem cách triển khai từng phần:

Phần 1:

# nhập các thư viện cần thiết
import pygame
import random

# khởi tạo các đối tượng pygame
pygame.init()

# định nghĩa các màu
white = (255, 255, 255)
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
black = (0, 0, 0)

# thiết lập kích thước
width = 650
height = 700

# kích thước của một khối
pixel = 64

# thiết lập màn hình
screen = pygame.display.set_mode((width, height))

# thiết lập tiêu đề
pygame.display.set_caption("CORONA SCARPER")

# tải ảnh biểu tượng
gameIcon = pygame.image.load("rectangleBlock.png")

# đặt biểu tượng cho cửa sổ
pygame.display.set_icon(gameIcon)

# tải ảnh nền
backgroundImg = pygame.image.load("wallBackground.jpg")

Đây là đoạn mã đơn giản cơ bản để tạo màn hình cửa sổ và thiết lập chú thích, biểu tượng, cùng một số biến được định nghĩa sẵn mà không quá quan trọng để tìm hiểu sâu. Biến pixel là kích thước của hình ảnh khối, tức là 64 pixel.

 Phần 2:

# tải hình ảnh người chơi
playerImage = pygame.image.load("player.png")

# thiết lập vị trí ban đầu theo trục X
playerXPosition = (width/2) - (pixel/2)

# để người chơi cách đáy màn hình 20px
playerYPosition = height - pixel - 10     

# thiết lập thay đổi vị trí X ban đầu là 0
playerXPositionChange = 0

# định nghĩa hàm để hiển thị ảnh người chơi tại tọa độ cụ thể
def player(x, y):
  # vẽ ảnh lên đối tượng màn hình
  screen.blit(playerImage, (x, y))

# tải hình ảnh khối chữ nhật (block)
blockImage = pygame.image.load("rectangleBlock.png")

# thiết lập vị trí ngẫu nhiên theo trục X cho khối
blockXPosition = random.randint(0, (width - pixel))

# thiết lập vị trí ban đầu theo trục Y (trên màn hình)
blockYPosition = 0 - pixel

# thiết lập tốc độ di chuyển khối
blockXPositionChange = 0
blockYPositionChange = 2    

# định nghĩa hàm để hiển thị khối tại tọa độ cụ thể
def block(x, y):
  # vẽ ảnh khối lên đối tượng màn hình
  screen.blit(blockImage, (x, y))

Ở đây chúng tôi hiển thị người chơi và khối ở vị trí X và Y tương ứng. Vị trí X của khối là ngẫu nhiên trong mỗi vòng.

Lưu ý: Bất cứ nơi nào từ pixel được sử dụng, nó được dùng để trừ 64 pixel khỏi vị trí đã cho để hiển thị toàn bộ hình ảnh

Ví dụ: Khối được hiển thị ở vị trí chiều rộng, thì nó sẽ được vẽ bắt đầu từ điểm đó và do đó nó sẽ được hiển thị ra ngoài màn hình. Do đó, chúng ta đang trừ đi 64 pixel để xem hình ảnh đầy đủ.

Hiện nay,


 

Va chạm ngang

Đầu tiên, chúng ta kiểm tra xem khối có đi qua đường ngang của người chơi hay không. Chúng ta sẽ thiết lập phạm vi sao cho đường ngang đáy của khối trùng với đường ngang của người chơi. Trong hình trên, khối 2 và 3 có đường cơ sở nằm ngoài phạm vi đường bề mặt trên cùng và dưới cùng của người chơi P. Do đó, chúng không nằm trong phạm vi va chạm. Đường cơ sở của khối 1 nằm trong phạm vi đường trên cùng và dưới cùng của người chơi P. Do đó, chúng ta có thể thấy rõ khối có nằm trong phạm vi phạm vi dọc của người chơi hay không.


 

Va chạm theo chiều dọc

Ở đây, chúng ta kiểm tra phạm vi kích thước bề mặt bên trái và bên phải của người chơi với các khối bên trái và bên phải. Ở đây, khối 2 và 3 khi rơi xuống sẽ va chạm với người chơi, do đó phạm vi của khối 2 và 3 nằm giữa vị trí X và Y của người chơi. 

Do đó, khái niệm này được sử dụng để phát hiện va chạm.

 Phần 3:

# định nghĩa một hàm để
# phát hiện va chạm
def crash():
  # lấy một biến toàn cục
  global blockYPosition

  # kiểm tra điều kiện
  if playerYPosition < (blockYPosition + pixel):

      if ((playerXPosition > blockXPosition 
           and playerXPosition < (blockXPosition + pixel))
          or ((playerXPosition + pixel) > blockXPosition
           and (playerXPosition + pixel) < (blockXPosition + pixel))):

          blockYPosition = height + 1000

hàm va chạm xác định điều kiện va chạm.

Trong điều kiện IF đầu tiên , chúng ta kiểm tra va chạm theo chiều ngang. Ở đây, nếu vị trí Y của người chơi nhỏ hơn vị trí Y của khối, tức là khối di chuyển ra khỏi phạm vi ngang của người chơi, thì điều kiện tiếp theo cần kiểm tra là va chạm theo chiều ngang. Pixel được thêm vào blockYPosition vì vị trí Y của nó nằm ở trên cùng của khối và đáy hoặc đáy của khối là vị trí trên cùng của khối + kích thước pixel của khối (kích thước hình ảnh).

Điều kiện IF thứ hai kiểm tra va chạm theo chiều dọc. Nếu khối di chuyển từ phạm vi ngang thì chỉ kiểm tra va chạm theo chiều dọc, để va chạm của khối được phát hiện ở cả bốn cạnh. Bây giờ, nếu vị trí X của người chơi lớn hơn vị trí X của khối, tức là khối ở bên trái so với người chơi. Ở đây, nếu vị trí bắt đầu của khối nhỏ hơn vị trí bắt đầu của người chơi và vị trí kết thúc của khối (vị trí Y của khối + pixel) lớn hơn vị trí bắt đầu của người chơi, điều này có nghĩa là khối sẽ chồng lên vị trí bắt đầu của người chơi và do đó va chạm. Điều này được thể hiện trong hình ảnh va chạm theo chiều dọc ở trên của khối 2.

Tương tự, phạm vi thứ hai được đưa ra nếu vị trí bắt đầu của các khối nhỏ hơn vị trí kết thúc của người chơi và vị trí kết thúc của các khối lớn hơn vị trí kết thúc của người chơi. Điều này được hiển thị trong cùng hình ảnh cho khối 3.

Hình ảnh giải thích rõ ràng góc nhìn về vụ va chạm.

Do đó, nếu xảy ra va chạm, chúng ta sẽ di chuyển khối xuống dưới màn hình, tức là ở khoảng cách hơn 1000 để khối đó trở nên vô hình và khối mới sẽ không xuất hiện.

Phần 4:

running = True

while running:
  # hiển thị hình nền lên đối tượng màn hình
  screen.blit(backgroundImg, (0, 0))

  # lặp qua tất cả các sự kiện
  for event in pygame.event.get():
       
      # kiểm tra điều kiện thoát game
       if event.type == pygame.QUIT:
          # thoát khỏi trò chơi
          pygame.quit()

       # điều khiển di chuyển của người chơi bằng bàn phím
       if event.type == pygame.KEYDOWN:

          if event.key == pygame.K_RIGHT:
              playerXPositionChange = 3

          if event.key == pygame.K_LEFT:
              playerXPositionChange = -3

       if event.type == pygame.KEYUP:
           # khi nhả phím trái hoặc phải thì dừng di chuyển
           if event.key == pygame.K_RIGHT or pygame.K_LEFT:
               playerXPositionChange = 0

Đây là vòng lặp trò chơi trong đó chuyển động của người chơi được điều khiển và trò chơi bắt đầu. 

Phần 5:

# Giới hạn cho người chơi

# Nếu nó đi về phía bên phải,
# Hãy giữ nguyên ở phía bên phải và
# Không vượt quá
if playerXPosition >= (width - pixel):
  playerXPosition = (width - pixel) 
  
# nếu nó đi về phía bên trái,
# giữ nguyên phía bên trái và
# không vượt quá
if playerXPosition <= 0:
  playerXPosition = 0

Đây là ranh giới đối với người chơi để khi người chơi di chuyển đến vị trí cực bên phải hoặc cực bên trái trên màn hình, họ sẽ không di chuyển xa hơn và bị bật trở lại.

Phần 6:

# Nhiều khối di chuyển liên tiếp
# và điều kiện được sử dụng do chức năng kết thúc trò chơi
if (blockYPosition >= height - 0 and 
    blockYPosition <= (height + 200)):
  
  blockYPosition = 0 - pixel
  
  # gán ngẫu nhiên giá trị trong phạm vi
  blockXPosition = random.randint(0, (width - pixel))

Khi khối không va chạm rời khỏi người chơi, chúng ta cần cho người chơi quay lại từ phía trên. Do đó, chúng ta đặt điều kiện nếu vị trí Y của khối nằm dưới chiều cao màn hình và dưới chiều cao +200 (ví dụ trên 1000+, khối sẽ xuất hiện khi khối đã va chạm), thì di chuyển khối trở lại phía trên.

Phần 7:

# chuyển động của Người chơi
playerXPosition += playerXPositionChange

# chuyển động của Khối
blockYPosition += blockYPositionChange

# Gọi hàm player
player(playerXPosition, playerYPosition)

# khối Gọi hàm
block(blockXPosition, blockYPosition)

# gọi hàm sập
crash()

# màn hình cập nhật
pygame.display.update()

Cuối cùng, chuyển động của người chơi và khối được đưa ra và màn hình được làm mới

Đầu ra:

Published on Jul 28, 2025

Related Posts