用Python Pygame编写弹珠游戏

结合之前所学,在这一节中,我们使用 Pygame 来编写一个小游戏——弹球游戏。

这个游戏中,我们通过移动鼠标来控制挡板,从而反弹弹球得分。可以通过点击鼠标左键,将挡板变长,以便降低游戏的难度;也可以通过点击鼠标的右键,将挡板变短,从而提高游戏的难度。

如果挡板没有接到弹球,玩家就会损失一条生命,而当玩家的生命数为零时,就无法再移动挡板。如果还想玩游戏,可以点击 F1 按键,重新开始游戏。生命数和得分都会显示在窗口的顶部,并且我们还为这款游戏增加了背景音乐。

完整代码如下。
import pygame # 导入pygame模块
pygame.init() # 创建 pygame
screen = pygame.display.set_mode([800,600]) # 创建窗口

# 创建颜色常量
WHITE = (255,255,255)
BLACK = (0,0,0)

ball = pygame.image.load("ball.png") # 加载弹球的图像
ballx = 0 # 弹球的X坐标
bally = 0 # 弹球的Y坐标
speedx = 5 # 弹球在X坐标方向移动像素
speedy = 5 # 弹球在Y坐标方向移动像素
paddlew = 100 # 挡板的宽
paddleh = 15  # 挡板的高
paddlex = 300 # 挡板的X坐标
paddley = 570 # 挡板的Y坐标

font = pygame.font.SysFont("SimHei", 24) # 设置支持中文的字体
timer = pygame.time.Clock() #创建了Clock对象

points = 0 # 得分
lives = 3  # 生命数

pop=pygame.mixer.Sound("sample.wav") # 加载背景音乐
pop.play()  # 播放背景音乐

# 游戏循环
Running = True
while Running:
    # 事件循环        
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            Running = False

        if event.type==pygame.MOUSEBUTTONDOWN:
            # 按下左键,并且挡板小于400的时候,挡板长度翻倍
            if pygame.mouse.get_pressed()[0] and paddlew<400:
                paddlew=paddlew*2
            # 按下右键,并且挡板大于20的时候,挡板长度减半 
            elif pygame.mouse.get_pressed()[2] and paddlew>20:
                paddlew=paddlew/2

        if event.type==pygame.KEYDOWN:
            # 按下F1键盘,重新开始游戏
            if event.key==pygame.K_F1:
                lives=3
                points=0
                pop.play()

    #生命数为零,停止游戏           
    if lives==0: 
        text = font.render("游戏结束", True, WHITE)
        screen.blit(text, (350,270)) # 复制文本surface到主surface上
        pygame.display.update() # 显示文本
        pop.stop() # 停止音乐播放
        continue # 结束单次while循环
    ballx += speedx  # 移动弹球的X坐标
    bally += speedy # 移动弹球的Y坐标

    #如果弹球超出窗口左边或右边,将弹球方向翻转       
    if ballx <= 0 or ballx + ball.get_width() >= 800:
        speedx = -speedx

    #如果弹球超出窗口底部,生命数减1,并且将弹球方向翻转
    if bally+ball.get_height()>=600:
        lives-=1
        speedy = -speedy        

    #如果弹球超出窗口顶部,将弹球方向翻转
    if bally <= 0: 
        speedy = -speedy

    screen.fill(BLACK) # 用白色填充Surface对象
    screen.blit(ball, (ballx, bally)) # 复制弹球surface到主surface上

    # 绘制和移动挡板
    paddlex = pygame.mouse.get_pos()[0] # X坐标随着鼠标移动而变化   
    pygame.draw.rect(screen, WHITE, (paddlex, paddley, paddlew, paddleh))

    # 如果弹球的底部碰到弹球而且速度大于0,并且一半的弹球的X坐标落在挡板上,弹球就可以反弹
    if bally + ball.get_height() >= paddley  and speedy > 0:
        if ballx + ball.get_width() /2 >= paddlex and ballx + ball.get_width() / 2 <= paddlex + paddlew:      
            points += 1 # 得分加1
            speedy = -speedy # 将弹球方向翻转

    # 绘制生命数和得分
    draw_string = "生命数: " + str(lives) + " 得分: " + str(points)
    text = font.render(draw_string, True, WHITE)
    text_rect = text.get_rect()
    text_rect.centerx = screen.get_rect().centerx
    text_rect.y = 10
    screen.blit(text, text_rect)

    pygame.display.update() # 刷新
    timer.tick(60) # 帧速率为60fps
pygame.quit() # 退出程序

这部分代码中的知识点我们前面都已经介绍过,这里不再专门说明了。程序运行结果如下图所示。读者可以通过运行这个程序,来体验一下这款游戏,以进一步加深对我们之前所学知识的理解。