Pygame:声音只播放8次,然后关闭4次,然后打开,然后关闭,然后再打开
Posted
技术标签:
【中文标题】Pygame:声音只播放8次,然后关闭4次,然后打开,然后关闭,然后再打开【英文标题】:Pygame: sound only playing 8 times, then off 4 times, then on, then off, then back on 【发布时间】:2015-10-23 17:36:55 【问题描述】:我有一个奇怪的现象,我的声音文件播放 8 次,然后关闭,然后播放,然后关闭,然后再次播放。
import sys, pygame, os, time
# Force static position of screen
os.environ['SDL_VIDEO_CENTERED'] = '1'
# to get rid of sound lag
pygame.mixer.pre_init(44100, -16, 8, 2048)
# Runs imported module
pygame.init()
# Constants
UP = 'up'
DOWN = 'down'
BOOSTSP = 12
NORMSP = 8
WIN_W = 920
WIN_H = 570
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
PADDLE_HEIGHT = 440
BALL_WIDTH = BALL_HEIGHT = 20
class Entity(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
class Paddle(Entity):
def __init__(self, x, y):
Entity.__init__(self)
self.x = x
self.y = y
self.speed = 8
self.pWidth = 20
self.score = 0
self.pHeight = PADDLE_HEIGHT
self.paddle = pygame.Surface((self.pWidth, self.pHeight))
self.paddle = self.paddle.convert()
self.lp_moveUP = self.lp_moveDOWN = self.rp_moveUP = self.rp_moveDOWN = False
def update(self, down, up):
# Adjust speed
if up or down or up or down:
if up:
self.y -= self.speed
if down:
self.y += self.speed
# paddle movement
if self.y < 0:
self.y = 0
if self.y > WIN_H - self.pHeight:
self.y = WIN_H - self.pHeight
class Ball(Entity):
def __init__(self, x, y):
Entity.__init__(self)
self.speed = [-5, -5]
self.ball = pygame.Surface((BALL_WIDTH, BALL_HEIGHT))
self.ball = self.ball.convert()
self.rect = pygame.Rect(WIN_W/2, WIN_H/2-(BALL_HEIGHT/2), BALL_WIDTH, BALL_HEIGHT)
def restart(self, lPaddle, rPaddle, screen):
time.sleep(2)
self.rect.y = WIN_H/2-(BALL_HEIGHT/2)
self.rect.x = WIN_W/2
lPaddle.y = (WIN_H/2) - (PADDLE_HEIGHT/2)
rPaddle.y = (WIN_H/2) - (PADDLE_HEIGHT/2)
return True
请注意,在“更新”方法中,如果球击中球拍,我会播放声音。您可以看到我打印了“playSound”函数的返回值,它是 play() 方法的返回值。
def update(self, lPaddle, rPaddle, sound, playSound):
# If ball hits the top or bottom
if self.rect.top < 0 or self.rect.top > WIN_H - BALL_HEIGHT:
self.speed[1] = -self.speed[1]
print playSound(sound["bop"], 1)
# If ball hits paddle
if(self.speed[0] < 0):
if (self.rect.left > lPaddle.x + lPaddle.pWidth - 15 and self.rect.left < lPaddle.x + lPaddle.pWidth-10) and (self.rect.top > lPaddle.y and self.rect.top < (lPaddle.y + lPaddle.pHeight)):
self.speed[0] = -self.speed[0]
print playSound(sound["beep"], 1)
else:
if (self.rect.left > rPaddle.x - 15 and self.rect.left < rPaddle.x - 5) and (self.rect.top > rPaddle.y and self.rect.top < (rPaddle.y + rPaddle.pHeight)):
self.speed[0] = -self.speed[0]
print playSound(sound["beep"], 1)
self.rect = self.rect.move(self.speed)
# Returns True for .5 seconds, then False for .5 seconds.
def checkTime(cur, beg):
return (cur - beg) % 1000 < 500
# Takes in string, (x, y) and size. Returns text and rect.
def txtRect(sen, xpos, ypos, size):
phrase = pygame.font.Font(None, size)
phrase = phrase.render(sen, 1, BLACK)
phraseRect = phrase.get_rect()
phraseRect.x = xpos
phraseRect.y = ypos
return phrase, phraseRect
# Loads sound files
def playSound(sound, volume):
sound.set_volume(volume)
return sound.play()
# Loads sound files
def loadSound():
sound =
sound["beep"] = pygame.mixer.Sound("sound/beep.ogg")
sound["boom"] = pygame.mixer.Sound("sound/boom.ogg")
sound["bop"] = pygame.mixer.Sound("sound/bop.ogg")
sound["choose"] = pygame.mixer.Sound("sound/choose.ogg")
sound["count"] = pygame.mixer.Sound("sound/count.ogg")
sound["end"] = pygame.mixer.Sound("sound/end.ogg")
sound["music"] = pygame.mixer.Sound("sound/music.ogg")
sound["select"] = pygame.mixer.Sound("sound/select.ogg")
return sound
def main():
size = WIN_W, WIN_H
fps = 60
# Used for count down
countDown = 3
decrement = True
pygame.display.set_caption('Pong')
screen = pygame.display.set_mode(size, pygame.SRCALPHA)
# Create our objects
ball = Ball((WIN_W/2)-(BALL_WIDTH/2), WIN_H/2-(BALL_HEIGHT/2))
lPaddle = Paddle(WIN_W/15, (WIN_H/2)-(PADDLE_HEIGHT/2))
rPaddle = Paddle(WIN_W/1.1, (WIN_H/2)-(PADDLE_HEIGHT/2))
# Create sound objects
sound = loadSound()
clock = pygame.time.Clock()
beg_time = pygame.time.get_ticks()
intro = count = play = outro = True
lp_moveUP = lp_moveDOWN = rp_moveDOWN = rp_moveUP = False
while intro:
# Print background
screen.fill(WHITE)
# Title Text: Pong
text = txtRect("Pong", 0, 0, 200)
text = txtRect("Pong", WIN_W/2-(text[1].width/2), WIN_H/4, 200)
screen.blit(text[0], text[1])
# Blinking Text: Click here to start
text = txtRect("- Click here to start -", 0, 0, 50)
text = txtRect("- Click here to start -", WIN_W/2-(text[1].width/2), WIN_H/1.7, 50)
if checkTime(beg_time, pygame.time.get_ticks()):
screen.blit(text[0], text[1])
# Checks if window exit button pressed
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN or pygame.key.get_pressed()[pygame.K_RETURN] != 0:
screen.blit(text[0], text[1])
pygame.display.flip()
playSound(sound["select"], .3)
pygame.time.wait(1500)
intro = False
# Limits frames per iteration of while loop
clock.tick(fps)
# Writes to main surface
pygame.display.flip()
# Gameplay
while play:
# Print background
screen.fill(WHITE)
screen.blit(lPaddle.paddle, (lPaddle.x, lPaddle.y))
screen.blit(rPaddle.paddle, (rPaddle.x, rPaddle.y))
screen.blit(ball.ball, ball.rect)
# Print Score
sen = "Player 1 score: " + str(lPaddle.score)
text = txtRect(sen, WIN_W/6.5, WIN_H/57, 40)
screen.blit(text[0], text[1])
sen = "Player 2 score: " + str(rPaddle.score)
text = txtRect(sen, WIN_W - WIN_W/6.5 - text[1].width, WIN_H/57, 40)
screen.blit(text[0], text[1])
# Countdown
if count:
text = txtRect(str(countDown), 0, 0, 75)
text = txtRect(str(countDown), WIN_W/3.5 - (text[1].width/2), WIN_H/4, 75)
screen.blit(text[0], text[1])
text = txtRect(str(countDown), WIN_W/1.4 - (text[1].width/2), WIN_H/4, 75)
screen.blit(text[0], text[1])
# Writes to main surface
pygame.display.flip()
playSound(sound["count"], 1)
time.sleep(1)
countDown -= 1
# bug fix: prevent display of 0.
if countDown == 0:
count = False
# Gameplay
else:
# Checks if window exit button pressed
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
# Keyboard mechanics
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
if event.key == pygame.K_UP:
rp_moveUP = True
rp_moveDOWN = False
elif event.key == pygame.K_DOWN:
rp_moveUP = False
rp_moveDOWN = True
if event.key == pygame.K_w:
lp_moveUP = True
lp_moveDOWN = False
elif event.key == pygame.K_s:
lp_moveUP = False
lp_moveDOWN = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
rp_moveUP = False
elif event.key == pygame.K_DOWN:
rp_moveDOWN = False
if event.key == pygame.K_w:
lp_moveUP = False
elif event.key == pygame.K_s:
lp_moveDOWN = False
lPaddle.update(lp_moveDOWN, lp_moveUP)
rPaddle.update(rp_moveDOWN, rp_moveUP)
ball.update(lPaddle, rPaddle, sound, playSound)
# If ball moves off the screen
if ball.rect.left < 0 - ball.rect.width or ball.rect.left > WIN_W + ball.rect.width:
if ball.rect.left < 0:
rPaddle.score += 1
elif ball.rect.left > WIN_H + ball.rect.width:
lPaddle.score += 1
playSound(sound["end"], 1)
count = ball.restart(lPaddle, rPaddle, screen)
countDown = 3
# Game ends
if lPaddle.score == 3 or rPaddle.score == 3:
playSound(sound["boom"], 1)
break
# Limits frames per iteration of while loop
clock.tick(fps)
# Writes to main surface
pygame.display.flip()
# Gameplay
while outro:
# Print background
screen.fill(WHITE)
# End Text: Player wins
if lPaddle.score == 3 or rPaddle.score == 3:
if lPaddle.score == 3:
sen = "Player 1 Wins!"
else:
sen = "Player 2 Wins!"
text = txtRect(sen, 0, 0, 40)
text = txtRect(sen, WIN_W/2-(text[1].width/2)-130, WIN_H/4, 100)
screen.blit(text[0], text[1])
text = txtRect("- Click here to continue -", 0, 0, 50)
text = txtRect("- Click here to continue -", WIN_W/2-(text[1].width/2), WIN_H/1.7, 50)
# Blinking Text: Click here to start
if checkTime(beg_time, pygame.time.get_ticks()):
screen.blit(text[0], text[1])
# Checks if window exit button pressed
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN or pygame.key.get_pressed()[pygame.K_RETURN] != 0:
screen.blit(text[0], (WIN_W/2-(text[1].width/2), WIN_H/1.7))
pygame.display.flip()
loadSound("choose", 1)
pygame.time.wait(1500)
outro = False
main()
# Limits frames per iteration of while loop
clock.tick(fps)
# Writes to main surface
pygame.display.flip()
if __name__ == "__main__":
main()
当我玩游戏时,前奏会响起,然后当球从球拍上弹起时,程序只播放 8 次,每次我玩游戏时结果完全相同。这是我的输出。任何帮助将非常感激。
/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /Users/DanielLee/PycharmProjects/newPong/pong7_sound.py
通道对象位于 0x1002c42e8
通道对象位于 0x1002c42e8
通道对象位于 0x1002c42e8
通道对象位于 0x1002c42e8
通道对象位于 0x1002c42e8
通道对象位于 0x1002c42e8
通道对象位于 0x1002c42e8
通道对象位于 0x1002c42e8
无
无
无
无
通道对象位于 0x1002c42e8
无
通道对象位于 0x1002c42e8
通道对象位于 0x1002c42e8
【问题讨论】:
【参考方案1】:我认为声音在播放然后不播放的原因与重复使用的频道有关。解决方案是为声音设置一个“最大时间”,将其关闭并释放通道供以后使用。
来自文档:play(loops=0, maxtime=0, fade_ms=0)
从 play() 的文档中可以看出,第二个参数是“maxtime”,可以设置它以确保频道可用。
我对它的工作原理没有清楚的了解,即使我对错误的理解是有效的,所以任何澄清都将不胜感激。
【讨论】:
以上是关于Pygame:声音只播放8次,然后关闭4次,然后打开,然后关闭,然后再打开的主要内容,如果未能解决你的问题,请参考以下文章