上传文件至 ''

This commit is contained in:
206530118 2021-06-24 12:49:51 +08:00
parent e41f2133e5
commit bc9299643c
1 changed files with 409 additions and 0 deletions

409
game_functions.py Normal file
View File

@ -0,0 +1,409 @@
import sys
import pygame
import random
import operator
import json
from bullet import Bullet
from super_bullet import SuperBullet
from alien import Alien
from alien_bullet import AlienBullet
from time import sleep
from threading import Timer
"""
用户操作响应
"""
def check_events(ai_settings, screen, ship, bullets, aliens, stats, play_button, scoreboard, alien_bullets, super_bullets, playername_inputbox):
"""响应按键和鼠标事件"""
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, stats, scoreboard, super_bullets, playername_inputbox)
elif event.type == pygame.KEYUP:
check_keyup_events(event, ship)
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = pygame.mouse.get_pos()
check_playername_input(playername_inputbox, stats, mouse_x, mouse_y)
check_play_button(ai_settings, screen, ship, bullets, aliens, stats, play_button, mouse_x, mouse_y, scoreboard, alien_bullets, super_bullets, playername_inputbox)
def check_keydown_events(event, ai_settings, screen, ship, bullets, stats, scoreboard, super_bullets, playername_inputbox):
"""响应按键按下"""
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:
if stats.game_active:
fire_bullet(ai_settings, screen, ship, bullets)
elif event.key == pygame.K_UP:
if stats.game_active:
activate_super_mode(ai_settings, ship, stats, scoreboard)
elif event.key == pygame.K_LALT:
if stats.game_active:
fire_super_bullet(ai_settings, screen, ship, stats, super_bullets)
elif event.key == pygame.K_q:
sys.exit()
else:
if playername_inputbox.login == False:
playername_inputbox.key_down(event)
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_playername_input(playername_inputbox, stats, mouse_x, mouse_y):
"""检查用户点击玩家名称输入框,若点击,则清空文本"""
if playername_inputbox.rect.collidepoint(mouse_x, mouse_y) and not stats.game_active:
playername_inputbox.text = ''
def check_play_button(ai_settings, screen, ship, bullets, aliens, stats, play_button, mouse_x, mouse_y, scoreboard, alien_bullets, super_bullets, playername_inputbox):
"""检查开始游戏按钮是否被按下,并响应"""
if play_button.rect.collidepoint(mouse_x, mouse_y) and not stats.game_active:
# 隐藏光标
pygame.mouse.set_visible(False)
# 重置游戏参数
ai_settings.initialize_dynamic_settings()
stats.reset_stats()
# 重置记分牌
scoreboard.prep_images()
# 设置状态为激活
stats.game_active = True
# 清屏并创建新的一群外星人
clear_and_create_fleet(ai_settings, screen, ship, bullets, aliens, alien_bullets, super_bullets)
if playername_inputbox.login == False:
stats.player = playername_inputbox.text
playername_inputbox.login = True
def fire_super_bullet(ai_settings, screen, ship, stats, super_bullets):
if stats.power >= ai_settings.points_of_power:
ai_settings.super_bullet_sound.play()
new_super_bullet = SuperBullet(ai_settings, screen, ship)
super_bullets.add(new_super_bullet)
stats.power -= ai_settings.points_of_power
def fire_bullet(ai_settings, screen, ship, bullets):
if len(bullets) < ai_settings.bullets_allowed:
ai_settings.bullet_sound.play()
new_bullet = Bullet(ai_settings, screen, ship)
bullets.add(new_bullet)
def activate_super_mode(ai_settings, ship, stats, scoreboard):
"""响应进入无敌模式"""
if stats.power >= ai_settings.points_of_power:
if ship.super_mode == False:
ai_settings.super_mode_sound.play()
ship.super_mode = True
stats.power -= ai_settings.points_of_power
scoreboard.prep_power()
Timer(5, quit_super_mode, args=[ship]).start()
def quit_super_mode(ship):
ship.super_mode = False
"""
子弹参数更新包括超级子弹
"""
def update_bullets(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, super_bullets):
"""更新子弹位置并检查碰撞"""
# 更新子弹位置
bullets.update()
super_bullets.update()
# 删除已超出范围的子弹
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
for super_bullet in super_bullets.copy():
if super_bullet.rect.bottom <= 0:
super_bullets.remove(super_bullet)
check_bullet_alien_collision(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, super_bullets)
def check_bullet_alien_collision(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, super_bullets):
"""响应子弹击中外星人"""
# 检查是否有子弹击中外星人,若有,删除对应的子弹与外星人
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
super_collisions = pygame.sprite.groupcollide(super_bullets, aliens, False, True)
if collisions:
for aliens in collisions.values():
stats.score += ai_settings.alien_points * len(aliens)
stats.power += ai_settings.alien_points * len(aliens)
scoreboard.prep_score()
scoreboard.prep_power()
# 检查是否打破历史记录
check_high_score(stats, scoreboard)
if super_collisions:
for aliens in super_collisions.values():
stats.score += ai_settings.alien_points * len(aliens)
stats.power += ai_settings.alien_points * len(aliens)
scoreboard.prep_score()
scoreboard.prep_power()
# 检查是否打破历史记录
check_high_score(stats, scoreboard)
if len(aliens) == 0:
# 外星人被消灭干净,开启新等级
start_new_level(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, super_bullets)
def start_new_level(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, super_bullets):
"""响应外星人被消灭干净"""
ai_settings.start_new_level_sound.play()
bullets.empty()
super_bullets.empty()
ai_settings.increase_speed()
create_fleet(ai_settings, screen, ship, aliens)
stats.level += 1
scoreboard.prep_level()
def check_high_score(stats, scoreboard):
"""响应打破历史记录"""
if stats.score > stats.high_score:
stats.high_score = stats.score
scoreboard.prep_high_score()
"""
外星人参数更新
"""
def update_aliens(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, alien_bullets, super_bullets):
"""更新所有外星人的位置"""
check_fleet_edges(ai_settings, aliens)
aliens.update()
# 检测外星人和飞船的碰撞
if pygame.sprite.spritecollideany(ship, aliens):
ship_hit(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, alien_bullets, super_bullets)
check_aliens_bottom(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, alien_bullets, super_bullets)
def check_fleet_edges(ai_settings, aliens):
"""有外星人到达屏幕边缘时采取相应措施"""
for alien in aliens.sprites():
if alien.check_edges():
change_fleet_direction(ai_settings, aliens)
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 check_aliens_bottom(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, alien_bullets, super_bullets):
"""检查是否有外星人撞到屏幕底端"""
screen_rect = screen.get_rect()
for alien in aliens.sprites():
if alien.rect.bottom >= screen_rect.bottom:
# 像飞船与外星人相撞一样处理
ship_hit(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, alien_bullets, super_bullets)
break
def ship_hit(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, alien_bullets, super_bullets):
"""响应飞船与外星人碰撞"""
if stats.ships_left > 0:
"""仍有剩余飞船,游戏继续"""
ai_settings.ship_hit_sound.play()
# 将剩余飞船数减一
stats.ships_left -= 1
# 清空外星人和子弹列表并创建一批新外星人
clear_and_create_fleet(ai_settings, screen, ship, bullets, aliens, alien_bullets, super_bullets)
# 更新剩余飞船数
scoreboard.prep_ships()
else:
"""游戏结束"""
if stats.score == stats.high_score:
ai_settings.recordbroken_sound.play()
else:
ai_settings.gameover_sound.play()
stats.game_active = False
pygame.mouse.set_visible(True)
# 记录此次玩家得分
new_score = { 'player': stats.player, 'score': stats.score }
stats.scores_data.append(new_score)
stats.scores_data.sort(key=lambda x:x["score"], reverse=True)
with open('scores.json', 'w') as f:
json.dump(stats.scores_data, f)
# 打印历史得分排行榜Top10
if len(stats.scores_data) >= 10:
leaderboard_height = 340
else:
leaderboard_height = len(stats.scores_data) * 30 + 40
leaderboard_rect = pygame.Rect(450, 180, 300, leaderboard_height)
screen.fill(ai_settings.lb_bg_color, leaderboard_rect)
# 表头
leaderboard_font = pygame.font.SysFont("Calibri, Arial", 28)
rank_image_rect = draw_leaderboard(ai_settings.lb_text_color, ai_settings.lb_bg_color, screen, 'Rank', leaderboard_font, 500, 200)
player_image_rect = draw_leaderboard(ai_settings.lb_text_color, ai_settings.lb_bg_color, screen, 'Player', leaderboard_font, 600, 200)
score_image_rect = draw_leaderboard(ai_settings.lb_text_color, ai_settings.lb_bg_color, screen, 'Score', leaderboard_font, 700, 200)
rank = 0
for player_score in stats.scores_data:
"""逐个显示玩家得分"""
rank += 1
if rank > 10:
break
rank_text = str(rank)
player_text = str(player_score["player"])
score_text = str(player_score["score"])
y_postion = rank_image_rect.centery + 30 * rank
font = leaderboard_font
text_color = ai_settings.lb_text_color
bg_color = ai_settings.lb_bg_color
if player_score == new_score:
"""当前用户的信息,样式不同"""
general_font = pygame.font.SysFont("Calibri, Arial", 32, True)
text_color = (255, 255, 0)
draw_leaderboard(text_color, bg_color, screen, rank_text, font, rank_image_rect.centerx, y_postion)
draw_leaderboard(text_color, bg_color, screen, player_text, font, player_image_rect.centerx, y_postion)
draw_leaderboard(text_color, bg_color, screen, score_text, font, score_image_rect.centerx, y_postion)
pygame.display.flip()
sleep(5)
sleep(0.5)
def draw_leaderboard(text_color ,bg_color, screen, text, font, x, y):
"""绘制排行榜的某一项"""
image = font.render(text, True, text_color, bg_color)
image_rect = image.get_rect()
image_rect.centerx = x
image_rect.centery = y
screen.blit(image, image_rect)
return image_rect
def clear_and_create_fleet(ai_settings, screen, ship, bullets, aliens, alien_bullets, super_bullets):
"""清空外星人和子弹列表并创建一批新外星人"""
# 清空外星人和子弹列表
bullets.empty()
super_bullets.empty()
aliens.empty()
alien_bullets.empty()
# 创建一批新的外星人,并将飞船放到屏幕底部中央
create_fleet(ai_settings, screen, ship, aliens)
ship.center_ship()
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)
def get_number_aliens_x(ai_settings, alien_width):
"""计算一行可容纳多少外星人"""
available_space_x = ai_settings.screen_width - 2 * alien_width
number_aliens_x = int(available_space_x / (2 * alien_width))
return number_aliens_x
def get_number_rows(ai_settings, alien_height, ship_height):
"""计算可容纳多少行外星人"""
available_space_y = ai_settings.screen_height - 6 * 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_width = alien.rect.width
alien_height = alien.rect.height
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 update_aliens_fire_bullet(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, alien_bullets, super_bullets):
"""更新外星人发射的子弹"""
for alien in aliens.sprites():
flag_is_last_line = True
for alien_next in aliens.sprites():
if (alien.rect.y + alien.rect.height * 2 == alien_next.rect.y
and alien.rect.x == alien_next.rect.x):
flag_is_last_line = False
break
if flag_is_last_line:
"""外星人有一定的概率发射子弹"""
if random.randint(0,3000) < 1:
new_alien_bullet = AlienBullet(ai_settings, screen, alien)
alien_bullets.add(new_alien_bullet)
check_alien_bullet_ship_collision(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, alien_bullets, super_bullets)
alien_bullets.update()
def check_alien_bullet_ship_collision(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, alien_bullets, super_bullets):
"""响应外星人子弹击中飞船"""
for alien_bullet in alien_bullets.sprites():
if alien_bullet.rect.colliderect(ship.rect) and not ship.super_mode:
ship_hit(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, alien_bullets, super_bullets)
break
"""
屏幕更新
"""
def update_screen(ai_settings, screen, ship, bullets, aliens, stats, play_button, scoreboard, alien_bullets, super_bullets, playername_inputbox):
"""更新屏幕上的图像,并切换到新屏幕"""
# 重绘屏幕
screen.fill(ai_settings.bg_color)
if playername_inputbox.login == False:
playername_inputbox.draw_inputbox()
# 绘制全部子弹
for bullet in bullets.sprites():
bullet.draw_bullet()
for alien_bullet in alien_bullets.sprites():
alien_bullet.draw_alien_bullet()
for super_bullet in super_bullets.sprites():
super_bullet.draw_bullet()
# 绘制玩家飞船
ship.blitme()
# 绘制全部外星人
aliens.draw(screen)
scoreboard.ships.draw(screen)
# 显示得分
scoreboard.show_score()
# 如果游戏处于非活动状态就显示Play按钮
if stats.game_active == False:
play_button.draw_button()
# 让最近绘制的屏幕可见
pygame.display.flip()