2016-11-27 11 views
1

私はpygameを使用してBrick Breaker/Breakoutゲームを開発しようとしていますが、私は矢と一緒に動くときパドル(プレーヤー)の "ボール"を汚す厄介な問題に直面しています。あなたのためにコードを残しています。Pygame logic issue

import pygame 

pygame.init() 

isRunning = True 

WIDTH = 800 
HEIGHT = 600 

FPS = 60 

clock = pygame.time.Clock() 

window = pygame.display.set_mode((WIDTH, HEIGHT)) 

class Player(pygame.sprite.Sprite): 
    def __init__(self): 
     pygame.sprite.Sprite.__init__(self) 

     self.image = pygame.Surface((60, 30)) 
     self.image.fill((200, 255, 200)) 
     self.rect = self.image.get_rect() 
     self.rect.centerx = WIDTH/2 
     self.rect.bottom = HEIGHT - 30 

    def update(self): 
     self.speedx = 0 

     keystate = pygame.key.get_pressed() 
     if keystate[pygame.K_a]: 
      self.speedx = -5 

     if keystate[pygame.K_d]: 
      self.speedx = 5 

     self.rect.x += self.speedx 

     if self.rect.right + self.speedx > WIDTH: 
      self.rect.right = WIDTH 

     if self.rect.left + self.speedx < 0: 
      self.rect.left = 0 

     ball = Ball(self.rect.centerx, self.rect.top) 
     for i in all_sprites: 
      print(i) 
     all_sprites.add(ball) 

    def shoot(self): 
     ball = Ball(self.rect.centerx, self.rect.top) 
     all_sprites.add(ball) 
     balls.add(ball) 

class Ball(pygame.sprite.Sprite): 
    def __init__(self, x, y): 
     pygame.sprite.Sprite.__init__(self) 
     self.image = pygame.Surface((10, 10)) 
     self.image.fill((100, 150, 200)) 
     self.rect = self.image.get_rect() 
     self.rect.bottom = y 
     self.rect.centerx = x 
     self.speedy = -3 

    def update(self): 
     pass 
     #self.rect.y += self.speedy 

all_sprites = pygame.sprite.Group() 
balls = pygame.sprite.Group() 
player = Player() 
all_sprites.add(player) 

while isRunning: 

    clock.tick(FPS) 

    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      isRunning = False 

     if event.type == pygame.KEYDOWN: 
      if event.key == pygame.K_SPACE: 
       player.shoot() 

    window.fill((0, 0, 30)) 

    all_sprites.update() 

    all_sprites.draw(window) 

    pygame.display.flip() 

pygame.quit() 
quit() 

答えて

2

質問が分かりませんが、コードの問題はプレーヤーを更新するたびにボールを作成していることです。プレーヤーの更新メソッドで最後の4行を削除し、ボールの更新メソッドで行のコメントを外してください。すべてが正常に動作します。彼らは画面を終了するとき

その他のヒント

はボールを削除します。これにより、ゲームの実行が遅くなったり、クラッシュすることがなくなります。ボールの更新方法にif self.rect.bottom < 0: self.kill()を追加すると、それを無視することができます。

適宜、elifを使用してください。

プレーヤーの更新方法では、そのメソッド内でのみ使用される属性self.speedxを定義します。したがって、代わりにローカル変数を使用する方がよいでしょう。また、__init__メソッド以外の属性を定義するのは避けてください。

コードは少し変更されています。

import pygame 
pygame.init() 

is_running = True # Use lowercase_and_underscore for variable names. 

WIDTH = 800 
HEIGHT = 600 
FPS = 60 

clock = pygame.time.Clock() 
window = pygame.display.set_mode((WIDTH, HEIGHT)) 


class Player(pygame.sprite.Sprite): 
    def __init__(self): 
     pygame.sprite.Sprite.__init__(self) 

     self.image = pygame.Surface((60, 30)) 
     self.image.fill((200, 255, 200)) 
     self.rect = self.image.get_rect() 
     self.rect.centerx = WIDTH/2 
     self.rect.bottom = HEIGHT - 30 

    def update(self): 
     speedx = 0 # Don't define attributes outside __init__. Local variable works in this case instead. 

     keystate = pygame.key.get_pressed() 
     if keystate[pygame.K_a]: 
      speedx = -5 
     elif keystate[pygame.K_d]: # Use elif so it doesn't need to check this condition if the above is true. 
      speedx = 5 

     self.rect.x += speedx 

     if self.rect.right + speedx > WIDTH: 
      self.rect.right = WIDTH 
     elif self.rect.left + speedx < 0: # Use elif so it doesn't need to check this condition if the above is true. 
      self.rect.left = 0 

    def shoot(self): 
     ball = Ball(self.rect.centerx, self.rect.top) 
     all_sprites.add(ball) 
     balls.add(ball) 


class Ball(pygame.sprite.Sprite): 
    def __init__(self, x, y): 
     pygame.sprite.Sprite.__init__(self) 
     self.image = pygame.Surface((10, 10)) 
     self.image.fill((100, 150, 200)) 
     self.rect = self.image.get_rect() 
     self.rect.bottom = y 
     self.rect.centerx = x 
     self.speedy = -3 

    def update(self): 
     if self.rect.bottom < 0: # Chack if the ball has exit above the screen. 
      self.kill() # If it has it should delete itself. 
     self.rect.y += self.speedy 

