PyGame 中的 Sprite 碰撞测试(尝试过:矩形和组)

问题描述 投票:0回答:1

我知道有近 5 或 6 个与我正在提出的问题类似的问题,但没有一个答案对我有帮助(如果我不是一个十足的菜鸟,他们可能会帮助我),所以我将尝试展示我的具体案例.

我正在尝试在 PyGame (Python lib)中进行精灵碰撞测试,但我无法让它工作,碰撞时我得到的只是“False”,它根本不起作用,我无法弄清楚为什么啊,连续找了两天了。

在我的游戏中,我有对象 Player(我称之为“花花公子”)和对象 Enemy(我称之为……“敌人”)。两者的

__init__
非常相似,并且都生成了矩形。

这是玩家的

__init__

class dude(pygame.sprite.Sprite):
def __init__(self):
    pygame.sprite.Sprite.__init__(self)
    self.image = self.load_image(SPRITE_PLAYER)
    self.X = randint(34,ALTURA-10)
    self.Y = randint(34,LARGURA-10)
    self.rect = pygame.Rect(self.X,self.Y,25,25) #currently testing this
    #self.rect = self.image.get_rect()           already tried this
    self.speed = SPEED_PLAYER
    self.clock = pygame.time.Clock()

对于敌人,我有这个:

class enemy(pygame.sprite.Sprite):
def __init__(self):
    pygame.sprite.Sprite.__init__(self)
    self.image = self.load_image(SPRITE_ENEMY)
    self.X = randint(34,ALTURA-10)
    self.Y = randint(34,LARGURA-10)
    self.rect = pygame.Rect(self.X,self.Y,25,25)
    self.speed = SPEED_ENEMY
    self.clock = pygame.time.Clock()
    self.xis=1
    self.yps=1

在测试碰撞时,这两个方法会返回一些东西(这对我来说已经很棒了,因为还有其他尝试只返回错误),但即使我在游戏中碰撞它们,它们也总是返回 0。 当玩家(由按键输入控制)触摸敌人精灵您的图像(在舞台上随机移动)时,应该发生碰撞。

这些是我有的测试方法:

print pygame.sprite.collide_rect(player, enemy),pygame.sprite.collide_rect(player, enemy2)
print pygame.sprite.collide_rect(player, enemy),player.rect.colliderect(enemy2)
print player.rect.colliderect(enemy),player.rect.colliderect(enemy2)

(编辑) 我一直致力于显示更多代码,以便可以找到问题,所以就这样了 (我还将全局加载精灵,将它们作为参数传递给对象,尖端的坦克)。

玩家对象:

# -*- coding: cp1252 -*-
import pygame, os
from pygame.locals import *
from Configs import *
from random import randint

class dude(pygame.sprite.Sprite):
def __init__(self):
    pygame.sprite.Sprite.__init__(self)
    self.image = self.load_image(SPRITE_PLAYER)
    self.X = randint(34,ALTURA-10)
    self.Y = randint(34,LARGURA-10)
    self.rectBox()
    self.speed = SPEED_PLAYER
    self.clock = pygame.time.Clock()

def load_image(self,image_loaded):
    try:
        image = pygame.image.load(image_loaded)
    except pygame.error, message:
        print "Impossivel carregar imagem: " + image_loaded
        raise SystemExit, message
    return image.convert_alpha()

def rectBox(self):
    self.rect = self.image.get_rect()
    self.image_w, self.image_h  = self.image.get_size()
    self.rect.move(self.X, self.Y)          
    self.rect.topleft = (self.X, self.Y)
    self.rect.bottomright = (self.X + self.image_w, self.Y + self.image_h)

