检查子弹精灵撞击水泥块精灵的碰撞

Check collision of bullet sprite hitting cement block sprite

我想检查我的 sprite 子弹与我的水泥块 sprite 的碰撞。我不想让我的子弹穿过水泥块。我希望我的子弹在击中我的水泥块底部时停止,我还希望我的水泥块在 4 颗子弹命中后消失。

autopilot.py

import pygame
import debris
import car

pygame.init()

WIDTH = 1000
HEIGHT = 400

screen = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption("AutoPilot")
screen.fill((255,255,255))

#fps
FPS = 120
clock = pygame.time.Clock()

#background img
bg = pygame.image.load('background/street.png').convert_alpha()


#define variables


######################CAR/DEBRIS##########################

car = car.Car(1,5)
debris = debris.Debris(1,5)

##########################################################

#groups
car_group = pygame.sprite.Group()
car_group.add(car)

debris_group = pygame.sprite.Group()
debris_group.add(debris)

#game runs here
run = True
while run:

    #draw street
    screen.blit(bg,[0,0])

    #update groups
    car_group.update()
    #car_group.draw(screen)

    #draw debris
    debris.draw()

    #draw car
    car.draw()
    car.move()

    #update bullets
    car.bullet_update()
    car.collision()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

        #check if key is down
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                run = False
            if event.key == pygame.K_a:
                car.movingLeft = True
            if event.key == pygame.K_d:
                car.movingRight = True
            #shoot bullets
            if event.key == pygame.K_SPACE:
                car.shoot()

        #check if key is up
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_a:
                car.movingLeft = False
            if event.key == pygame.K_d:
                car.movingRight = False


    #update the display
    pygame.display.update()
    pygame.display.flip()
    clock.tick(FPS)


pygame.quit()

car.py

import pygame
from debris import Debris
from autopilot import debris_group
from autopilot import car_group

#screen height & width
WIDTH = 1000
HEIGHT = 400

screen = pygame.display.set_mode((WIDTH,HEIGHT))

#car class
class Car(pygame.sprite.Sprite):
    def __init__(self, scale, speed):
        pygame.sprite.Sprite.__init__(self)

        #load bullets
        self.vel = 5
        self.bullet_list = [] #holds bullet position
        self.bullet = pygame.image.load('car/bullet.png').convert_alpha()
        self.rect1 = self.bullet.get_rect()
        self.y = float(self.rect1.y)

        self.speed = speed
        #self.x = x
        #self.y = y
        self.moving = True
        self.frame = 0
        self.flip = False
        self.direction = 0

        #load car
        self.images = []
        img = pygame.image.load('car/car.png').convert_alpha()
        img = pygame.transform.scale(img, (int(img.get_width()) * scale, (int(img.get_height()) * scale)))
        self.images.append(img)
        self.image = self.images[0]
        self.rect = self.image.get_rect()
        self.update_time = pygame.time.get_ticks()
        self.movingLeft = False
        self.movingRight = False
        self.rect.x = 465
        self.rect.y = 325

    #draw car to screen
    def draw(self):
        for bullet_pos in self.bullet_list:
            screen.blit(self.bullet, bullet_pos)
        screen.blit(self.image, (self.rect.centerx, self.rect.centery))

    #move car
    def move(self):
        #reset the movement variables
        dx = 0
        dy = 0

        # moving variables
        if self.movingLeft and self.rect.x > 33:
            dx -= self.speed
            self.flip = True
            self.direction = -1
        if self.movingRight and self.rect.x < 900:
            dx += self.speed
            self.flip = False
            self.direction = 1

        #update rectangle position
        self.rect.x += dx
        self.rect.y += dy


    #shoot bullets
    def shoot(self):
        self.bullet_list.append([self.rect.centerx + 14.50,self.rect.centery])

    #update bullet travel
    def bullet_update(self):
        for bullet_pos in self.bullet_list[:]:
            bullet_pos[1] -= self.vel
            if bullet_pos[1] > 400: #400 value will change to checking if bullet collides with debris
                self.bullet_list.remove(bullet_pos)

    #check collision
    def collision():
        #start coding here

debris.py

import time
import pygame
import random

#screen height & width
WIDTH = 1000
HEIGHT = 400

screen = pygame.display.set_mode((WIDTH, HEIGHT))

#debris class
class Debris(pygame.sprite.Sprite):
    def __init__(self, scale, speed):
        pygame.sprite.Sprite.__init__(self)

        self.x = 400
        self.y = HEIGHT / 2 - 200
        self.speed = speed
        self.vy = 0
        self.on_ground = True
        self.move = True

        #load debris
        self.images = []
        img = pygame.image.load('debris/cement.png').convert_alpha()
        img = pygame.transform.scale(img, (int(img.get_width()) * scale, (int(img.get_height()) * scale)))
        self.images.append(img)
        self.image = self.images[0]
        self.rect = self.image.get_rect()

    #draw debris to screen
    def draw(self):
        screen.blit(self.image,(self.x,self.y))

pygame.sprite.Group.draw() 使用包含的 pygame.sprite.Spriteimagerect 属性绘制对象:

Draws the contained Sprites to the Surface argument. This uses the Sprite.image attribute for the source surface, and Sprite.rect. [...]

你必须在中绘制碎片而不是对象debris:

run = True
while run:
    # [...]

    # debris.draw() <--- DELETE
    debris_group.draw(screen)

    # [...]

Debris 添加健康属性:

class Debris(pygame.sprite.Sprite):
    def __init__(self, scale, speed):
        # [...]

        self.health = 4

我建议阅读 How do I detect collision in pygame?

使用 2 个嵌套循环和 pygame.Rect.colliderect to detect the collision between the objects. Remove the bullet and reduce health when a collision is detected. When health is 0, kill debris Sprite:

class Car(pygame.sprite.Sprite):
    # [...]

    def collision(self, debris_group):
        for debris in debris_group:
            for bullet_pos in self.bullet_list[:]:
                bullet_rect = self.bullet.get_rect(topleft = bullet_pos)
                if bullet_rect.colliderect(debris.rect):
                    self.bullet_list.remove(bullet_pos)
                    debris.health -= 1
                    if debris.health <= 0:
                        debris.kill()
run = True
while run:
    # [...]

    car.bullet_update()
    car.collision(debris_group)

    # [...]