基于 python 3.9.12:
import pygame, sys
from pygame.locals import *
## 定义球类
class MyBallClass(pygame.sprite.Sprite):
def __init__(self, image_file, speed, location):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
self.speed = speed
def move(self):
global points, score_text
self.rect = self.rect.move(self.speed)
if (self.rect.left < 0 or self.rect.right > screen.get_width()):
self.speed[0] = -self.speed[0]
hit_wall.play()
if (self.rect.top <= 0):
self.speed[1] = -self.speed[1]
points = points + 1
score_text = font.render(str(points), 1, (0, 0, 0))
get_point.play()
## 定义挡板类
class MyPaddleClass(pygame.sprite.Sprite):
def __init__(self, location):
pygame.sprite.Sprite.__init__(self)
image_surface = pygame.surface.Surface([100, 20])
image_surface.fill([0, 0, 0])
self.image = image_surface.convert()
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode([640, 640])
clock = pygame.time.Clock()
ball_speed = [10, 5]
# 滚动的球的显示效果
myBall = MyBallClass('../pygame/wackyball.bmp', ball_speed, [50, 50])
ballGroup = pygame.sprite.Group(myBall)
paddle = MyPaddleClass([270, 400])
## 分数
points = 0
## 剩余生命值
lives = 2
##done = False
pygame.time.delay(1000)
## 加载背景音乐
pygame.mixer.music.load('bg_music.mp3')
# 设置音量
pygame.mixer.music.set_volume(0.30)
## 负数表示连续播放
pygame.mixer.music.play(-1)
## 挡板击打球的音效
hit = pygame.mixer.Sound('hit_paddle.wav')
hit.set_volume(0.4)
## 球碰到两边的墙的音效
hit_wall = pygame.mixer.Sound('hit_wall.wav')
hit_wall.set_volume(0.4)
## 玩家得分时的音效
get_point = pygame.mixer.Sound('get_point.wav')
get_point.set_volume(0.2)
## 重新开始音效
new_life = pygame.mixer.Sound('new_life.wav')
new_life.set_volume(0.5)
## 漏球音效
splat = pygame.mixer.Sound('splat.wav')
splat.set_volume(0.5)
## 游戏终结音效
bye = pygame.mixer.Sound('game_over.wav')
bye.set_volume(0.6)
def gameOver():
## 游戏结束
## pause() 中断背景音乐
## pygame.mixer.music.pause()
## fadeout() 背景音乐淡出效果
pygame.mixer.music.fadeout(2000)
pygame.time.delay(2000)
## 显示最终得分
tips_text = 'Game Over'
score_text = 'Your final score is: ' + str(points)
# 使用 pygame.font.Font()从一个字体文件中创建一个 Font 对象
# None 表示加载 pygame 的默认字体, 这里 70 表示字号
# 调用 render() 方法在一个新 Surface 对象上绘制文本
# render('文本内容’, 是否抗锯齿, 字体颜色, backgroundcolor = None)
tips_surface = pygame.font.Font(None, 70).render(tips_text, 1, (255, 0, 0))
score_surface = pygame.font.Font(None, 50).render(score_text, 1, (0, 255, 255))
screen.blit(tips_surface, [screen.get_width() / 2 - tips_surface.get_width() / 2, 100])
screen.blit(score_surface, [screen.get_width() / 2 - score_surface.get_width() / 2, 200])
pygame.display.flip()
# 播放终止提示音,
# play(times) 实际播放次数为 times + 1
bye.play(2)
pygame.time.delay(2000)
def quitGame():
pygame.quit()
sys.exit()
while (1):
clock.tick(30)
screen.fill([255, 255, 255])
# 显示分数
font = pygame.font.Font(None, 50)
score_text = font.render(str(points), 1, (0, 0, 0))
screen.blit(score_text, [10, 10])
# 显示生命值
for i in range(lives):
width = screen.get_rect().width
screen.blit(myBall.image, [width - 40 * i, 20])
# 滚动
myBall.move()
for event in pygame.event.get():
if (event.type == pygame.QUIT):
# 点击左上角退出游戏
quitGame()
elif (event.type == pygame.MOUSEMOTION):
# 移动鼠标时更新挡板位置
paddle.rect.centerx = event.pos[0]
# 挡板是否接住球
if (pygame.sprite.spritecollide(paddle, ballGroup, False)):
myBall.speed[1] = -myBall.speed[1]
hit.play()
# 没及时接住,掉下去了
if (myBall.rect.top >= screen.get_rect().bottom):
lives -= 1
pygame.time.delay(500)
splat.play()
myBall.rect.topleft = [50, 50]
if (lives <= 0):
# 生命用完了,游戏结束
pygame.time.delay(1000)
gameOver()
##quitGame()
break
else:
pygame.time.delay(1000)
myBall.rect.topleft = [(screen.get_rect().width) - 40 * lives, 20]
new_life.play()
screen.blit(myBall.image, myBall.rect)
screen.blit(paddle.image, paddle.rect)
pygame.display.flip()