直到上一篇博文为止,我们实现了《外星人入侵》这款有中飞船、外星人、子弹的绘制和移动,以及它们之间的碰撞检测。
在这篇博文中,将要实现为游戏增加“开始按钮”。
由于 pygame 不提供原生的按钮类供我们使用,因此我们需要自己来定义一个按钮类,以便创建“开始按钮”。
我们新建一个模块 button.py ,在其中定义 Button 类
我们自己定义的按钮由这么两部分构成:
1、作为按钮整体的一个矩形
2、按钮上的文本
而再细分成类的属性的话,可以这么分:
1、按钮整体的尺寸
2、按钮整体的颜色
3、文本的字体
4、文本的颜色
5、按钮的位置
6、文本的内容
# 按钮的基类,我们可以通过实例化按钮类来创建各种按钮class Button(): # 初始化按钮 def __init__(lf, ttings, screen, msg): lf.screen = screen lf.screen_rect = lf.screen.get_rect() lf.ttings = ttings # 设置按钮的尺寸 lf.width = 200 lf.height = 50 # 设置按钮的颜色 lf.button_color = (0, 255, 0) # 设置文本的颜色 lf.text_color = (255, 255, 255) # 设置文本的字体 lf.font = pygame.font.Font(None, 48) # 设置按钮的位置 lf.rect = pygame.Rect(0, 0, lf.width, lf.height) # 将按钮设置到屏幕中间 lf.rect.center = lf.screen_rect.center # 将文本渲染成 Surface对象 lf.prep_msg(msg)
这里值得注意的是:
pygame 没有直接将字符串渲染到 Surface对象上的方法,所以我们必须将字符串转换成 Surface对象,然后将这个 Surface对象(文本)渲染到另一个 Surface对象(按钮)上。
这里是通过 prep_msg() 方法来实现将字符串转换成 Surface对象的
def prep_msg(lf, msg): # 将文本字符串渲染成一个Surface对象 lf.msg_image = lf.font.render(msg, True, lf.text_color, lf.button_color) # 获取文本的坐标 lf.msg_rect = lf.msg_image.get_rect() # 将文本位置放到按钮中间 lf.msg_rect.center = lf.rect.center
其中,pygame 包中的 font 模块的 render 函数将文本转换成 Sruface对象,第二个参数是反锯齿功能,第三个参数是文本颜色,第四个参数是背景颜色。
代码写到这里,其实已经可以发现,我们的按钮实际上是绘制出来的一个矩形图案,而按钮上的字实际上是一个由字符串渲染成的 Surface对象
现在,我们如何将两者“组合”成我们希望的完整按钮呢?
其实很简单,就是我们现在游戏屏幕的指定位置上绘制按钮矩形,然后再在矩形上绘制文本即可。
我们将这个方法定义在 Button 类中
def draw_button(lf): lf.screen.fill(lf.button_color, lf.rect) lf.screen.blit(lf.msg_image, lf.msg_rect)
至此,我们就有了一个按钮基类,可以通过它来创建各种不同的按钮,但在《外星人入侵》中,我们只需要一个“开始按钮”。
我们想要在运行游戏之初先显示“开始按钮”,然后游戏才开始正常进行。
因此,我们需要将游戏状态的初始值修改为 Fal,代表着运行之初游戏是处于非活跃状态的
class GameStats(): # 初始化游戏状态,设置玩家开局将有多少架飞船可以使用 def __init__(lf, ttings): lf.ttings = ttings lf.ret_stats() def ret_stats(lf): lf.ship_left = lf.ttings.ship_limit # 英语时间表达游戏刚开始时,处于非活跃状态 lf.game_active = Fal
我们在主模块中导入 Button 类,并且在游戏主逻辑前创建一个 Button实例,作为我们的开始按钮
# 从 按钮模块 中导入 Button 类from button import Button...def run_game():...# 创建一个 启动游戏 的按钮 play_button = Button(my_ttings, my_screen, 'Play') ...
此时,我们在绘制游戏元素之外,还需要绘制刚才创建的开始按钮,因此,需要修改 update_screen() 方法
def update_screen(screen, tting, ship, bullets, aliens, game_stats, button): # 为纯黑的游戏屏幕填充上不一样的颜色 screen.fill(tting.background_color) # 在背景之上绘制我们的飞船,注意这里的逻辑,必须是飞船在背景之后绘制,确保飞船在背景的上层 ship.blit高中必读名著me() # 在屏幕和飞船之上,绘制子弹 for bullet in bullets.sprites(): bullet.draw_bullet() # 在屏幕上关于爱情的成语绘制外星人 aliens.draw(screen) # 如果游戏处于非活跃状态,那么就绘制按钮 if not game_stats.game_active: button.draw_button() # 刷新屏幕,使得元素能够不断刷新位置 pygame.display.flip()
效果如下:
现在,我们有了一个显示在屏幕中间的开始按钮。但它只是一个简单的矩形图案,没有任何实质性的作用。
pygame 的事件包括点击鼠标的行为,所以我们可以在事件检测方法中新增玩家标记鼠标的检测
# 当玩家 点击鼠标 发出事件时 elif event.type == pygame.MOUSEBUTTONDOWN: # 获取玩家鼠标点击的位置 mou_x, mou_y 文言词= pygame.mou.get_pos() check_play_button(mou_x, mou_y, play_button, game_stats, aliens, bullets, ttings, screen, ship)
当检测到玩家点击了鼠标后,我们需要获取玩家点击的位置信息,并且判断这个位置是否在开始按钮内。
通过 pygame 包的 mou 模块的 get_pos() 方法来获取玩家鼠标的位置。
当玩家点击的是开始按钮时,我们需要考虑游戏需要做什么
1、如果游戏处于非活跃状态,那么就转换成活跃
2、重置游戏设置,主要是让玩家可以重启游戏
3、清空外星人和子弹、生成一群新的外星人、将飞船置于屏幕底部中间。
这些业务统一封装到一个函数中,在检测到玩家点击开始按钮后调用
# 玩家点击Play按钮后开始新游戏def check_play_button(mou_x, mou_y, play_button, game_stats, aliens, bullets, ttings, screen, ship): button_clicked = play_button.rect.collidepoint(mou_x, mou_y) # 当玩家在游戏处于非活跃状态下点击Play按钮时 if button_clicked and not game_stats.game_active: #优质服务工作总结 游戏活跃时隐藏光标 pygame.mou.t_visible(Fal) # 重置游戏设置 game_stats.ret_stats() # 将游戏切换回活跃状态 game_stats.game_active = True # 清空子弹和外星人 aliens.empty() bullets.empty() # 创建一群新的外星人,并让飞船居中 create_fleet(ttings, screen, aliens, ship) ship.center_ship()
其中,我们还设置了当游戏活跃性为 True 时,玩家的光标不可见的效果。
只有当活跃性为 Fal 时,玩家才可以看到自己的光标。
由于我们将游戏设置的活跃性初始值改成了 Fal
所以当游戏开始时,有些事情就不需要做了,这些事包括:
1、飞船的绘制
2、子弹的绘制
3、外星人群的生成
即使游戏没开始也要一直做的事有:
1、事件检测
2、绘制游戏屏幕和开始按钮
因此,我们需要修改一下游戏主循环
# 游戏主循环,使得循环中的代码可以不断循环执行 while True: # 事件检测,现在我们已经将事件循环的代码封装到函数中了,直接运行即可 check_events(my_ship, my_screen, my_ttings, bullets, play_button, game_stats, aliens) # 绘制游戏画面,包括屏幕背景、飞船,并将内容显示到游戏屏幕上 update_screen(my_screen, my_ttings, my_ship, bullets, aliens, game_stats, play_button) # 当游戏处于活跃状态时,才渲染屏幕元素 if game_stats.game_active: # 每次执行完事件检测循环后,都更新飞船的位置 my_ship.update() # 每次执行完事件检测循环后,都更新子弹的位置、并删除出界的子弹,检测子弹和外星人之间的碰撞 update_bullet(bullets, my_ttings, aliens, my_screen, my_ship) # 每次执行完事件检测后,都更新外星人的位置,检测外星人和飞船之间的碰撞 update_aliens(aliens, my_ttings, my_ship, game_stats, bullets, my_screen)
此时,我们运行游戏,可以先看到一个开始按钮,当玩家点击按钮后,才会开始游戏。
当玩家的3架飞船都用完时,会重新跳出开始按钮,玩家再次点击可以重开游戏。
至此,我们实现了开始按钮的绘制,并通过玩家点击开始按钮来实现游戏流程的控制。
这里学到了 pygame 字体的使用方法,并且掌握了如何通过现有的模块来组织成需要的东西(类似造轮子?)
通过对前面知识的巩固,再加新功能时,就不会感到迷茫,可以马上猜到需要修改的位置,基本上八九不离十。
本文地址:https://blog.csdn.net/qq_32740521/article/details/107871553
本文发布于:2023-04-04 02:22:10,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/52dc6035406624c552711880cd20739c.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:Pygame 外星人入侵(9)开始按钮.doc
本文 PDF 下载地址:Pygame 外星人入侵(9)开始按钮.pdf
留言与评论(共有 0 条评论) |