更新-我修改了代码以显示汽车面罩,结果发现面罩在错误的位置(左上角)并且没有移动...虽然仍然卡住了。
只是试图检测汽车是否偏离了轨道,到目前为止,我已经尝试实现遮罩碰撞检测,但是它似乎没有按预期工作。我试过从https://github.com/illume/pixel_perfect_collision/blob/master/balloon.py复制方法,但是即使这样也不起作用。
这是简化的代码(下面是完整代码):
#make masks
car_mask = pygame.mask.from_surface(car_image, 50)
back_mask = pygame.mask.from_surface(background_image, 50)
#make background rect
back_rect = background_image.get_rect()
#-=-=-=--==-=#
##MAIN LOGIC##
#-=-=-=-=-=-=#
#Get the car rect
rotated = pygame.transform.rotate(car_image, car.angle)
car_rect = rotated.get_rect()
#Calculate offset
offset_x = car_rect[0] - back_rect[0]
offset_y = car_rect[1] - back_rect[1]
#Check for overlap
overlap = back_mask.overlap(car_mask, (offset_x, offset_y))
#Draw everything
self.screen.fill((255, 255, 255))
self.screen.blit(background_image, (0,0))
self.screen.blit(rotated, car.position * 32 - (car_rect.width / 2, car_rect.height / 2))
#Confirm overlap
if overlap:
print("collision")
这是完整的代码:
import os
import pygame
from math import tan, radians, degrees, copysign
from pygame.math import Vector2
class Car:
def __init__(self, x, y, angle=0.0):
#initialize
self.position = Vector2(x, y)
self.velocity = Vector2(0.0, 0.0)
self.angle = angle
self.acceleration = 0.0
self.steering = 0.0
def update(self, dt):
#update car variables
self.velocity = Vector2(self.acceleration, 0)
angular_velocity = self.steering * dt * self.velocity.x
self.position += self.velocity.rotate(-self.angle) * dt
self.angle += degrees(angular_velocity) * dt
class Game:
def __init__(self):
#initialize
pygame.init()
pygame.display.set_caption("Car tutorial")
self.screen = pygame.display.set_mode((1280, 720))
self.clock = pygame.time.Clock()
self.ticks = 60
self.exit = False
def run(self):
#get images
current_dir = os.path.dirname(os.path.abspath(__file__))
image_path = os.path.join(current_dir, "car.png")
car_image = pygame.image.load(image_path).convert_alpha()
image_path2 = os.path.join(current_dir, "racetrackv1.png")
background_image = pygame.image.load(image_path2).convert_alpha()
#make car
car = Car(17, 5)
#make masks
car_mask = pygame.mask.from_surface(car_image, 50)
back_mask = pygame.mask.from_surface(background_image, 50)
#make background rect
back_rect = background_image.get_rect()
while not self.exit:
dt = self.clock.get_time() / 1000
#Check for exit
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.exit = True
#Get user input
pressed = pygame.key.get_pressed()
#Acceleration logic
if pressed[pygame.K_UP]:
car.acceleration += 1 * dt
elif pressed[pygame.K_DOWN]:
car.acceleration -= 1 * dt
else:
car.acceleration *= 0.99
#Steering logic
if pressed[pygame.K_RIGHT]:
car.steering -= 30 * dt
elif pressed[pygame.K_LEFT]:
car.steering += 30 * dt
else:
car.steering = 0
#Update the car
car.update(dt)
#Get the car rect
rotated = pygame.transform.rotate(car_image, car.angle)
car_rect = rotated.get_rect()
#Calculate offset
offset_x = car_rect[0] - back_rect[0]
offset_y = car_rect[1] - back_rect[1]
#Check for overlap
overlap = back_mask.overlap(car_mask, (offset_x, offset_y))
#Draw everything
self.screen.fill((255, 255, 255))
self.screen.blit(background_image, (0,0))
self.screen.blit(rotated, car.position * 32 - (car_rect.width / 2, car_rect.height / 2))
#Confirm overlap
if overlap:
print("collision")
pygame.display.flip()
self.clock.tick(self.ticks)
pygame.quit()
if __name__ == '__main__':
game = Game()
game.run()
最佳答案
您永远不会移动car_rect
,因此它始终保持在默认位置(0,0),并且由于它用于计算蒙版的偏移,因此碰撞检测将无法进行。每次汽车行驶时,都必须更新其位置。我对您的代码进行了一些重新排列,并将汽车的rect,遮罩和图像放入它们所属的Car
类中。
import os
import pygame
from math import tan, radians, degrees, copysign
from pygame.math import Vector2
class Car:
def __init__(self, x, y, car_image, angle=0.0):
#initialize
self.orig_image = car_image
self.image = car_image
self.rect = self.image.get_rect(center=(x, y))
self.position = Vector2(x, y)
self.velocity = Vector2(0.0, 0.0)
self.angle = angle
self.acceleration = 0.0
self.steering = 0.0
self.mask = pygame.mask.from_surface(self.image, 50)
def update(self, dt):
#update car variables
self.velocity = Vector2(self.acceleration, 0)
angular_velocity = self.steering * dt * self.velocity.x
self.position += self.velocity.rotate(-self.angle) * dt
self.rect.center = self.position # Update the rect each frame.
self.angle += degrees(angular_velocity) * dt
# Rotate the orig image, rect and mask.
self.image = pygame.transform.rotate(self.orig_image, self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
self.mask = pygame.mask.from_surface(self.image, 50)
class Game:
def __init__(self):
#initialize
pygame.init()
pygame.display.set_caption("Car tutorial")
self.screen = pygame.display.set_mode((1280, 720))
self.clock = pygame.time.Clock()
self.ticks = 60
self.exit = False
def run(self):
#get images
current_dir = os.path.dirname(os.path.abspath(__file__))
image_path = os.path.join(current_dir, "car.png")
car_image = pygame.image.load(image_path).convert_alpha()
image_path2 = os.path.join(current_dir, "racetrackv1.png")
background_image = pygame.image.load(image_path2).convert_alpha()
#make car
car = Car(17, 5, car_image) # Pass the image.
#make masks
back_mask = pygame.mask.from_surface(background_image, 50)
#make background rect
back_rect = background_image.get_rect()
while not self.exit:
dt = self.clock.get_time() / 1000
#Check for exit
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.exit = True
#Get user input
pressed = pygame.key.get_pressed()
#Acceleration logic
if pressed[pygame.K_UP]:
car.acceleration += 100 * dt
print(car.acceleration)
elif pressed[pygame.K_DOWN]:
car.acceleration -= 1 * dt
else:
car.acceleration *= 0.99
#Steering logic
if pressed[pygame.K_RIGHT]:
car.steering -= 30 * dt
elif pressed[pygame.K_LEFT]:
car.steering += 30 * dt
else:
car.steering = 0
#Update the car
car.update(dt)
#Calculate offset
offset_x = car.rect[0] - back_rect[0]
offset_y = car.rect[1] - back_rect[1]
#Check for overlap
overlap = back_mask.overlap(car.mask, (offset_x, offset_y))
#Draw everything
self.screen.fill((255, 255, 255))
self.screen.blit(background_image, (0,0))
# The old blit position makes no sense to me.
# self.screen.blit(rotated, car.position * 32 - (car_rect.width / 2, car_rect.height / 2))
# Just blit the car image at the car rect (top left) coords now.
self.screen.blit(car.image, car.rect)
# Make the mask visible to debug it.
for point in car.mask.outline(8):
pygame.draw.rect(self.screen, (255, 0, 0), (point+Vector2(car.rect.topleft), (2, 2)))
#Confirm overlap
if overlap:
print("collision", car.position)
pygame.display.flip()
self.clock.tick(self.ticks)
pygame.quit()
if __name__ == '__main__':
game = Game()
game.run()
另外,如果将汽车和背景设置为
pygame.sprite.Sprite
s,并将它们放入子画面组,则可以使用pygame.sprite.spritecollide
和pygame.sprite.collide_mask
作为碰撞检测的回调函数。关于python - pygame背景蒙版碰撞不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53081079/