ボールの反射音
ボールがブロックやパドルに当たったとき音が鳴るように改良します。効果音はザ・マッチメイカァズさんからお借りしています。
効果音のロード
まず効果音をロードします。効果音はすべてBallのクラス変数へセットします。クラス変数なのでボールのオブジェクトをたくさん作ってもサウンドのロードは1回で済みます。サウンドのようにすべてのボールに共通した属性はクラス変数とした方がいいですね。
今、気がつきましたがボールやブロックの画像もクラス変数にした方がよかったです。画像のロードが1回で済みますね。今はインスタンス変数にしているのでオブジェクトを作成するたびに画像をファイルからロードしてしまいます。
# サウンドのロード Ball.paddle_sound = load_sound("wood00.wav") # パドルとの衝突音 Ball.brick_sound = load_sound("chari06.wav") # ブロックとの衝突音 Ball.fall_sound = load_sound("fall06.wav") # ボールを落とした音
サウンドのロードはmain()で1回だけ実行します。ボールがパドルと衝突したときの音はBall.paddle_sound、ボールがブロックと衝突したときの音はBall.brick_sound、ボールをパドルで受け損ねて落としたときの音はBall.fall_soundにロードします。 Ballは特定のオブジェクト名ではなくクラス名なので上の変数はすべてクラス変数となりすべてのボールオブジェクトで共有されます。
上のコードでpaddle_soundとかの変数がBallクラスで定義されてないのに代入してよいのか?疑問に思った方もいるかもしれません。C++やJavaのような言語ではこのようなマネはできないのですがPythonではOKです。Pythonでは、インスタンス変数やクラス変数は代入すると同時に自動的に作られます。だから上のような書き方はOKです。とはいうものの代入する前に変数にアクセスすることはできません。ここら辺はプログラマがしっかり管理してないとダメですね。
def load_sound(filename): filename = os.path.join("data", filename) return pygame.mixer.Sound(filename)
load_sound()は、効果音をロードしてサウンドオブジェクトを返す関数です。効果音のロードと再生は非常に簡単ですが、基礎編の効果音のロードと再生(2008/5/11)でも解説しました。
効果音の再生
効果音がロードできたので適切な場所で鳴るようにします。すべてBallのmove()で鳴らしています。
def move(self): """ボールの移動""" self.rect.centerx += self.dx self.rect.centery += self.dy # 壁との反射 if self.rect.left < SCR_RECT.left: # 左側 self.rect.left = SCR_RECT.left self.dx = -self.dx # 速度を反転 if self.rect.right > SCR_RECT.right: # 右側 self.rect.right = SCR_RECT.right self.dx = -self.dx if self.rect.top < SCR_RECT.top: # 上側 self.rect.top = SCR_RECT.top self.dy = -self.dy # パドルとの反射 if self.rect.colliderect(self.paddle.rect) and self.dy > 0: self.dy = -self.dy self.paddle_sound.play() # ボールを落とした場合 if self.rect.top > SCR_RECT.bottom: self.update = self.start # ボールを初期状態に self.fall_sound.play() # ブロックを壊す # ボールと衝突したブロックリストを取得 bricks_collided = pygame.sprite.spritecollide(self, self.bricks, True) if bricks_collided: # 衝突ブロックがある場合 oldrect = self.rect for brick in bricks_collided: # 各衝突ブロックに対して # ボールが左から衝突 if oldrect.left < brick.rect.left < oldrect.right < brick.rect.right: self.rect.right = brick.rect.left self.dx = -self.dx # ボールが右から衝突 if brick.rect.left < oldrect.left < brick.rect.right < oldrect.right: self.rect.left = brick.rect.right self.dx = -self.dx # ボールが上から衝突 if oldrect.top < brick.rect.top < oldrect.bottom < brick.rect.bottom: self.rect.bottom = brick.rect.top self.dy = -self.dy # ボールが下から衝突 if brick.rect.top < oldrect.top < brick.rect.bottom < oldrect.bottom: self.rect.top = brick.rect.bottom self.dy = -self.dy self.brick_sound.play()
パドルと反射したとき、ボールを落としたとき、ブロックを壊したときに効果音をplay()で鳴らしています。クラス変数にもselfは必要です。壁と当たったときにも鳴らそうと思いましたが、うるさかったので止めました。