ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
   在这篇博文中,我们准备为打飞机小游戏添加一个暂停的功能,即用户在游戏过程中随时可以通过单击屏幕右上方的一个暂停按钮来暂停和恢复游戏。这个功能看似比较简单,但其中涉及了鼠标操作、图片切换、代码结构的重置等等,接下来我们一一进行介绍。   1、加载暂停按钮图标   在image文件夹下一共有四张暂停按钮的图片,分别为深色和浅色两组,首先在main()函数中加载相关图片资源并初始化暂停/开始标志位: ~~~ paused = False # 标志是否暂停游戏 pause_nor_image = pygame.image.load("image/game_pause_nor.png") # 加载暂停相关按钮 pause_pressed_image = pygame.image.load("image/game_pause_pressed.png") resume_nor_image = pygame.image.load("image/game_resume_nor.png") resume_pressed_image = pygame.image.load("image/game_resume_pressed.png") paused_rect = pause_nor_image.get_rect() paused_rect.left, paused_rect.top = width - paused_rect.width - 10, 10 # 设置暂停按钮位置 paused_image = pause_nor_image # 设置默认显示的暂停按钮 ~~~   代码看起来有点繁琐,其实每句代码的功能都十分简单。先设置一个暂停/开始标志位“paused”,为true表示暂停状态,为false表示非暂停状态。然后加载四张图片,注意这里四张图片都是由特定含义的,“pause_nor_image”代表未选中状态下的暂停按钮, “pause_pressed_image”代表选中状态下的暂停按钮,“resume_nor_image”代表未选中状态下的开始按钮,“resume_pressed_image”代表选中状态下的开始按钮,鼠标移动到按钮区域按钮就变为选中状态。然后创建一个“paused_image”变量用以保存当前需要显示的按钮图片,游戏开始时默认为“pause_nor_image”。注意这里需要事先得到并设置好按钮图片的区域位置,在接下来的程序中会用到。   2、定义“选中/未选中”状态切换   之前已经说过,选中和未选中状态是由鼠标是否移动到按钮区域来决定的,因此需要定义鼠标移动的事件响应函数,先上代码: ~~~ # ====================检测用户的退出及暂停操作==================== for event in pygame.event.get(): # 响应用户的偶然操作 if event.type == QUIT: # 如果用户按下屏幕上的关闭按钮,触发QUIT事件,程序退出elif event.type == MOUSEMOTION: if paused_rect.collidepoint(event.pos): # 如果鼠标悬停在按钮区域 if paused: # r如果当前的状态是暂停 paused_image = resume_pressed_image else: paused_image = pause_pressed_image else: if paused: paused_image = resume_nor_image else: paused_image = pause_nor_image ~~~   对于鼠标移动事件,每当鼠标指针的位置坐标发生变化时,都会触发一次“MOUSEMOTION”事件,在系统接收到鼠标移动事件后,首先要判断当前鼠标指针是否位于按钮的矩形区域,这个功能可以通过rect类的的collidepoint()成员函数完成,它能够实现判断一个坐标点(例如当前的event.pos)是否在调用者的(一个矩形对象)的区域范围之内。如果鼠标处于按钮区域,则将当前显示的图片指定为“选中状态下的开始/暂停”(resume_pressed_image和pause_pressed_image),否则设定为“非选中状态下的开始/暂停”(resume_nor_image和pause_nor_image),这些小逻辑还是挺磨人的,需要仔细的推敲一把才能理清。   3、定义“暂停/开始”状态切换   程序的暂停/开始时通过鼠标单击的动作来决定的,因此需要编写鼠标单击事件的响应函数,在函数中修改“paused”标志位的值来控制暂停/开始状态的切换: ~~~ for event in pygame.event.get(): # 响应用户的偶然操作 if event.type == QUIT: # 如果用户按下屏幕上的关闭按钮,触发QUIT事件,程序退出elif event.type == MOUSEBUTTONDOWN: button_down_sound.play() if event.button == 1 and paused_rect.collidepoint(event.pos): # 如果检测到用户在指定按钮区域按下鼠标左键 paused = not paused if paused: # r如果当前的状态是暂停 paused_image = resume_pressed_image pygame.time.set_timer(supply_timer, 0) # 关闭补给机制以及所有音效 pygame.mixer.music.pause() pygame.mixer.pause() else: paused_image = pause_pressed_image pygame.time.set_timer(supply_timer, 30 * 1000) # 开启补给机制以及所有音效 pygame.mixer.music.unpause() pygame.mixer.unpause() ~~~   简单分析一下这段代码:当鼠标按下时(无论是左键、右键还是中间滚轮)会触发“MOUSEBUTTONDOWN”事件。程序检测到鼠标按下的消息事件后,先播放一声鼠标单击的音效,然后检测按键顺序以及鼠标位置。如果检测到当前为左键单击(event.button == 1)并且鼠标指针位于按钮区域之内(paused_rect.collidepoint(event.pos)返回true),则认为用户发出了有效的暂停指令,此时需要将paused标志位取反。紧接着就需要判断当前状态是暂停还是非暂停,如果单击鼠标之后变为暂停状态(paused为真),则需要关闭补给机制、关闭背景音效、关闭混音器,将按钮图片设置为resume_pressed_image(待开始),让程序静静的等待即可;相反若鼠标单击之后为开始状态,则需要重新开启这些机制,同时调整按钮图片为pause_pressed_image(待暂停)。   4、将paused标志位加入到控制语句   在完成了准备阶段的工作之后,我们开始让paused这个控制标志位真正参与到程序的控制结构中。由于之前在添加“life_num”控制变量的过程中已经对程序结构进行了统一调整,这里的工作就变得相对简单,只需在“life_num”的判断语句之后加上对paused标志位的判断即可: ~~~ if life_num and (not paused): # 如果游戏未被暂停,正常运行 ~~~   对了,差点忘了在while循环内部绘制暂停按钮图标,不过这里绘制操作应该放在“if life_num and (not paused):”判断语句的控制范围之外,以便使得无论程序是否暂停,用户都有图标可以点击: ~~~ screen.blit(paused_image, paused_rect) ~~~   OK,程序到这里应该能够顺利运行了,在下一篇博客中我们将为游戏添加最后一个功能:GameOver界面的设置。