简体   繁体   中英

Pygame: sprite collision has no output

I am making a game, where you can jump with sprite and obstacles are moving towards you. I made a sprite mask and tried to use sprite collision function but nothing happens: for checking if collision happens I made a simple print statement. I tried colliding player sprite with itself and collision it worked. So I'm puzziling around what is missing or wrong.

Background image
Player image
Obstacle image

import pygame, random

pygame.init()


W, H = 800,600
HW, HH = W/2,H/2
AREA = W * H

bg = pygame.image.load('Linn.png')
bg = pygame.transform.scale(bg, (800, 600))

DS = pygame.display.set_mode((W,H))
clock = pygame.time.Clock()



class Player(pygame.sprite.Sprite):
    def __init__(self, x, y, py, paat, veerg, rida):
        super(Player,self).__init__()
        '''Mangija huppamine'''
        self.x = x
        self.y = y

        self.jumping = False
        self.platform_y = py
        self.velocity_index = 0

        '''Sprite sheet'''
        self.paat = pygame.image.load('STlaev.png').convert_alpha() #pildi uleslaadimine
        self.paat = pygame.transform.scale(self.paat,(300,200)) #muutmaks pilti vaiksemaks
        self.rect = self.paat.get_rect()

        '''Sprite sheeti piltide jaotamine pikslite jargi'''
        self.veerg = veerg
        self.rida = rida
        self.kokku = veerg * rida

        W = self.veergL = self.rect.width/veerg
        H = self.weegK = self.rect.height/rida
        HW,HH = self.veergKeskel = (W/2,H/2)

        self.veerg = list([(index % veerg * W, int(index/veerg) * H,W,H )for index in range(self.kokku)])
        self.handle = list([ #pildi paigutamise voimalikud positsioonid
            (0, 0), (-HW, 0), (-W, 0),
            (0, -HH), (-HW, -HH), (-W, -HH),
            (0, -W), (-HW, -H), (-W, -H),])

        self.mask = pygame.mask.from_surface(self.paat)

    def do_jumpt(self):
        '''Huppamine: kiirus, korgus, platvorm'''
        global velocity
        if self.jumping:
            self.y += velocity[self.velocity_index]
            self.velocity_index += 1
            if self.velocity_index >= len(velocity) - 1:
                self.velocity_index = len(velocity) - 1
            if self.y > self.platform_y:
                self.y = self.platform_y
                self.jumping = False
                self.velocity_index = 0



    def draw(self, DS,veergindex,x,y,handle=0):
        DS.blit(self.paat,(self.x+self.handle[handle][0], self.y + self.handle[handle][1]),self.veerg[veergindex])


    def do(self):
        '''Funktsioonide kokkupanek'''
        self.do_jumpt()
        p.draw(DS,index%p.kokku,300,300,0)

    def update(self):
        self.rect.center = self.x, self.y

p = Player(310, 200, 200, 'STlaev.png', 4, 1) #Mangija algkordinaadid, huppe korgus, pilt, sprite valik
velocity = list([(i/ 2.0)-14 for i in range (0,50)])  #Huppe ulatus
index = 3

def keys(player):
    keys = pygame.key.get_pressed()
    if keys[pygame.K_SPACE] or keys[pygame.K_UP] and player.jumping == False:
         player.jumping = True




class Obsticles(pygame.sprite.Sprite):
    '''Game obsticles: **'''
    #img = pygame.image.load(os.path.join('images', 'box.png'))
    def __init__(self, x, y, width, height):
        super(Obsticles,self).__init__()

        self.img = pygame.image.load('box.png').convert_alpha()
        self.img = pygame.transform.scale(self.img, (64,64))
        self.rect = self.img.get_rect()

        self.x = x
        self.y = y
        self.width = width
        self.height = height

        self.mask = pygame.mask.from_surface(self.img)

    def draw(self, DS):
        '''Obsticle img blitting and hitbox'''
        DS.blit(self.img, (self.x, self.y))

    def update(self):
        self.rect.center = self.x, self.y

def redrawWindow():
    '''Obsticle loop'''
    for i in objects:
        i.draw(DS)


pygame.time.set_timer(pygame.USEREVENT+2, random.choice([3000,2000,1000,800]))
objects = []


