pygame - 纠正碰撞检测问题
pygame - rects collision detection issue
我正在学习 pygame,但我在检测矩形碰撞方面遇到了问题。我现在正在使用 colliderect() 函数,但它仅在矩形重叠时才有效,问题是“如何检测边缘碰撞?”。欢迎对整体发表一般性评论。首先 post 顺便说一句。
这是我的代码:
import pygame
#####SETTINGS#####
HEIGHT = 1080
WIDTH = 1920
BLOCK_SIZE = 60
##################
class Level():
def __init__(self, file):
self.file = file
self.blocks = []
self.map = self.load_from_file()
def load_from_file(self):
map = []
file = open(self.file + '.txt', 'r')
data = file.read()
file.close()
data = data.split('\n')
for x in data:
map.append(list(x))
return map
def render(self, screen):
self.blocks = []
y = 0
for row in self.map:
x = 0
for block in row:
if block != '0':
self.blocks.append(pygame.Rect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))
if block == '1':
pygame.draw.rect(screen, (56,24,0), (x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))
elif block == '2':
pygame.draw.rect(screen, (18,115,81), (x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))
x += 1
y += 1
class Player():
def __init__(self, x, y, color):
self.x = x
self.y = y
self.color = color
self.rect = pygame.Rect(x, y, BLOCK_SIZE, BLOCK_SIZE)
self.go_left = False
self.go_right = False
self.go_up = False
self.go_down = False
self.collisions = {'left' : False, 'right' : False, 'top' : False, 'bottom' : False}
def move(self):
self.collisions = test_collisions(self.rect, level.blocks)
if self.go_left and not self.collisions['left']:
self.x -= 10
self.go_left = False
if self.go_right and not self.collisions['right']:
self.x += 10
self.go_right = False
if self.go_up and not self.collisions['top']:
self.y -= 10
self.go_up = False
if self.go_down and not self.collisions['bottom']:
self.y += 10
self.go_down = False
self.rect = pygame.Rect(self.x, self.y, BLOCK_SIZE, BLOCK_SIZE)
def render(self, screen):
pygame.draw.rect(screen, self.color, self.rect)
def render(screen, player, level):
screen.fill((49, 113, 181))
level.render(screen)
player.render(screen)
pygame.display.update()
def handle_events(player):
for event in pygame.event.get():
if event.type == pygame.QUIT or event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
run = False
pygame.quit()
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
player.go_left = True
if keys[pygame.K_d]:
player.go_right = True
if keys[pygame.K_w]:
player.go_up = True
if keys[pygame.K_s]:
player.go_down = True
def test_collisions(object, rects):
collisions = {'left' : False, 'right' : False, 'top' : False, 'bottom' : False}
for rect in rects:
if object.colliderect(rect):
if object.x <= rect.x:
collisions['right'] = True
if object.x >= rect.x:
collisions['left'] = True
if object.y >= rect.y:
collisions['top'] = True
if object.y <= rect.y:
collisions['bottom'] = True
return(collisions)
def main_loop():
clock = pygame.time.Clock()
while run:
clock.tick(60)
handle_events(player)
player.move()
render(screen, player, level)
if __name__ == "__main__":
run = True
screen = pygame.display.set_mode((WIDTH, HEIGHT))
level = Level('assets/level_one')
player = Player(0,0,(255,255,0))
main_loop()
这里是level_one.txt文件内容:
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000002222222222200000
00000000000000000000000000000000
00000000000000000000000000000000
00022222222200000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
22222222222222222222222222222222
11111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
您可以 enlarge the rectangles for the collision detection with [
pygame.Rect.inflate`](builtins.TypeError: argument 1 must be pygame.Surface, not function)。例如:
if object.colliderect(rect.inflate(1, 1)):
# [...]
我正在学习 pygame,但我在检测矩形碰撞方面遇到了问题。我现在正在使用 colliderect() 函数,但它仅在矩形重叠时才有效,问题是“如何检测边缘碰撞?”。欢迎对整体发表一般性评论。首先 post 顺便说一句。
这是我的代码:
import pygame
#####SETTINGS#####
HEIGHT = 1080
WIDTH = 1920
BLOCK_SIZE = 60
##################
class Level():
def __init__(self, file):
self.file = file
self.blocks = []
self.map = self.load_from_file()
def load_from_file(self):
map = []
file = open(self.file + '.txt', 'r')
data = file.read()
file.close()
data = data.split('\n')
for x in data:
map.append(list(x))
return map
def render(self, screen):
self.blocks = []
y = 0
for row in self.map:
x = 0
for block in row:
if block != '0':
self.blocks.append(pygame.Rect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))
if block == '1':
pygame.draw.rect(screen, (56,24,0), (x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))
elif block == '2':
pygame.draw.rect(screen, (18,115,81), (x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))
x += 1
y += 1
class Player():
def __init__(self, x, y, color):
self.x = x
self.y = y
self.color = color
self.rect = pygame.Rect(x, y, BLOCK_SIZE, BLOCK_SIZE)
self.go_left = False
self.go_right = False
self.go_up = False
self.go_down = False
self.collisions = {'left' : False, 'right' : False, 'top' : False, 'bottom' : False}
def move(self):
self.collisions = test_collisions(self.rect, level.blocks)
if self.go_left and not self.collisions['left']:
self.x -= 10
self.go_left = False
if self.go_right and not self.collisions['right']:
self.x += 10
self.go_right = False
if self.go_up and not self.collisions['top']:
self.y -= 10
self.go_up = False
if self.go_down and not self.collisions['bottom']:
self.y += 10
self.go_down = False
self.rect = pygame.Rect(self.x, self.y, BLOCK_SIZE, BLOCK_SIZE)
def render(self, screen):
pygame.draw.rect(screen, self.color, self.rect)
def render(screen, player, level):
screen.fill((49, 113, 181))
level.render(screen)
player.render(screen)
pygame.display.update()
def handle_events(player):
for event in pygame.event.get():
if event.type == pygame.QUIT or event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
run = False
pygame.quit()
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
player.go_left = True
if keys[pygame.K_d]:
player.go_right = True
if keys[pygame.K_w]:
player.go_up = True
if keys[pygame.K_s]:
player.go_down = True
def test_collisions(object, rects):
collisions = {'left' : False, 'right' : False, 'top' : False, 'bottom' : False}
for rect in rects:
if object.colliderect(rect):
if object.x <= rect.x:
collisions['right'] = True
if object.x >= rect.x:
collisions['left'] = True
if object.y >= rect.y:
collisions['top'] = True
if object.y <= rect.y:
collisions['bottom'] = True
return(collisions)
def main_loop():
clock = pygame.time.Clock()
while run:
clock.tick(60)
handle_events(player)
player.move()
render(screen, player, level)
if __name__ == "__main__":
run = True
screen = pygame.display.set_mode((WIDTH, HEIGHT))
level = Level('assets/level_one')
player = Player(0,0,(255,255,0))
main_loop()
这里是level_one.txt文件内容:
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000002222222222200000
00000000000000000000000000000000
00000000000000000000000000000000
00022222222200000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
22222222222222222222222222222222
11111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
您可以 enlarge the rectangles for the collision detection with [
pygame.Rect.inflate`](builtins.TypeError: argument 1 must be pygame.Surface, not function)。例如:
if object.colliderect(rect.inflate(1, 1)):
# [...]