質問が分かりませんが、コードの問題はプレーヤーを更新するたびにボールを作成していることです。プレーヤーの更新メソッドで最後の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()
これは実際に私が実装しようとしていたものではありません。あなたが使ったのと同じロジックを使って別のゲームでやったことがあります。 私の問題は、ボールを絶えず四角形で上に移動したい、上に移動しなければならないということです。 この問題を解決するのに手伝ってもらえますか? –
編集:同様の問題を扱った投稿を見ました。その人は窓の表面を更新していませんでした。ちょうどその直腸が表示されていませんでした。私の視点では、スクリーンを吸う代わりに1回だけ描画するのではないからです。 http://stackoverflow.com/questions/39970906/pygame-move-a-square-on-the-screen-but-can-not-erase-the-previous-movements/39970939#39970939 –
私は追加しましたあなたが探している実装の例。あなたのコードが画面をぼかしていた理由は、あなたがリンクした質問で私が答えた理由のためではありませんでした。あなたの問題は、プレーヤーを更新するたびに毎回60回の新しいボールを作成していたことでした。だから1秒後に別の位置に60個のボールを作りました。あなたは一つのボールを作り、それを動かすべきです。 –