zlp/game_functions

240 lines
12 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import sys
from time import sleep
import pygame
from bullet import Bullet
from alien import Alien
def check_keydown_events(event, ai_settings, screen, ship, bullets):
"""响应按键"""
if event.key == pygame.K_RIGHT: #监测按下右方向键事件
ship.moving_right = True
elif event.key == pygame.K_LEFT: #监测按下左方向键事件
ship.moving_left = True
elif event.key == pygame.K_SPACE: #监测按下空格键事件
fire_bullet(ai_settings, screen, ship, bullets) #调用fire_bullet()函数发射子弹
elif event.key == pygame.K_q: #监测按下Q键事件
sys.exit()
def check_keyup_events(event, ship):
"""响应松开"""
if event.key == pygame.K_RIGHT: #监测松开右方向键事件
ship.moving_right = False
elif event.key == pygame.K_LEFT: #监测松开左方向键事件
ship.moving_left = False
def check_events(ai_settings, screen, stats, sb, play_button, ship, aliens, bullets):
"""响应按键和鼠标事件"""
for event in pygame.event.get():
if event.type == pygame.QUIT: #监测单击窗口关闭按钮事件
sys.exit()
elif event.type == pygame.KEYDOWN: #监测键盘按下事件
check_keydown_events(event, ai_settings, screen, ship, bullets) #调用check_keydown_events()函数处理键盘按下事件
elif event.type == pygame.KEYUP: #监测键盘松开事件
check_keyup_events(event, ship) #调用check_keyup_events()处理键盘松开事件
elif event.type == pygame.MOUSEBUTTONDOWN: #监测鼠标按下事件
mouse_x, mouse_y = pygame.mouse.get_pos() #调用get_pos()方法获取鼠标光标的位置,返回元组(x, y)
check_play_button(ai_settings, screen, stats, sb, play_button, ship, aliens, bullets, mouse_x, mouse_y) #调用check_play_button()函数处理按下play按钮事件
def check_play_button(ai_settings, screen, stats, sb, play_button, ship, aliens, bullets, mouse_x, mouse_y):
"""在玩家单击Play按钮时开始新游戏"""
button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y) #调用collidepoint()方法检查鼠标单击位置是否在Play按钮的rect内
if button_clicked and not stats.game_active:
# 重置游戏设置
ai_settings.initialize_dynamic_settings() #调用Settings类的initialize_dynamic_settings()方法初始化游戏设置
# 隐藏光标
pygame.mouse.set_visible(False) #调用set_visible()方法隐藏鼠标光标
# 重置游戏统计信息
stats.reset_stats() #调用GameStats类的reset_stats()方法初始化统计信息
stats.game_active = True
# 重置记分牌图像
sb.prep_score() #调用Scoreboard类的prep_score()方法显示游戏得分
sb.prep_high_score() #调用Scoreboard类的prep_high_score()方法显示游戏最高得分得分
sb.prep_level() #调用Scoreboard类的prep_level()方法显示游戏等级
sb.prep_ships() #调用Scoreboard类的prep_ships()方法显示飞船剩余“命数”
# 清空外星人列表和子弹列表
aliens.empty()
bullets.empty()
# 创建一群新的外星人,并让飞船居中
create_fleet(ai_settings, screen, ship, aliens) #调用create_fleet()函数创建新的外星人群
ship.center_ship() #调用Ship类的center_ship()方法让飞船居中
def update_screen(ai_settings, screen, stats, sb, ship, aliens, bullets, play_button):
"""更新屏幕上的图像,并切换到新屏幕"""
# 每次循环时都重绘屏幕
screen.fill(ai_settings.bg_color) #屏幕对象填充颜色
# 在飞船和外星人后面重绘所有子弹
for bullet in bullets.sprites():
bullet.draw_bullet() #绘制每颗子弹到屏幕上
ship.blitme() #调用Ship类的blitme()方法绘制飞船
aliens.draw(screen) #aliens是编组对编组调用draw()时Pygame自动绘制编组的每个元素绘制位置由元素的属性rect决定
# 显示得分
sb.show_score() #调用Scoreboard类的show_score()方法显示得分
# 如果游戏处于非活动状态就绘制Play按钮
if not stats.game_active:
play_button.draw_button() #调用Button类的draw_button()方法绘制Play按钮
# 让最近绘制的屏幕可见
pygame.display.flip()
def update_bullets(ai_settings, screen, stats, sb, ship, aliens, bullets):
"""更新子弹的位置,并删除已消失的子弹"""
# 更新子弹的位置
bullets.update() #为编组bullets中的每个精灵调用bullet.update()
# 删除已消失的子弹
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
check_bullet_alien_collisitions(ai_settings, screen, stats, sb, ship, aliens, bullets) #调用check_bullet_alien_collisitions()函数删除碰撞的子弹和外星人
def check_bullet_alien_collisitions(ai_settings, screen, stats, sb, ship, aliens, bullets):
"""响应子弹和外星人的碰撞"""
# 删除发生碰撞的子弹和外星人
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True) #检测两个精灵编组是否碰撞后面的两个True即让发生碰撞的子弹和外星人都消失
if collisions:
for aliens in collisions.values():
stats.score += ai_settings.alien_points * len(aliens) #杀死外星人增加分数
sb.prep_score() #调用Scoreboard类的prep_score()方法显示得分
check_high_score(stats, sb) #调用check_high_score()函数检查最高得分并显示
if len(aliens) == 0:
# 删除现有的子弹并新建一群外星人
bullets.empty()
ai_settings.increase_speed() #调用Settings类的increase_speed()方法提高速度设置
# 提高等级
stats.level += 1
sb.prep_level() #调用Scoreboard类的prep_level()方法显示等级
create_fleet(ai_settings, screen, ship, aliens) #调用create_fleet()函数新建一个外星人群
def fire_bullet(ai_settings, screen, ship, bullets): #检测当前子弹编组中精灵数量,小于限制则发射子弹
"""如果还没有到达限制,就发射一颗子弹"""
# 创建新子弹并将其加入到编组bullets中
if len(bullets) < ai_settings.bullets_allowed:
new_bullet = Bullet(ai_settings, screen, ship) #实例化Bullet类
bullets.add(new_bullet)
def get_numbwe_aliens_x(ai_settings, alien_width): #外星人之间的留白宽度就是外星人矩形的宽度
"""计算每行可容纳多少个外星人"""
available_space_x = ai_settings.screen_width - 2 * alien_width
number_alien_x = int(available_space_x / (2 * alien_width))
return number_alien_x
def get_number_rows(ai_settings, ship_height, alien_height): ##外星人之间的留白高度就是外星人矩形的高度
"""计算屏幕可容纳多少行外星人"""
available_space_y = (ai_settings.screen_height - (3 * alien_height) - ship_height)
number_rows = int(available_space_y / (2 * alien_height))
return number_rows
def create_alien(ai_settings, screen, aliens, alien_number, row_number):
"""创建一个外星人并将其放在当前行"""
alien = Alien(ai_settings, screen) #实例化Alien类
alien_width = alien.rect.width
alien.x = alien_width + 2 * alien_width * alien_number
alien.rect.x = alien.x
alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
aliens.add(alien)
def create_fleet(ai_settings, screen, ship, aliens):
"""创建外星人群"""
# 创建一个外星人,并计算一行可容纳多少个外星人
alien = Alien(ai_settings, screen) #实例化Alien类
number_aliens_x = get_numbwe_aliens_x(ai_settings, alien.rect.width)
number_rows = get_number_rows(ai_settings, ship.rect.height, alien.rect.height)
# 创建第一行外星人
for row_number in range(number_rows):
for alien_number in range(number_aliens_x):
create_alien(ai_settings, screen, aliens, alien_number, row_number)
def check_fleet_edges(ai_settings, aliens):
"""有外星人到达边缘时采取相应的措施"""
for alien in aliens.sprites():
if alien.check_edges(): #调用Alien类的check_edges()方法检测外星人是否位于屏幕边缘
change_fleet_direction(ai_settings, aliens) #调用change_fleet_direction()函数下移外星人群
break
def change_fleet_direction(ai_settings, aliens):
"""将整群外星人下移,并改变它们的方向"""
for alien in aliens.sprites():
alien.rect.y += ai_settings.fleet_drop_speed
ai_settings.fleet_direction *= -1
def ship_hit(ai_settings, screen, stats, sb, ship, aliens, bullets):
"""响应被外星人撞到的飞船"""
if stats.ships_left > 0:
# 将ship_left减1
stats.ships_left -= 1
# 更新记分牌
sb.prep_ships()
# 清空外星人列表和子弹列表
aliens.empty()
bullets.empty()
# 创建一群新的外星人,并将飞船放到屏幕底部中央
create_fleet(ai_settings, screen, ship, aliens) #调用create_fleet()函数创建外星人群
ship.center_ship() #调用Ship类的center_ship()方法让飞船在屏幕底部居中
# 暂停
sleep(0.5)
else:
stats.game_active = False #当飞船没有“命数”的时候,停止运行游戏
pygame.mouse.set_visible(True)
def check_aliens_bottom(ai_settings, screen, stats, sb, ship, aliens, bullets):
"""检查是否有外星人到达了屏幕底部"""
screen_rect = screen.get_rect()
for alien in aliens.sprites():
if alien.rect.bottom >= screen_rect.bottom:
# 像飞船被撞到一样继续处理
ship_hit(ai_settings, screen, stats, sb, ship, aliens, bullets)
break
def update_aliens(ai_settings, screen, stats, sb, ship, aliens, bullets):
"""检查是否有外星人位于屏幕边缘,并更新外星人群中所有外星人的位置"""
check_fleet_edges(ai_settings, aliens) #调用check_fleet_edges()函数检查外星人是否位于屏幕边缘并向下移动
aliens.update() ##为编组aliens中的每个精灵调用alien.update(),做左右移动
# 检测外星人和飞船直接的碰撞
if pygame.sprite.spritecollideany(ship, aliens):
ship_hit(ai_settings, screen, stats, sb, ship, aliens, bullets)
# 检查是否有外星人到达屏幕底部
check_aliens_bottom(ai_settings, screen, stats, sb, ship, aliens, bullets)
def check_high_score(stats, sb):
"""检查是否诞生了新的最高得分"""
if stats.score > stats.high_score:
stats.high_score = stats.score
sb.prep_high_score() #调用Scoreboard类的prep_high_score()方法显示最高得分