首页 > 解决方案 > 多个精灵碰撞检测

问题描述

好的,所以我一直在试图弄清楚如何设置它并且无法使其正常工作。如果您熟悉它,我正在尝试获得类似于游戏Frogger中移动日志的功能。到目前为止,我只对一个碰撞检测起作用pygame.sprite.Group()

import pygame
import os
import random

os.environ['SDL_VIDEO_CENTERED'] = '1'

WIDTH = 480
HEIGHT = 720
FPS = 60

# Moving Object spacing setup first row 
INSTANCE_COUNT = 0
BOX_WIDTH = 30
SPACING = 120

# object speed
pos_objspeed = 1
neg_objspeed = -1

BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)

pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()

class Player(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((30, 30))
        self.image.fill(GREEN)
        self.rect = self.image.get_rect()
        self.rect.centerx = WIDTH / 2
        self.rect.bottom = HEIGHT - 96
        self.speedx = 0
        self.speedy = 0

class MovingObj_Test(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((90, 30))
        self.image.fill(RED)
        self.rect = self.image.get_rect()
        self.rect.x = (INSTANCE_COUNT * (SPACING+ BOX_WIDTH))
        #self.rect.x = random.randrange(WIDTH)
        self.rect.bottom = 384
        self.speedx = pos_objspeed

    def update(self):
        self.rect.x += self.speedx
        if self.rect.x >= 480:
            self.rect.x = -30
            self.rect.bottom = 384
            self.speedx = pos_objspeed        

class MovingObj_TestTwo(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((90, 30))
        self.image.fill(RED)
        self.rect = self.image.get_rect()
        self.rect.x = (INSTANCE_COUNT * (SPACING+ BOX_WIDTH))
        #self.rect.x = random.randrange(WIDTH)
        self.rect.bottom = 336
        self.speedx = neg_objspeed

    def update(self):
        self.rect.x += self.speedx
        if self.rect.x >= 480:
            self.rect.x = -30
            self.rect.bottom = 336
            self.speedx = neg_objspeed

all_sprites = pygame.sprite.Group()
movingobj_l = pygame.sprite.Group()
movingobj_r = pygame.sprite.Group()

for i in range (3):
    INSTANCE_COUNT = i + 1
    obj1 = MovingObj_Test()
    all_sprites.add(obj1)
    movingobj_l.add(obj1)

for i in range (3):
    INSTANCE_COUNT = i + 1
    obj2 = MovingObj_TestTwo()
    all_sprites.add(obj2)
    movingobj_r.add(obj2)

player = Player()
all_sprites.add(player)

running = True
onLogLeft = False
onLogRight = False
groundSpd = 48
while running:

    clock.tick(FPS)

    hitsleft = pygame.sprite.spritecollide(player, movingobj_l, False, pygame.sprite.collide_rect)
    for hit in hitsleft:
        player.speedx = pos_objspeed
        player.speedy = 0
        onLogLeft = True
    if len(hitsleft) == 0:
        onLogLeft = False
        player.speedx = 0
        player.speedy = 0
    hitsright = pygame.sprite.spritecollide(player, movingobj_r, False, pygame.sprite.collide_rect)
    for hit in hitsright:
        player.speedx = neg_objspeed
        player.speedy = 0
        onLogRight = True
    if len(hitsright) == 0:
        onLogRight = False
        player.speedx = 0
        player.speedy = 0


    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                player.speedx = -groundSpd
            if event.key == pygame.K_RIGHT:
                player.speedx = groundSpd
            if event.key == pygame.K_UP:
                player.speedy = -groundSpd
            if event.key == pygame.K_DOWN:
                player.speedy = groundSpd

        if event.type == pygame.KEYUP and onLogLeft == False and onLogRight == False:
            if event.key == pygame.K_LEFT:
                player.speedx = 0
            if event.key == pygame.K_RIGHT:
                player.speedx = 0
            if event.key == pygame.K_UP:
                player.speedy = 0
            if event.key == pygame.K_DOWN:
                player.speedy = 0

    if onLogLeft == False and onLogRight == False and player.rect.bottom <= 384:
        running = False

    player.rect.x += player.speedx
    player.rect.y += player.speedy

    if event.type == pygame.QUIT:
        running = False



    #player.rect.x += player.speedx
    #player.rect.y += player.speedy

    all_sprites.update()
    screen.fill(BLACK)
    all_sprites.draw(screen)
    pygame.display.flip()



pygame.quit()
quit()

好的,所以在我的代码中

hitsright = pygame.sprite.spritecollide(player, movingobj_r, False, pygame.sprite.collide_rect)

检查碰撞并更新玩家的速度,但我期望它

hitsleft = pygame.sprite.spritecollide(player, movingobj_l, False, pygame.sprite.collide_rect)

没有做同样的事情。

如果有人有任何想法,我很困惑为什么会这样。另外,我该如何修复它以使其对两者都有效?

标签: pythonpython-3.xpygame

解决方案


left 和 right 的代码表现不同,因为如果hitsleft检测到碰撞,player.speedx则设置为:

for hit in hitsleft:
   player.speedx = pos_objspeed

但是,如果与hitsleft那里发生冲突,则不会与之发生冲突hitsrightplayer.speedx立即重置:

if len(hitsright) == 0:
   onLogRight = False
   player.speedx = 0

您必须player.speedx根据两个条件进行设置(例如在if- elif-else语句中):

while running:
    # [...]

    hitsleft = pygame.sprite.spritecollide(player, movingobj_l, False, pygame.sprite.collide_rect)
    onLogLeft = any(hitsleft)

    hitsright = pygame.sprite.spritecollide(player, movingobj_r, False, pygame.sprite.collide_rect)
    onLogRight = any(hitsright)

    player.speedy = 0
    if onLogLeft:
        player.speedx = pos_objspeed
    elif onLogRight:
        player.speedx = neg_objspeed
    else:
        player.speedx = 0

推荐阅读