2017-05-19 13 views
1

私はこれに似た5〜6の質問があることを知っていますが、答えのどれも私を助けませんでした。完全なnoob)、私は私の特定の場合を表示しようとします。PyGameのスプライト衝突テスト(試してみました:rectとgroup)

私はPyGame(Python lib)でスプライト衝突テストをしようとしていますが、動作させることができません。衝突すると "False"となり、なぜ、2日連続して検索しているのか理解していない。

私のゲームでは、Player(オブジェクトと呼んでいます)とオブジェクトEnemy(私は「敵」と呼んでいます)を持っています。両方の__init__は非常に似ていて、両方とも矩形が生成されています。 (ウィッヒはすでに素晴らしいです衝突をテストする場合

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 

、これらが何かを返す2つの方法がある:私はこれを持って、敵のために

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

この

はプレーヤーのための __init__です私にとっては、エラーを返すだけの試みがあったからです)、衝突しても、常に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://stackoverflow.com/help/mcve)を提供してください。 --- Sidenote:新しいインスタンスを作成するたびに再度読み込まなければならないので、イメージをクラスに読み込まないでください。メインループが開始する前にそれらをグローバルにロードしてから、それらを再利用するだけです。 – skrx

+1

修正しました。ありがとうございます! –

答えて

0

衝突検出に問題がある場合は、rect秒のスプライトを印刷すると便利です。 print(player.rect)。矩形は決して更新されず、同じ位置に留まります。衝突検出に使用されるため、スプライトは衝突しません。 update方法で現在のself.Xself.Y座標にスプライトのあなたがself.rect.center(またはself.rect.topleft)を設定する必要があなたの問題を解決するために

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

非常にありがとう!私はそれだけであると信じることはできません、私のrectsの位置をリフレッシュの問題!お手伝いありがとう! –

+0

ようこそ。アップして、有益な回答を受け入れてください。 – skrx

+0

もう1つのこと: 'clock.tick()'はオブジェクトごとに1回ではなく、フレームごとに1回しか呼び出されません。メインのwhileループで 'time_passed = clock.tick()'を呼び出すのがよいでしょう。そして、 'time_passed'をスプライトの' update'メソッドに渡してください。そして、[sprite groups](http://programarcadegames.com/index.php?chapter=introduction_to_sprites&lang=de#section_13)に慣れてください。 – skrx