2016-10-19 2 views
0

У меня есть изображение ufo и ракеты. Я пытаюсь доставить его туда, где, если ракета попадет в ufo, они оба взорвутся и исчезнут, а затем через несколько мгновений снова появится другое уфо, но код столкновения не работает. может кто-нибудь объяснить мне, как заставить код работать?Столкновение между двумя спрайтами - Python 3.5.2

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() 

ответ

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, и объект из параметра группы будет удален. И наоборот, если для аргумента dokill установлено значение false. Это еще один параметр, который выполняет функция, но для того, что вы пытаетесь сделать, он не нужен.

Включая приведенную выше информацию, приведен пример. В примере создается спрайт и список спрайтов. Каждый раз, когда спрайт сталкивается с спрайтов из группы, 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 

Мой пример, если достаточно большой, так что не торопитесь и пройти через нее осторожно. Я попытался добавить столько хороших комментариев, сколько мог. Удачи!

+1

@Allison, если вы не хотите использовать [Sprites] (http://www.pygame.org/docs/ref/sprite.html), но затем используйте как минимум [pygame.Rect()] (http: //www.pygame.org/docs/ref/rect.html) и 'pygame.Rect.colliderect()' – furas

+1

@furas Да, я думаю, он мог. Но поскольку он уже загружал изображения, я подумал, что он может использовать Sprites. –

+0

да, рано или поздно OP придется изучать спрайты - так что ваш пример OP может начать его сейчас. – furas

Смежные вопросы