def update(self,xis,yps,screen):
    time_passed = self.clock.tick()
    time_passed_seconds = time_passed/1000.0
    distance_moved = time_passed_seconds * (self.speed +100) #Distancia = tempo * velocidade
    
    self.X +=xis*distance_moved
    self.Y +=yps*distance_moved

    screen.blit(self.image, (self.X,self.Y))
    
    if self.X>ALTURA-52:
        self.X-=2

    elif self.X<30:
        self.X+=2

    if self.Y>LARGURA-52:
        self.Y-=2

    elif self.Y<30:
        self.Y+=2

敌方物体:

# -*- coding: cp1252 -*-
import pygame, os
from pygame.locals import *
from Configs import *
from random import randint

class enemy(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = self.load_image(SPRITE_ENEMY)
        self.X = randint(34,ALTURA-10)
        self.Y = randint(34,LARGURA-10)
        self.rectBox()
        self.speed = SPEED_ENEMY
        self.clock = pygame.time.Clock()
        self.xis=1
        self.yps=1

    def load_image(self,image_loaded):
        try:
            image = pygame.image.load(image_loaded)
        except pygame.error, message:
            print "Impossivel carregar imagem: " + image_loaded
            raise SystemExit, message
        return image.convert_alpha()

    def rectBox(self):
        self.rect = self.image.get_rect()
        self.image_w, self.image_h  = self.image.get_size()
        self.rect.move(self.X, self.Y)          
        self.rect.topleft = (self.X, self.Y)
        self.rect.bottomright = (self.X + self.image_w, self.Y + self.image_h)
    
    def update(self,screen):
        time_passed = self.clock.tick()
        time_passed_seconds = time_passed/1000.0
        distance_moved = time_passed_seconds * (self.speed +100)
        
        self.X +=self.xis*distance_moved
        self.Y -=self.yps*distance_moved

        screen.blit(self.image, (self.X,self.Y))

        #Maquina de estados finitos para inteligência da movimentação
        if self.X>ALTURA-50:
            self.X-=2
            self.xis=-1
        elif self.X<30:
            self.X+=2
            self.xis=1
        
        if self.Y>LARGURA-50:
            self.Y-=2
            self.yps=1
        elif self.Y<30:
            self.Y+=2
            self.yps=-1
    

主要脚本:

# -*- coding: cp1252 -*-
import pygame, os
from pygame.locals import *
from Configs import *
from Enemy import enemy as e
from Player import dude
from sys import exit

pygame.init()

#Função para carregar imagens
def load_image(image_loaded):
        try:
            image = pygame.image.load(image_loaded)
        except pygame.error, message:
            print "Impossivel carregar imagem: " + image_loaded
            raise SystemExit, message
        return image.convert()

#Funções do Pause
def pause():
    drawpause()
    while 1:
        p = pygame.event.wait()
        if p.type in (pygame.QUIT, pygame.KEYDOWN):
            return
  
def drawpause():
    font = pygame.font.Font(None, 48)
    text1 = font.render("PAUSE", 1, (10, 10, 10))
    text1pos = text1.get_rect()
    text1pos.centerx = screen.get_rect().centerx
    text1pos.centery = screen.get_rect().centery
    screen.blit(text1, text1pos)
    font = pygame.font.Font(None, 36)
    text2 = font.render("Pressione qualquer tecla para continuar", 1, (10, 10, 10))
    text2pos = text2.get_rect()
    text2pos.centerx = screen.get_rect().centerx
    text2pos.centery = screen.get_rect().centery + 50
    screen.blit(text2, text2pos)
    pygame.display.flip()

#Inicializa tela principal    
os.environ["SDL_VIDEO_CENTERED"] = "1"
screen = pygame.display.set_mode((ALTURA, LARGURA),0,32)
bg = load_image(BACKGROUND)
pygame.display.set_caption("Jogo teste para TCC - Top-Down")

#Inicialização do personagem
move_x, move_y = 0, 0
player = dude()

#Inicialização dos inimigos
enemy = e()
enemy2 = e()

#Atribuição de grupos de entidades
inimigos = pygame.sprite.Group()
inimigos.add(enemy)
inimigos.add(enemy2)

personagem = pygame.sprite.Group()
personagem.add(player)

#Objeto clock
clock = pygame.time.Clock()

#Loop principal sprite.get_height() sprite.get_width()
while True:

    #Eventos do jogo
    for event in pygame.event.get():
        #SAIR DO JOGO
        if event.type == QUIT:
            pygame.quit()
            exit()
        if event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                pygame.quit()
                exit()
            elif event.key == K_p:
                pause()
                
        #TECLAS DE MOVIMENTAÇÃO PERSONAGEM
        if event.type == KEYDOWN:
            if event.key == K_LEFT:
                move_x = -1
            elif event.key == K_RIGHT:
                move_x = +1
            elif event.key == K_UP:
                move_y = -1
            elif event.key == K_DOWN:
                move_y = +1
        elif event.type == KEYUP:
            if event.key == K_LEFT:
                move_x = 0
            elif event.key == K_RIGHT:
                move_x = 0
            elif event.key == K_UP:
                move_y = 0
            elif event.key == K_DOWN:
                move_y = 0

    #Posicionamento do background
    screen.blit(bg, (0,0))

    #Movimentação do personagem
    player.update(move_x,move_y,screen)

    #Movimentação inimigos
    enemy.update(screen)
    enemy2.update(screen)

    #Teste colisão
    #print pygame.sprite.collide_rect(player, enemy),pygame.sprite.collide_rect(player, enemy2)
    #print pygame.sprite.collide_rect(player, enemy),player.rect.colliderect(enemy2)
    #print player.rect.colliderect(enemy),player.rect.colliderect(enemy2)

    #Refresh (por FPS)
    pygame.display.update()

就是这样,感谢您对我的帖子的反馈!

python pygame collision
1个回答
0
投票

如果您遇到碰撞检测问题,打印精灵的

rect
通常会有所帮助,例如
print(player.rect)
。它会告诉你,矩形永远不会更新,它们保持在相同的位置,并且因为它们用于碰撞检测,所以你的精灵不会发生碰撞。

要解决您的问题,您必须在

self.rect.center
方法中将精灵的
self.rect.topleft
(或
self.X
)设置为当前
self.Y
update
坐标。

self.rect.center = self.X, self.Y

我建议看看

pygame.sprite.spritecollide
方法。将你的敌人放入一个单独的精灵组中,然后通过以下方式获取碰撞的精灵:

collided_enemies = pg.sprite.spritecollide(player, enemies, False)
for collided_enemy in collided_enemies:
    # Do something with the collided_enemy.

这是一个最小的完整示例:

import sys
import pygame as pg


class Player(pg.sprite.Sprite):

    def __init__(self, pos, color):
        super().__init__()
        self.image = pg.Surface((50, 30))
        self.image.fill(color)
        self.rect = self.image.get_rect(center=pos)


def main():
    screen = pg.display.set_mode((640, 480))
    clock = pg.time.Clock()
    player = Player((100, 100), pg.Color('dodgerblue2'))
    enemy = Player((300, 100), pg.Color('sienna2'))
    enemy2 = Player((200, 300), pg.Color('sienna2'))
    all_sprites = pg.sprite.Group(player, enemy, enemy2)
    enemies = pg.sprite.Group(enemy, enemy2)

    done = False

    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True
            if event.type == pg.MOUSEMOTION:
                player.rect.center = event.pos

        all_sprites.update()

        collided_enemies = pg.sprite.spritecollide(player, enemies, False)
        for collided_enemy in collided_enemies:
            print(collided_enemy.rect)

        screen.fill((50, 50, 50))
        all_sprites.draw(screen)

        pg.display.flip()
        clock.tick(30)


if __name__ == '__main__':
    pg.init()
    main()
    pg.quit()
    sys.exit()
© www.soinside.com 2019 - 2024. All rights reserved.