📜  PyGame 中的碰撞检测

📅  最后修改于: 2022-05-13 01:54:48.178000             🧑  作者: Mango

PyGame 中的碰撞检测

先决条件: pygame简介

碰撞检测是一个非常常见的概念,几乎在乒乓球游戏、太空入侵者等游戏中都有使用。简单直接的概念是匹配两个对象的坐标并为发生碰撞设置条件。

在本文中,我们将检测两个对象之间的碰撞,其中一个对象将向下方向移动,而另一个对象将通过按键控制左右移动。这与从落在玩家身上的方块逃跑是一样的,如果方块与玩家发生碰撞,则检测到碰撞。

让我们看看部分明智的实现:

第1部分:

Python3
# import required libraries
import pygame
import random
 
# initialize pygame objects
pygame.init()
 
# define the colours
white = (255, 255, 255)
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
black = (0, 0, 0)
 
# set the Dimensions
width = 650
height = 700
 
# size of a block
pixel = 64
 
# set Screen
screen = pygame.display.set_mode((width,
                                  height))
 
# set caption
pygame.display.set_caption("CORONA SCARPER")
 
# load the image
gameIcon = pygame.image.load("rectangleBlock.png")
 
# set icon
pygame.display.set_icon(gameIcon)
 
# load the image
backgroundImg = pygame.image.load("wallBackground.jpg")


Python3
# load the image
playerImage = pygame.image.load("player.png")
 
# set the position
playerXPosition = (width/2) - (pixel/2)
 
# So that the player will be
# at height of 20 above the base
playerYPosition = height - pixel - 10    
 
# set initially 0
playerXPositionChange = 0
 
# define a function for setting
# the image at particular
# coordinates
def player(x, y):
  # paste image on screen object
  screen.blit(playerImage, (x, y))
 
# load the image
blockImage = pygame.image.load("rectangleBlock.png")
 
# set the random position
blockXPosition = random.randint(0,
                                (width - pixel))
 
blockYPosition = 0 - pixel
 
# set the speed of
# the block
blockXPositionChange = 0
blockYPositionChange = 2   
 
# define a function for setting
# the image at particular
# coordinates
def block(x, y):
  # paste image on screen object
  screen.blit(blockImage,
              (x, y))


Python3
# define a function for
# collision detection
def crash():
  # take a global variable
  global blockYPosition
 
  # check conditions
  if playerYPosition < (blockYPosition + pixel):
 
      if ((playerXPosition > blockXPosition
           and playerXPosition < (blockXPosition + pixel))
          or ((playerXPosition + pixel) > blockXPosition
           and (playerXPosition + pixel) < (blockXPosition + pixel))):
 
          blockYPosition = height + 1000


Python3
running = True
 
while running:
  # set the image on screen object
  screen.blit(backgroundImg, (0, 0))
 
  # loop through all events
  for event in pygame.event.get():
        
      # check the quit condition
       if event.type == pygame.QUIT:
          # quit the game
          pygame.quit()
 
       # movement key control of player
       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:
 
           if event.key == pygame.K_RIGHT or pygame.K_LEFT:
 
               playerXPositionChange = 0


Python3
# Boundaries to the Player
 
# if it comes at right end,
# stay at right end and
# does not exceed
if playerXPosition >= (width - pixel):
  playerXPosition = (width - pixel)
   
# if it comes at left end,
# stay at left end and
# does not exceed
if playerXPosition <= 0:
  playerXPosition = 0


Python3
# Multiple Blocks Movement after each other
# and condition used because of game over function
if (blockYPosition >= height - 0 and
    blockYPosition <= (height + 200)):
   
  blockYPosition = 0 - pixel
   
  # randomly assign value in range
  blockXPosition = random.randint(0, (width - pixel))


Python3
# movement of Player
playerXPosition += playerXPositionChange
 
# movement of Block
blockYPosition += blockYPositionChange
 
# player Function Call
player(playerXPosition, playerYPosition)
 
# block Function Call
block(blockXPosition, blockYPosition)
 
# crash function call
crash()
 
# update screen
pygame.display.update()



这是创建窗口屏幕和设置标题、图标和一些预定义变量的基本简单代码,这些变量并不那么重要,无法深入了解。像素变量是块图像的大小,即 64 像素。

2 部分:

Python3

# load the image
playerImage = pygame.image.load("player.png")
 
# set the position
playerXPosition = (width/2) - (pixel/2)
 
# So that the player will be
# at height of 20 above the base
playerYPosition = height - pixel - 10    
 
# set initially 0
playerXPositionChange = 0
 
# define a function for setting
# the image at particular
# coordinates
def player(x, y):
  # paste image on screen object
  screen.blit(playerImage, (x, y))
 
# load the image
blockImage = pygame.image.load("rectangleBlock.png")
 
# set the random position
blockXPosition = random.randint(0,
                                (width - pixel))
 
blockYPosition = 0 - pixel
 
