14.1 添加play按钮
1、创建Button类
导入pygame.font,让pygame能够将文本渲染到屏幕上。
初始方法__init__()最后需要接受一个对象为文本内容(msg)。
pygame.font.SysFont(para1,para2) ---- 指定什么字体来渲染文本。para1位字体,para2为字号
初始方法中将button设置为矩形,并调整到屏幕当中。
再新建文本方法,通过self.font.render(para1,para2,para3,para4)将文本转换为图片 ---- para1=文本内容(msg),para2=布尔值,开启反锯齿功能,
para3 = 文本颜色 ,para4 = 背景色,即button颜色。最后将文本设置为矩形,调整到不是屏幕中央而是button中央。
注意:不是都实例化一次吗,为什么要另外做一个文本的方法??
2、在屏幕上绘制按钮
在主程序导入Button类,并直接创建play实例化button按钮。在screen_update中引入条件判断,如果游戏不运行,即game_active = False,则调用draw_button
3、开始游戏
在为玩家单击play按钮时开始游戏。需要在game_function中监视该按钮。check event
在监视中,如果鼠标的x,y位置与play_button的矩形向撞,则将game_active变为true。
pygame.mouse.get_pos() ---- 返回一个元组,包含玩家点击鼠标的x,y坐标。
play_button.rect.collidepoint(x,y)。 ---- collidepoint()函数检测位置(即鼠标位置)是否在play按钮的rect范围内,如果在范围内返回值。
4、重置游戏
补全check_play_button的代码内容,表示每次按play键重置游戏时,恢复ship次数,消除子弹,消除aliens并重建,ship位置重置。
5、将play按钮切换到非活动状态
当前,play按钮有一个问题,就是即便play按钮不可见,玩家单击原来所在的区域时,游戏依然会做出响应,所以在check_play_button中将游戏鼠标按键和游戏非活动设为“与”条件。
6、隐藏光标
通过pygame.mouse.set_visible(False),将光标位于窗口内时隐藏起来。游戏结束后重新显示光标。
在ship_hit()中,在ship_left=0时将光标调整为可见,同时通过game_active=False,启动play按钮的代码。
14.2 提高等级
1、修改速度设置
在Settings类中分静态和动态两组设置。 ---- 即对于飞船、外星人、子弹的速度为可调整的动态配置。
调整完初始配置数据后,设置一个属性为速度增加的等级,作为后续提高等级的系数。
新建increase_speed()方法,相应速度因子乘等于等级系数。
在game_function中check_bullet_alien_collision中,将外星人被消灭后,提高相应速度等级,再新建新的舰队。
2、重置速度
在check_play_button出将settings的速度调整为初始,即点击play按钮后重置。
14.3 记分
下面实现一个记分系统,实时跟踪玩家的得分,显示最高的得分,当前的等级和余下的飞船数。
因为每次开始游戏时都要重置得分,我们在reset_stats中初始化score。 ---- 明白为什么建立reset_stats方法,而不是直接在类中直接初始化。为了实例化一次后多次调用并重置相关内容。
1、显示得分
创建Scoreboard类。初始化screen,settings,stats参数,初始化定于字体和文字颜色,并且调用self.prep_score()方法,后续有另外定义该方法。
在prep_score方法中。先将从stats中调用的score数值转换为字符串(font方法只能对渲染字符串)
将字符串score转换成图片。将图片变成rect,调整rect的位置。
新建show_score,画分数。
2、创建记分牌
在主程序中导入Scoreboard类,实例化,在screen_update中加入show_score方法。
3、在外星人被消灭时更新得分
为在屏幕上更新得分,每次有外星人被消灭,1,更新stats.score的值,2,更新prep_score图片。
在check_bullets_aliens_collisions中,以条件判断collisions的碰撞发生(注意,groupcollide()的运行模式是当发生碰撞后就返回一个以第一实参为键,第二实参为值的键值对,如果一次循环的时候没有碰撞就返回一个空字典,不是累计的,单次计算。),所以当发生碰撞时,就将stats.score记分增加,prep_score更新调用。
4、将消灭的每个外星人的点数都计入得分
如果一次循环中有两颗子弹射中外星人,或者一颗子弹射中两个外星人,就会漏掉计算。
遍历collisions字典,取出所涉及到的外星人。
遍历collisions的所有值,取出每个值即为一个列表,取列表长度乘以外星人分值。 ---- 这一步非常之高级。
5、提高点数
每次增加难度后外星人的得分也需要提高,更速度提高差不多,新建一个得分系数score_scale,在increase_speed中加入递增的属性。
6、将得分圆整
将得分精确到十位,同时加入千位分隔符。
使用round函数。round(para1,para2) ---- 让小数精确到小数点后多少位,para1为要取的数字,para2为精确到的位数,-1表示十位。
用format函数对整数进行格式化:"{:,}".format(int_num) ---- 该格式显示的整数有千位分隔符。具体参考format的语句格式。
7、最高得分
在game_stats的初始中新建,而不是在reset_stats中新建,因为不用刷新。
在scoreboard中新建high_score方法,设置相应的配置,在show_score中画出。
在game_functions中添加check_high_score的函数。条件判断,如果得分大于最高得分,则得分定义为最高得分,并且刷新prep_high_score。
完成上述之后,调用是在check_bullets_aliens_collisions函数中进行更新的,每次有碰撞得分,就要判断是否需要更新最高分。
注意:当前代码中,如果重置游戏后,虽然在start_game中有重置分数,但是在按下play键时并不归零,需要有子弹有新的碰撞后才会从零开始记。什么问题。。。
8、显示等级
类似前述。
在start_game中调用一下prep_score,prep_high_score,prep_level之后前述红字的问题解决。就是说签署reset之后数值已经更新,但是必须要调用一下这三个函数才能对图片做更新,否则还是原来的值。
9、显示余下飞船数
用图像来显示还有多少飞船。
首先让Ship继承Sprite,以便能够创建飞船的编组。
在scoreboard模块中导入Group类和Ship类。创建prep_ships()方法,创建空的编组存放ship实例,创建循环遍历self.stats.ship_left,创建ship实例,并对每个ship安排位置,加入编组中。
在show_score方法中加入draw一下ships编组里的ship.
在check_play_button中在重置stats.ship_left后调用一下sb.prep_ships,
在ship_hit中每次ship_left有变化就调用一下sb.prep_ships.
做作业