'''Sprites'''
sprites = pygame.sprite.Group()

obsticles = Obsticles(832,300,64,64)
p = Player(310, 200, 200, 'STlaev.png', 4, 1)

all_sprites = pygame.sprite.Group(p,obsticles)
ob = pygame.sprite.Group(obsticles)

x=0
while True:

    '''Game loop'''
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()
        if event.type == pygame.USEREVENT+2:
            r = random.randrange(0,2)
            if r == 0:
                objects.append(Obsticles(832,300,64,64))


    '''Obsticle speed and deleting'''
    for i in objects:
        i.x -= 5 #the speed of the obsticle
        if i.x < -64: #deleting obsticle from the window
            objects.pop(objects.index(i))

    '''Background movement'''
    back_x = x % bg.get_rect().width
    DS.blit(bg, (back_x - bg.get_rect().width, 0))
    if back_x < W:
        DS.blit(bg, (back_x, 0))
    x -= 1

    '''Sprites'''
    all_sprites.update()

    collided = pygame.sprite.spritecollide(p,ob,True,pygame.sprite.collide_mask)
    for i in collided:
        print('Collision.')


    '''Funktsioonid'''
    keys(p)
    p.do()
    index+=1

    redrawWindow()

    pygame.display.update()
    clock.tick(60)

pygame.quit()
quit()

The problem is that you only append the obstacle sprites to the objects list, but not to the all_sprites and the ob group. The line all_sprites.update() calls the update methods of all contained sprites, and since your obstacles are not in this group, the rects won't be updated. You also have to add them to the ob group because it is used for the collision detection.

I suggest to remove the objects list and just add the obstacle sprites to the two groups.

class Obsticles(pygame.sprite.Sprite):

    def __init__(self, x, y):  # Removed width and height parameters.
        super(Obsticles, self).__init__()
        # Note that it would be more efficient to load the image
        # once in the global scope instead of loading it from the
        # hard disk again and again.
        # Also call the attribute `self.image`, then you can draw all
        # sprites by calling `all_sprites.draw(DS)` in the main loop.
        self.image = pygame.image.load('box.png').convert_alpha()
        self.image = pygame.transform.scale(self.image, (64, 64))
        self.rect = self.image.get_rect(center=(x, y))
        self.x = x
        self.y = y
        self.speed = -5
        self.mask = pygame.mask.from_surface(self.image)

    def draw(self, DS):
        '''Obsticle img blitting and hitbox'''
        DS.blit(self.img, (self.x, self.y))

    def update(self):
        self.x += self.speed  # Move the obstacle.
        # Update the rect because it's used to blit the 
        # sprite and for the collision detection.
        self.rect.center = self.x, self.y

        if self.x < -64:  # Delete the obstacle.
            # `kill()` removes this obstacle sprite from all sprite groups.
            self.kill()


def redrawWindow():
    """Draw the obstacles."""
    for i in ob:  # Uses the ob group now.
        i.draw(DS)


obsticles = Obsticles(832, 300)
# Use comprehensible variable names.
p = Player(310, 200, 200, 'STlaev.png', 4, 1)

all_sprites = pygame.sprite.Group(p, obsticles)
ob = pygame.sprite.Group(obsticles)

x = 0
done = False
while not done:
    # ---Handle the events.---
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
        elif event.type == pygame.USEREVENT+2:
            r = random.randrange(0, 2)
            if r == 0:
                obsticles = Obsticles(832, 300)
                # Add the obstacle to both groups.
                ob.add(obsticles)
                all_sprites.add(obsticles)

    keys(p)

    # ---Game logic.---
    all_sprites.update()

    collided = pygame.sprite.spritecollide(p, ob, True, pygame.sprite.collide_mask)
    for i in collided:
        print('Collision.')

    index += 1
    # Background movement.
    x -= 1
    back_x = x % bg.get_rect().width

    # ---Draw everything.---
    DS.blit(bg, (back_x - bg.get_rect().width, 0))
    if back_x < W:
        DS.blit(bg, (back_x, 0))

    p.do()
    redrawWindow()

    pygame.display.update()
    clock.tick(60)


pygame.quit()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM