206530323/game_functions.py

267 lines
9.3 KiB
Python
Raw 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
import pygame
from bullet import Bullet
from alien import Alien
from time import sleep
import json
import music
def play_bg_music():
"""背景音乐"""
if not pygame.mixer.music.get_busy():
pygame.mixer.music.play()
def check_keydown_events(event, ai_settings, screen, ship, bullets, game_stats, scoreb, aliens):
""""
响应鼠标按下操作
"""
# 按右箭头飞船向右移动
if event.key == pygame.K_RIGHT:
ship.moving_right = True
# 按左箭头飞船向左移动
elif event.key == pygame.K_LEFT:
ship.moving_left = True
# 按空格键创建一颗子弹并将其加入到编组bullets中
elif event.key == pygame.K_SPACE:
fire_bullet(ai_settings, screen, ship, bullets)
# 按p开始游戏
elif event.key == pygame.K_p:
start_game(ai_settings, screen, ship, bullets, game_stats, scoreb,
aliens)
# 按z暂停游戏3s
elif event.key == pygame.K_z:
sleep(2)
# 按q退出游戏并把最高分写入文件
elif event.key == pygame.K_q:
with open('Max_score.json', 'w', encoding='UTF-8') as file:
json.dump(game_stats.high_score, file)
sys.exit()
def fire_bullet(ai_settings, screen, ship, bullets):
"""
按照要求发射子弹数量
"""
if len(bullets) < ai_settings.bullet_allowed:
music.bullet_biu() # 发射子弹的声音
new_bullet = Bullet(ai_settings, screen, ship) # 如果还没有到达限制,就发射一颗子弹
bullets.add(new_bullet) # 创建一颗子弹并将其加入到编组bullets中
def start_game(ai_settings, screen, ship, bullets, game_stats, scoreb,
aliens):
"""
P264中动手试一试14-1的练习让玩家按p开始游戏
"""
# 重置游戏统计信息
game_stats.reset_stats()
game_stats.game_active = True
# 重置记分牌图像
scoreb.prep_score()
scoreb.prep_high_score()
scoreb.prep_level()
scoreb.prep_ships()
# 清空外星人列表和子弹列表
aliens.empty()
bullets.empty()
# 创建一群新的外星人,并让飞船居中
create_fleet(ai_settings, screen, ship, aliens)
ship.center_ship()
# 暂停让用户反应一会
sleep(0.5)
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_play_button(ai_settings, screen, game_stats, scoreb, play_button, ship,
aliens, bullets, mouse_x, mouse_y):
"""
在玩家单击Play按钮时开始游戏
"""
button_clicked = play_button.button_rect.collidepoint(mouse_x, mouse_y)
# 单击Play按钮且游戏处于非活跃状态时----避免了游戏处于活跃状态下单击到了Play按钮区域重启游戏
if button_clicked and not game_stats.game_active:
"""如果鼠标单击位置在msg_image_rect范围内则将游戏置于活跃状态"""
# # 重置游戏设置
ai_settings.initialize_dynamic_settings()
# 游戏开始后Play按钮隐藏起来
pygame.mouse.set_visible(False)
start_game(ai_settings, screen, ship, bullets, game_stats, scoreb, aliens)
def check_events(ai_settings, screen, game_stats, scoreb, play_button, ship, aliens, bullets):
"""
响应鼠标和键盘事件
"""
# 游戏退出并把最高分写入文件
for event in pygame.event.get():
if event.type == pygame.QUIT:
with open('Max_score.json', 'w', encoding='UTF-8') as file:
json.dump(game_stats.high_score, file)
sys.exit()
# 响应Play按钮操作
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = pygame.mouse.get_pos() # 该函数返回一个元组--获取鼠标单击Play按钮时的位置
check_play_button(ai_settings, screen, game_stats, scoreb, play_button, ship,
aliens, bullets, mouse_x, mouse_y)
# 判读飞船向左还是向右移动
elif event.type == pygame.KEYDOWN:
check_keydown_events(event, ai_settings, screen, ship, bullets, game_stats, scoreb, aliens)
# 飞船停下
elif event.type == pygame.KEYUP:
check_keyup_events(event, ship)
def update_screen(ai_settings, screen, game_stats, scoreb, ship, aliens, bullets, play_button):
"""
更新屏幕上的图像并切换到新屏幕
"""
# 每次循环时都重绘屏幕
screen.fill(ai_settings.bg_color) # 先填充背景后绘制飞船
ship.blitem()
aliens.draw(screen)
# 在飞船后重绘所有子弹
for bullet in bullets.sprites():
bullet.draw_bullet()
# 显示得分
scoreb.show_score()
# 如果游戏处于非活动状态就绘制Play按钮
if not game_stats.game_active:
play_button.draw_button()
# 让最近绘制的屏幕可见
pygame.display.flip()
def start_new_level(ai_settings, screen, game_stats, scoreb, ship, aliens, bullets):
"""
当消灭干净外星人提高一个等级
"""
if len(aliens) == 0:
# 删除现有子弹
bullets.empty()
# 逐渐提高速度加快游戏节奏
ai_settings.increase_speed()
# 当前屏幕外星人全部被消灭就提高一个等级
game_stats.level += 1
scoreb.prep_level()
# 创建一群新的外星人
create_fleet(ai_settings, screen, ship, aliens) # 调用创建外星人群的函数
def check_bullet_alien_collisions(ai_settings, screen, game_stats, scoreb, ship, aliens, bullets):
"""子弹与外星人相撞后的操作"""
# 检查是否有子弹击中外星人
# 如果击中了就删除相应的子弹与外星人
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
"""方法sprite.groupcollide()检查两个编组的成员之间的碰撞(碰撞是指游戏元素重叠在一起):
将每颗子弹同每个外星人的rect作比较 并返回一个字典 字典中的键为子弹 值为被击中的外星人"""
# 每消灭一个外星人都将加一个points且显示最新得分的图像
if collisions:
music.voice_small() # 子弹与外星人相撞的声音
for aliens in collisions.values(): # aliens指被同一颗子弹击中的外星人---是一个列表
game_stats.score += ai_settings.alien_points * len(aliens)
scoreb.prep_score()
check_high_score(game_stats, scoreb)
start_new_level(ai_settings, screen, game_stats, scoreb, ship, aliens, bullets)
def update_bullets(ai_settings, screen, game_stats, scoreb, ship, aliens, bullets):
"""
更新子弹位置并删除已消失的子弹
"""
# 更新子弹位置
bullets.update()
# 删除已消失的子弹
for bullet in bullets.copy():
if bullet.rect.bottom <= 0: # 当子弹底部越过屏幕顶部0时删除子弹
bullets.remove(bullet)
check_bullet_alien_collisions(ai_settings, screen, game_stats, scoreb, ship, aliens, bullets)
def get_number_aliens_X(ai_settings, alien_width):
"""
计算每行可容纳多少个外星人
"""
availabble_space_x = ai_settings.screen_width - 2 * alien_width # 一行可可容纳的水平长度
number_aliens_x = int(availabble_space_x / (2 * alien_width)) # 一行可容纳多少个外星人
return number_aliens_x
def get_number_rows(ai_settings, alien_height, ship_height):
"""
计算屏幕可容纳多少行外星人
"""
availables_space_y = (ai_settings.screen_height-ship_height-
(3*alien_height))
number_rows = int(availables_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_width = alien.rect.width
alien_height = alien.rect.height + 3 # 让外星人之间间隔大些
alien.x = alien_width + 2 * alien_width * alien_number # 获取新建外星人所移动的位置
alien.rect.x = alien.x # 新建外星人的位置
alien.rect.y = alien_height + 2 * alien_height * row_number # 新行的位置
aliens.add(alien)
def create_fleet(ai_settings, screen, ship, aliens):
"""
创建外星人群
"""
# 创建一个外星人并计算一行可容纳多少个外星人
# 外星人间距为外星人的宽度
alien = Alien(ai_settings, screen)
number_aliens_x = get_number_aliens_X(ai_settings, alien.rect.width) # 一行可容纳外星人的个数
number_rows = get_number_rows(ai_settings, alien.rect.height,
ship.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) # 调用创建外星人的函数