all_sprites = pygame.sprite.Group() 
balls = pygame.sprite.Group() 
player = Player() 
all_sprites.add(player) 

while is_running: 

    clock.tick(FPS) 
    print(all_sprites) 

    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      is_running = False 
     elif event.type == pygame.KEYDOWN: 
      if event.key == pygame.K_SPACE: 
       player.shoot() 

    window.fill((0, 0, 30)) 
    all_sprites.update() 
    all_sprites.draw(window) 
    pygame.display.flip() 

pygame.quit() 
quit() 

EDIT:パドル上のボールを保ち、あなたはパドルでボールを参照するプレーヤークラスの属性self.current_ballを作成することができますSPACE

まずWITH LAUNCHING。次に、Playerクラスのupdateメソッドで、パドルに対するボールの位置を更新します。

ボールをパドルに保持するには、ボールのself.speedyを0から開始するように変更する必要があります。それ以外の場合は、ボールが作成された直後に移動します。 player.shoot()メソッドを呼び出すと、self.speedy = -3が設定され、ボールの移動が開始されます。

パドルの上に新しいボールを作成し、同じプロセスを繰り返すだけです。

import pygame 
pygame.init() 

is_running = True # Use lowercase_and_underscore for variable names. 

WIDTH = 800 
HEIGHT = 600 
FPS = 60 

clock = pygame.time.Clock() 
window = pygame.display.set_mode((WIDTH, HEIGHT)) 


class Player(pygame.sprite.Sprite): 
    def __init__(self): 
     pygame.sprite.Sprite.__init__(self) 

     self.image = pygame.Surface((60, 30)) 
     self.image.fill((200, 255, 200)) 
     self.rect = self.image.get_rect() 
     self.rect.centerx = WIDTH/2 
     self.rect.bottom = HEIGHT - 30 
     self.current_ball = Ball(self.rect.centerx, self.rect.top) 
     all_sprites.add(self.current_ball) 
     balls.add(self.current_ball) 

    def update(self): 
     speedx = 0 # Don't define attributes outside __init__. Local variable works in this case instead. 

     keystate = pygame.key.get_pressed() 
     if keystate[pygame.K_a]: 
      speedx = -5 
     elif keystate[pygame.K_d]: # Use elif so it doesn't need to check this condition if the above is true. 
      speedx = 5 

     self.rect.x += speedx 

     if self.rect.right + speedx > WIDTH: 
      self.rect.right = WIDTH 
     elif self.rect.left + speedx < 0: # Use elif so it doesn't need to check this condition if the above is true. 
      self.rect.left = 0 

     self.current_ball.rect.midbottom = self.rect.midtop # Set the ball position relative to paddle position. 

    def shoot(self): 
     self.current_ball.speedy = -3 # The ball should start moving. 
     self.current_ball = Ball(self.rect.centerx, self.rect.top) # Create a new ball on the paddle. 
     all_sprites.add(self.current_ball) 
     balls.add(self.current_ball) 


class Ball(pygame.sprite.Sprite): 
    def __init__(self, x, y): 
     pygame.sprite.Sprite.__init__(self) 
     self.image = pygame.Surface((10, 10)) 
     self.image.fill((100, 150, 200)) 
     self.rect = self.image.get_rect() 
     self.rect.bottom = y 
     self.rect.centerx = x 
     self.speedy = 0 # The ball don't move from the beginning. 

    def update(self): 
     if self.rect.bottom < 0: # Chack if the ball has exit above the screen. 
      self.kill() # If it has it should delete itself. 
     self.rect.y += self.speedy 

all_sprites = pygame.sprite.Group() 
balls = pygame.sprite.Group() 
player = Player() 
all_sprites.add(player) 

while is_running: 

    clock.tick(FPS) 
    print(all_sprites) 

    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      is_running = False 
     elif event.type == pygame.KEYDOWN: 
      if event.key == pygame.K_SPACE: 
       player.shoot() 

    window.fill((0, 0, 30)) 
    all_sprites.update() 
    all_sprites.draw(window) 
    pygame.display.flip() 

pygame.quit() 
quit() 
+0

これは実際に私が実装しようとしていたものではありません。あなたが使ったのと同じロジックを使って別のゲームでやったことがあります。 私の問題は、ボールを絶えず四角形で上に移動したい、上に移動しなければならないということです。 この問題を解決するのに手伝ってもらえますか? –

+0

編集:同様の問題を扱った投稿を見ました。その人は窓の表面を更新していませんでした。ちょうどその直腸が表示されていませんでした。私の視点では、スクリーンを吸う代わりに1回だけ描​​画するのではないからです。 http://stackoverflow.com/questions/39970906/pygame-move-a-square-on-the-screen-but-can-not-erase-the-previous-movements/39970939#39970939 –

+0

私は追加しましたあなたが探している実装の例。あなたのコードが画面をぼかしていた理由は、あなたがリンクした質問で私が答えた理由のためではありませんでした。あなたの問題は、プレーヤーを更新するたびに毎回60回の新しいボールを作成していたことでした。だから1秒後に別の位置に60個のボールを作りました。あなたは一つのボールを作り、それを動かすべきです。 –