更新-我修改了代码以显示汽车面罩,结果发现面罩在错误的位置(左上角)并且没有移动...虽然仍然卡住了。

只是试图检测汽车是否偏离了轨道,到目前为止,我已经尝试实现遮罩碰撞检测,但是它似乎没有按预期工作。我试过从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.Sprites,并将它们放入子画面组,则可以使用pygame.sprite.spritecollidepygame.sprite.collide_mask作为碰撞检测的回调函数。

关于python - pygame背景蒙版碰撞不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53081079/

10-15 22:56