PyGame中的雪碧碰撞测试(尝试:rect和组)

问题描述:

我知道有近5或6个问题类似于我正在做的这个,但没有一个答案帮助了我(他们可能会,如果我不是完成noob),所以我会试着展示我的具体情况。我试图在PyGame(Python库)做一个精灵碰撞测试,但我不能得到它的工作,所有我碰到时是“假”,它根本不会工作,我可以'不知道为什么,一直在寻找连续两天。PyGame中的雪碧碰撞测试(尝试:rect和组)

在我的游戏中,我有对象玩家(我称之为“伙计”)和对象敌人(我称之为“敌人”)。两者上的__init__非常相似,并且都产生了rects。

这是__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) 

我已经为导向,以显示更多的代码,所以这个问题可以发现(EDIT) ,所以它 (我也要去在全球加载精灵,将它们作为参数传递给对象,提示坦克)。

播放器目标:

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

完蛋了,感谢在我的岗位反馈!

+1

你的代码示例是不完整的,足以发现其中的错误。所提到的碰撞检测功能应能正常工作。请编辑您的帖子并提供一个[最小,完整且可验证的示例](http://*.com/help/mcve),我们可以复制并执行。 ---旁注:不要在你的类中加载图像,因为每次创建新实例时都必须重新加载它们。在主循环开始之前全局加载它们,然后重新使用它们。 – skrx

+1

修正了它,谢谢! –

如果碰撞检测有问题,通常会帮助打印精灵的rect,例如, print(player.rect)。它会告诉你rects永远不会更新,并且它们保持在同一个位置,并且因为它们用于碰撞检测,所以你的sprite不会碰撞。

要解决你的问题,你必须精灵的设定self.rect.center(或self.rect.topleft),以当前self.Xself.Yupdate方法坐标。

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

非常感谢你!我不能相信那只是它,只是提升我的反应姿势!感谢您的帮助! –

+0

不客气。请注意并接受有用的答案。 – skrx

+0

还有一件事:'clock.tick()'应该每帧只调用一次,而不是每个对象一次。最好在main while循环中调用'time_passed = clock.tick()',然后将'time_passed'传递给sprite的'update'方法。并熟悉[sprite groups](http://programarcadegames.com/index.php?chapter=introduction_to_sprites&lang=de#section_13)。 – skrx