# set the speed of
# the block
blockXPositionChange = 0
blockYPositionChange = 2   
 
# define a function for setting
# the image at particular
# coordinates
def block(x, y):
  # paste image on screen object
  screen.blit(blockImage,
              (x, y))


在这里,我们在各自的 X 和 Y 位置显示玩家和方块。方块的 X 位置在每一轮中是随机的。

注意:无论在哪里使用像素字,它都用于从给定位置减去 64 个像素,以便显示完整的图像

例如:如果显示的块在宽度位置,那么它将从该点开始绘制,因此它将显示在屏幕之外。因此,我们减去 64 个像素以完整查看图像

现在,

水平碰撞

首先,我们检查方块是否穿过玩家的水平线。我们将设置范围以使块的基本水平线与玩家的水平线相匹配。在上图中,区块 2 和 3 的基线超出了玩家 P 的顶面线和底面线的范围。因此,它们不在碰撞范围内。块 1 的基线在玩家 P 的顶部和底部的范围内。因此,我们进一步看到该块是否在玩家的垂直范围内。

垂直碰撞

在这里,我们用块的左右表面检查玩家左右侧面尺寸的范围。这里,方块2和3在下降时会碰撞玩家,因此2和3方块的范围在玩家的X位置和玩家的Y位置之间。

因此,这个概念用于检测碰撞。

 3 部分:

Python3

# define a function for
# collision detection
def crash():
  # take a global variable
  global blockYPosition
 
  # check conditions
  if playerYPosition < (blockYPosition + pixel):
 
      if ((playerXPosition > blockXPosition
           and playerXPosition < (blockXPosition + pixel))
          or ((playerXPosition + pixel) > blockXPosition
           and (playerXPosition + pixel) < (blockXPosition + pixel))):
 
          blockYPosition = height + 1000

crash函数定义了碰撞条件。

在第一个IF条件下,我们检查水平碰撞。这里,如果玩家的Y位置小于方块的Y位置,即方块离开玩家的水平范围,那么接下来要检查的条件是水平的。像素被添加到 blockYPosition 因为它的 Y 位置在块的顶部,而块的底部或底部是块的顶部位置 + 其像素大小(图像大小)。

第二个IF条件检查垂直碰撞。如果方块从水平范围通过,则只检查垂直范围,以便在其所有四个侧面检测到方块的碰撞。现在,如果玩家的 X 位置大于方块的 X 位置,即方块在玩家的左边。这里,如果方块的起始位置小于玩家起始位置,并且方块的结束位置(方块Y位置+像素)大于玩家起始位置,这意味着方块将与玩家起始位置重叠并因此发生碰撞。这显示在上面块 2 的垂直碰撞图像中。

类似地,给出第二个范围,如果块的开始位置小于玩家的结束位置并且块的结束位置大于玩家的结束位置。这显示在块 3 的同一图像中。

该图像清楚地解释了碰撞的视图。

因此,如果发生碰撞,我们会将块移动到屏幕下方,即在下方 1000+ 距离处,这样它就会不可见并且不会出现新块。

4 部分:

Python3

running = True
 
while running:
  # set the image on screen object
  screen.blit(backgroundImg, (0, 0))
 
  # loop through all events
  for event in pygame.event.get():
        
      # check the quit condition
       if event.type == pygame.QUIT:
          # quit the game
          pygame.quit()
 
       # movement key control of player
       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:
 
           if event.key == pygame.K_RIGHT or pygame.K_LEFT:
 
               playerXPositionChange = 0


这是控制玩家移动的游戏循环。游戏开始了。

5 部分:

Python3

# Boundaries to the Player
 
# if it comes at right end,
# stay at right end and
# does not exceed
if playerXPosition >= (width - pixel):
  playerXPosition = (width - pixel)
   
# if it comes at left end,
# stay at left end and
# does not exceed
if playerXPosition <= 0:
  playerXPosition = 0

这些是玩家的边界,因此当玩家移动到屏幕上最右边或最左边的位置时,它不应该走得更远并反弹回来。

6 部分:

Python3

# Multiple Blocks Movement after each other
# and condition used because of game over function
if (blockYPosition >= height - 0 and
    blockYPosition <= (height + 200)):
   
  blockYPosition = 0 - pixel
   
  # randomly assign value in range
  blockXPosition = random.randint(0, (width - pixel))


当没有碰撞的方块远离玩家时,我们需要让他从顶部再次出现。因此我们提供了一个条件,如果块的 Y 位置低于屏幕高度且低于 height+200(如高于 1000+,则在块碰撞时出现块),然后将其再次移动到顶部。

7 部分:

Python3

# movement of Player
playerXPosition += playerXPositionChange
 
# movement of Block
blockYPosition += blockYPositionChange
 
# player Function Call
player(playerXPosition, playerYPosition)
 
# block Function Call
block(blockXPosition, blockYPosition)
 
# crash function call
crash()
 
# update screen
pygame.display.update()


最后给出玩家和方块的移动并刷新屏幕

输出: