两个精灵之间的碰撞 - Python 3.5.2

时间:2016-10-19 22:47:00

标签: python pygame collision-detection

我有一个不明飞行物和导弹的图像。我试图把它送到那里,如果导弹击中不明飞行物,它们都会爆炸并消失,然后片刻之后另一个不明飞行物会重生,但是碰撞代码不起作用。有人可以向我解释如何使代码工作吗?

pygame.display.init()
pygame.font.init()
screen = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
ufo = pygame.image.load("ufo.png")
rocket = pygame.image.load("rocket.png")
done = False
debug = False
fontObj = pygame.font.SysFont("Courier New", 20)

#Making my Empty Lists
missiles = [] #[x,y]
ufo_list = [] #[x,y,hspeed]
particle_list = []

#UFO Respawn Info
ufoRespawn = True
ufoHits = 0
ufoSpawnTimer = 0.0
ufoSpeed = 500.0

#MISSILE Info
launchX = 400
launchY = 550
missileSpeed = 100.0
missileDirection = 0

#creating the Starfield
myStars = []            # An (initially) empty list
for i in range(1000):
    x = random.randint(0, 800)
    y = random.randint(0, 600)
    newStar = [x, y]    # A 2-element list
    myStars.append(newStar)
starSpeed = 100.0       # Rate of star movement (px / s)
starDirection = 0       # 0 = not moving, -1 = left, +1 = right

#input
while not done: 
    event = pygame.event.poll()
    if event.type == pygame.QUIT:
        done = True

    keys = pygame.key.get_pressed()
    if keys[pygame.K_ESCAPE]:
        done = True

    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_d:
            debug = not debug


    dt = clock.tick() /1000.0

#the missile range (making it disappear after it hits the top)
    for missile in missiles:
        missile[1] -= missileSpeed * dt 
        if missile[1] < 0:    missiles.remove(missle)


#triangle following mouse position
    mx, my = pygame.mouse.get_pos()
    if mx > launchX:
        launchX += .3
    if mx < launchX:
        launchX -= .3


#bullets firing when pressing with mouse
    mbuttons = pygame.mouse.get_pressed()
    if mbuttons [0]:
        x = launchX
        y = launchY
        newMissiles = [x,y]
        missiles.append(newMissiles)

#Creating the UFOs
    ufoSpawnTimer -= dt
    if ufoSpawnTimer <= 0:
        if random.choice (("head", "tail")) == "head":
            x = 0
            hspeed = random.randint (10,50)
        else:
            x = 800
            hspeed = random.randint (-50, -10)
        y = random.randint (0,300)
        new_ufo = [x,y,hspeed]
        ufo_list.append(new_ufo)
        ufoSpawnTimer = 5.0


#Moving the Starfield
    for i in range(len(myStars)):
        myStars[i][0] += starSpeed * dt * starDirection
        if myStars[i][0] < 0:       myStars[i][0] = 800
        if myStars[i][0] > 800:     myStars[i][0] = 0   



    screen.fill ((0,0,0))
#drawing the triangle  a.k.a missle launcher :D
    pygame.draw.polygon(screen, (255,255,255), [[launchX, launchY], [launchX + 10, launchY + 10], \
                        [launchX - 10, launchY + 10]], 3)

    for missile in missiles:
        x = int(missile[0])
        y = int(missile[1])
        screen.blit(rocket, (x,y))


    #drawing the ufo
    for v in ufo_list:
        v[0] += v[2] * dt
        screen.blit(ufo,(v[0],v[1]))


    #Missle distance from UFO  - NEED HELP ON THIS PORTION
    #Hit Detection
    missileDist = ((x - v[0]) ** 2 + (y - v[1]) ** 2) ** 0.5
    if **????** :
        ufoRespawn = True
        ufoHits += 10

    #drawing th starfield
    for star in myStars:
        x = int(star[0])
        y = int(star[1])
        pygame.draw.circle(screen, (255,255,255), (x,y), 2)



    pygame.display.flip()
pygame.font.quit()
pygame.display.quit()

1 个答案:

答案 0 :(得分:2)

有很多不同的方法来检测碰撞,可能值得查看可以这样做的库,但到目前为止最简单的方法是使用pygame.sprite.spritecollide()

但在我展示如何使用该函数之前,您需要知道pygame.sprite.Group()是什么以及精灵类是什么。

基本上,pygame.sprite.Group()是一种跟踪和保持多个精灵的方法。在你的情况下,似乎为你的导弹制造导弹组将是最好的选择。

所以我会创建一个小组来装载你的导弹: missiles_group = pygame.sprite.Group()。您可以通过说missiles_group.add(<sprite instance name>)

向群组中添加导弹

至于精灵班,请看我给出的一个问题的答案。简而言之,Sprite类是一种创建精灵的模块化方法。精灵类不仅仅使用普通图像,而是拥有精灵的必要方法和属性。我将在下面的示例中使用精灵类,因此如果需要更多细节,请阅读我上面链接的答案。

有了这一点,并且没有太多细节,这里是你如何填写上述函数的每个函数参数。

  • sprite:这是将针对一组精灵进行测试的精灵
  • group:这是用于使用精灵进行测试的组。
  • dokill:这是一个布尔值。如果设置为true,则每次sprite参数与group参数中的某些内容发生冲突时,将删除group参数中的对象。如果dokill参数设置为false,则反之亦然。 这是函数所采用的另一个参数,但是对于你想要做的事情,它是不需要的。

结合以上信息,这是一个例子。该示例创建一个sprite和一个sprite列表。每次精灵与组中的精灵碰撞时,HIT都会打印到屏幕上:

import pygame #import the pygame module into the namespace <module>

WIDTH = 640 # define a constant width for our window
HEIGHT = 480 # define a constant height for our window

#create a pygame window, and
#initialize it with our WIDTH and HEIGHT constants
display = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock() # create a game clock

class Sprite(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((20, 20))
        self.image.fill((255, 0, 0))
        self.rect = self.image.get_rect()
        self.rect.x = WIDTH / 2
        self.rect.y = HEIGHT / 2
        self.vx = 0
        self.vy = 0

    def update(self):
        self.vx = 0
        self.vy = 0
        key = pygame.key.get_pressed()
        if key[pygame.K_LEFT]:
            self.vx = -1
        elif key[pygame.K_RIGHT]:
            self.vx = 1
        if key[pygame.K_UP]:
            self.vy = -1
        elif key[pygame.K_DOWN]:
            self.vy = 1
        self.rect.x += self.vx
        self.rect.y += self.vy

# cretae a player sprite
player = Sprite()

# create a group to hold all of our sprites
sprites = pygame.sprite.Group()

# create a group to hold sprites we want to
# test collions against. These sprites will
# still be added to the sprites list
# but we need a seperate group to test for
# collisions against
collision_sprites = pygame.sprite.Group()

# add a sprite to out collison sprite group
# We also add the sprite to our sprites group
# that holds all sprites
tmp = Sprite()
tmp.update = lambda: None
sprites.add(tmp)
collision_sprites.add(tmp)

# add a player sprites to the player group
player.rect.x = 10
sprites.add(player)


running = True # our variable for controlling our game loop
while running:
    for e in pygame.event.get(): # iterate ofver all the events pygame is tracking
        clock.tick(60) # make our clock keep pour game at 60 FPS
        if e.type == pygame.QUIT: # is the user trying to close the window?
            running = False # if so break the loop
            pygame.quit() # quit the pygame module
            quit() # quit is for IDLE friendliness

    sprites.update()

    # here is where we test for collision
    if pygame.sprite.spritecollide(player, collision_sprites, False):
        print("HIT!")

    display.fill((180, 180, 180)) # fill the pygame screen with white
    sprites.draw(display)
    pygame.display.flip() # update the screen

我的例子,如果相当大,所以请花时间仔细检查。我尽力添加尽可能多的好评。祝你好运!