This commit is contained in:
206530118 2021-06-24 13:57:35 +08:00
parent 1eadba9854
commit a94fd61cc8
14 changed files with 944 additions and 0 deletions

35
alien.py Normal file
View File

@ -0,0 +1,35 @@
import pygame
from pygame.sprite import Sprite
class Alien(Sprite):
"""表示单个外星人的类"""
def __init__(self, ai_settings, screen):
"""初始化外星人并设置其初始位置"""
super().__init__()
self.screen = screen
self.ai_settings = ai_settings
# 加载外星人图像并设置其rect属性
self.image = pygame.image.load('images/alien.bmp')
self.rect = self.image.get_rect()
# 每个外星人初始都在屏幕左上角,设置为其宽高以进行留白
self.rect.x = self.rect.width
self.rect.y = self.rect.height * 2
self.x = float(self.rect.x)
def update(self):
"""向左或向右右移动外星人"""
self.x += self.ai_settings.alien_speed_factor * self.ai_settings.fleet_direction
self.rect.x = self.x
def check_edges(self):
screen_rect = self.screen.get_rect()
if self.rect.right >= screen_rect.right:
return True
elif self.rect.left <= screen_rect.left:
return True

33
alien_bullet.py Normal file
View File

@ -0,0 +1,33 @@
import pygame
from pygame.sprite import Sprite
class AlienBullet(Sprite):
"""一个对外星人发射的子弹进行管理的类"""
def __init__(self, ai_settings, screen, alien):
"""在飞船所处的位置创建一个子弹对象"""
super().__init__()
self.screen = screen
# 在(0,0)处创建一个表示子弹的矩形,再设置正确的位置
self.rect = pygame.Rect(0, 0, ai_settings.bullet_width, ai_settings.bullet_height)
self.rect.centerx = alien.rect.centerx
self.rect.top = alien.rect.bottom
# 存储用小数表示的子弹位置
self.y = float(self.rect.y)
# 设置子弹颜色及速度(从ai_settings中读取)
self.color = ai_settings.alien_bullet_color
self.speed_factor = ai_settings.bullet_speed_factor
def update(self):
"""向下移动子弹"""
self.y += self.speed_factor
self.rect.y = self.y
def draw_alien_bullet(self):
"""在屏幕上绘制子弹"""
pygame.draw.rect(self.screen, self.color, self.rect)

52
alien_invasion.py Normal file
View File

@ -0,0 +1,52 @@
import pygame
import game_functions as gf
from settings import Settings
from ship import Ship
from pygame.sprite import Group
from game_stats import GameStats
from button import Button
from scoreboard import Scoreboard
from playername_inputbox import PlayernameInputbox
def run_game():
# 初始化游戏并创建一个屏幕对象
pygame.init()
ai_settings = Settings()
screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))
pygame.display.set_caption("Alien Invasion")
# 创建一艘飞船, 一个子弹编组和一个外星人编组
ship = Ship(ai_settings, screen)
bullets = Group()
aliens = Group()
alien_bullets = Group()
super_bullets = Group()
# 创建外星人群
gf.create_fleet(ai_settings, screen, ship, aliens)
# 创建一个用于游戏统计信息的示例,并创建记分牌
stats = GameStats(ai_settings)
scoreboard = Scoreboard(ai_settings, screen, stats)
# 创建开始游戏按钮
play_button = Button(ai_settings, screen, "Play")
# 创建玩家名字文本输入框
playername_inputbox = PlayernameInputbox(screen)
# 开始游戏的主循环
while True:
gf.check_events(ai_settings, screen, ship, bullets, aliens, stats, play_button, scoreboard, alien_bullets, super_bullets, playername_inputbox)
if stats.game_active:
ship.update()
gf.update_bullets(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, super_bullets)
gf.update_aliens(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, alien_bullets, super_bullets)
gf.update_aliens_fire_bullet(ai_settings, screen, ship, bullets, aliens, stats, scoreboard, alien_bullets, super_bullets)
gf.update_screen(ai_settings, screen, ship, bullets, aliens, stats, play_button, scoreboard, alien_bullets, super_bullets, playername_inputbox)
run_game()

33
bullet.py Normal file
View File

@ -0,0 +1,33 @@
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
"""一个对飞船发射的子弹进行管理的类"""
def __init__(self, ai_settings, screen, ship):
"""在飞船所处的位置创建一个子弹对象"""
super().__init__()
self.screen = screen
# 在(0,0)处创建一个表示子弹的矩形,再设置正确的位置
self.rect = pygame.Rect(0, 0, ai_settings.bullet_width, ai_settings.bullet_height)
self.rect.centerx = ship.rect.centerx
self.rect.bottom = ship.rect.top
# 存储用小数表示的子弹位置
self.y = float(self.rect.y)
# 设置子弹颜色及速度(从ai_settings中读取)
self.color = ai_settings.bullet_color
self.speed_factor = ai_settings.bullet_speed_factor
def update(self):
"""向上移动子弹"""
self.y -= self.speed_factor
self.rect.y = self.y
def draw_bullet(self):
"""在屏幕上绘制子弹"""
pygame.draw.rect(self.screen, self.color, self.rect)

37
button.py Normal file
View File

@ -0,0 +1,37 @@
import pygame.font
class Button():
"""一个用于创建矩形按钮的类"""
def __init__(self, ai_settings, screen, msg):
"""初始化按钮的属性"""
self.screen = screen
self.screen_rect = screen.get_rect()
# 设置按钮的尺寸和其他属性
self.width = 200
self.height = 50
self.button_color = (0, 255, 0)
self.text_color = (255, 255, 255)
self.font = pygame.font.SysFont('Calibri, Arial', 48)
# 创建按钮的rect对象并使其在屏幕上居中
self.rect = pygame.Rect(0, 0, self.width, self.height)
self.rect.center = self.screen_rect.center
self.rect.y += 120
# 按钮标签
self.prep_msg(msg)
def prep_msg(self, msg):
"""将msg渲染成图像并使其在按钮上居中"""
self.msg_image = self.font.render(msg, True, self.text_color, self.button_color)
self.msg_image_rect = self.msg_image.get_rect()
self.msg_image_rect.center = self.rect.center
def draw_button(self):
"""绘制一个用颜色填充的按钮,并绘制文本"""
self.screen.fill(self.button_color, self.rect)
self.screen.blit(self.msg_image, self.msg_image_rect)

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()

25
game_stats.py Normal file
View File

@ -0,0 +1,25 @@
import json
class GameStats():
"""跟踪游戏的统计信息"""
def __init__(self, ai_settings):
"""初始化统计信息"""
self.ai_settings = ai_settings
self.game_active = False
self.reset_stats()
def reset_stats(self):
"""初始化在游戏运行期间可能变化的信息"""
self.ships_left = self.ai_settings.ship_limit
self.score = 0
self.level = 1
self.power = 0
# 提取历史得分信息
scorefilename = 'scores.json'
with open(scorefilename) as f:
self.scores_data = json.load(f)
self.high_score = int(self.scores_data[0]['score'])

56
playername_inputbox.py Normal file
View File

@ -0,0 +1,56 @@
import pygame
class PlayernameInputbox:
def __init__(self, screen):
"""初始化文本框的属性"""
self.screen = screen
self.screen_rect = screen.get_rect()
# 设置按钮的尺寸和其他属性
self.width = 200
self.height = 50
self.box_color = (255, 255, 255)
self.text_color = (20, 20, 20)
self.font = pygame.font.SysFont("Calibri, Arial", 38)
# 创建按钮的rect对象并使其在屏幕上居中
self.rect = pygame.Rect(0, 0, self.width, self.height)
self.rect.center = self.screen_rect.center
self.rect.y += 40
self.text = "Your Name"
self.login = False
def draw_inputbox(self):
"""将输入文本渲染为图像,并显示"""
self.text_image = self.font.render(self.text, True, self.text_color, self.box_color)
self.text_image_rect = self.text_image.get_rect()
self.text_image_rect.center = self.rect.center
self.screen.fill(self.box_color, self.rect)
self.screen.blit(self.text_image, self.text_image_rect)
def key_down(self, event):
"""输入新文本"""
unicode = event.unicode
key = event.key
if key == 8:
# 退位键
self.text = self.text[:-1]
return
if key == 301:
# 切换大小写键
return
if key == 13:
# 回车键
return
if unicode != "":
char = unicode
else:
char = chr(key)
self.text += char

96
scoreboard.py Normal file
View File

@ -0,0 +1,96 @@
import pygame.font
from pygame.sprite import Group
from ship import Ship
class Scoreboard():
"""显示得分信息的类"""
def __init__(self, ai_settings, screen, stats):
"""初始化相关参数"""
self.ai_settings = ai_settings
self.screen = screen
self.screen_rect = screen.get_rect()
self.stats = stats
# 字体设置
self.text_color = (230, 230, 230)
self.font = pygame.font.SysFont("Calibri, Arial", 28)
# 准备得分图像、等级及剩余飞船图像
self.prep_images()
def show_score(self):
"""在屏幕上显示得分、历史记录、等级、大招数"""
self.screen.blit(self.score_image, self.score_rect)
self.screen.blit(self.high_score_image, self.high_score_rect)
self.screen.blit(self.level_image, self.level_rect)
self.screen.blit(self.power_image, self.power_rect)
def prep_images(self):
"""准备各个图像(得分,历史记录,等级,剩余飞船)"""
self.prep_score()
self.prep_high_score()
self.prep_level()
self.prep_ships()
self.prep_power()
def prep_score(self):
"""将得分渲染为图像"""
rounded_score = round(self.stats.score, -1)
score_str = "{:,}".format(rounded_score)
self.score_image = self.font.render(score_str, True, self.text_color, self.ai_settings.bg_color)
# 将得分放在屏幕右上角
self.score_rect = self.score_image.get_rect()
self.score_rect.top = 20
self.score_rect.right = self.screen_rect.right - 20
def prep_high_score(self):
"""将历史记录渲染为图像"""
rounded_high_score = round(self.stats.high_score, -1)
high_score_str = "Record: " + "{:,}".format(rounded_high_score)
self.high_score_image = self.font.render(high_score_str, True, self.text_color, self.ai_settings.bg_color)
# 将历史记录放在屏幕左下角
self.high_score_rect = self.high_score_image.get_rect()
self.high_score_rect.bottom = self.screen_rect.bottom - 10
self.high_score_rect.left = self.screen_rect.left + 10
def prep_level(self):
"""将等级渲染为图像"""
level_str = "Level: " + str(self.stats.level)
self.level_image = self.font.render(level_str, True, self.text_color, self.ai_settings.bg_color)
# 将等级放在得分下面
self.level_rect = self.level_image.get_rect()
self.level_rect.top = self.score_rect.bottom
self.level_rect.right = self.screen_rect.right - 20
def prep_ships(self):
"""显示剩余飞船"""
self.ships = Group()
for ship_number in range(self.stats.ships_left):
ship = Ship(self.ai_settings, self.screen)
ship.image = pygame.transform.scale(ship.image,(25, 27))
ship.rect = ship.image.get_rect()
ship.rect.x = ship.rect.width * ship_number + 10
ship.rect.y = 10
self.ships.add(ship)
def prep_power(self):
"""将大招渲染为图像"""
power_num = int(self.stats.power / self.ai_settings.points_of_power)
power_str = "Power: " + str(power_num)
self.power_image = self.font.render(power_str, True, self.text_color, self.ai_settings.bg_color)
# 将大招数放在屏幕右下
self.power_rect = self.power_image.get_rect()
self.power_rect.bottom = self.screen_rect.bottom - 10
self.power_rect.right = self.screen_rect.right - 10

1
scores.json Normal file
View File

@ -0,0 +1 @@
[{"player": "666", "score": 425805}, {"player": "cwj", "score": 21874}, {"player": "Your Name", "score": 4850}, {"player": "Your Name", "score": 4700}, {"player": "Your Name", "score": 2900}, {"player": "Your Name", "score": 1350}, {"player": "Your Name", "score": 1250}]

73
settings.py Normal file
View File

@ -0,0 +1,73 @@
import pygame
class Settings():
"""储存《外星人入侵》所有设置的类"""
def __init__(self):
"""初始化游戏的设置"""
# 屏幕设置
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (0, 0, 0)
self.lb_bg_color = (10, 10, 10)
self.lb_text_color = (230, 230, 230)
# 飞船设置
self.ship_limit = 3
# 子弹设置
self.bullet_width = 3
self.bullet_height = 15
self.bullet_color = (180, 180, 180)
self.bullets_allowed = 5
# 超级子弹设置
self.super_bullet_color = (0, 255, 0)
self.super_bullet_width = 6
self.super_bullet_height = 150
self.points_of_power = 1000
# 外星人设置
self.fleet_drop_speed = 10
self.alien_bullet_color = (220, 220, 0)
# 游戏加快节奏参数
self.speedup_scale = 1.1
# 击中外星人得分点数的提高速度
self.score_scale = 1.2
# 音效设置
self.bullet_sound = pygame.mixer.Sound("sounds/bullet.wav")
self.super_bullet_sound = pygame.mixer.Sound("sounds/super_bullet.wav")
self.ship_hit_sound = pygame.mixer.Sound("sounds/ship_hit.wav")
self.start_new_level_sound = pygame.mixer.Sound("sounds/start_new_level.wav")
self.super_mode_sound = pygame.mixer.Sound("sounds/super_mode.wav")
self.gameover_sound = pygame.mixer.Sound("sounds/gameover.wav")
self.recordbroken_sound = pygame.mixer.Sound("sounds/recordbroken.wav")
# 初始化游戏动态设置
self.initialize_dynamic_settings()
def initialize_dynamic_settings(self):
"""初始化动态参数"""
self.ship_speed_factor = 1.5
self.bullet_speed_factor = 3
self.alien_speed_factor = 1
self.super_bullet_speed_factor = 30
# 1表示右移-1表示左移
self.fleet_direction = 1
# 记分
self.alien_points = 50
def increase_speed(self):
"""提高速度设置"""
self.ship_speed_factor *= self.speedup_scale
self.bullet_speed_factor *= self.speedup_scale
self.alien_speed_factor *= self.speedup_scale
self.alien_points = int(self.alien_points * self.score_scale)

50
ship.py Normal file
View File

@ -0,0 +1,50 @@
import pygame
from pygame.sprite import Sprite
class Ship(Sprite):
def __init__(self, ai_settings, screen):
"""初始化飞船并设置其初始位置"""
super().__init__()
self.ai_settings = ai_settings
self.screen = screen
# 加载飞船图像并获得其外接矩形
self.image = pygame.image.load('images/ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
# 将飞船放在屏幕底部中央
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
# 在飞船的属性center中储存小数值
self.center = float(self.rect.centerx)
# 移动标志
self.moving_right = False
self.moving_left = False
# 无敌标志
self.super_mode = False
def update(self):
"""根据移动标志调整飞船位置"""
if self.moving_right and self.rect.right < self.screen_rect.right:
self.center += self.ai_settings.ship_speed_factor
if self.moving_left and self.rect.left > self.screen_rect.left:
self.center -= self.ai_settings.ship_speed_factor
self.rect.centerx = self.center
def blitme(self):
"""在指定位置绘制飞船"""
self.screen.blit(self.image, self.rect)
if self.super_mode:
# 无敌模式,绘制金色边框
pygame.draw.rect(self.screen, (200, 200, 0),(self.rect), 2)
def center_ship(self):
self.rect.centerx = self.screen_rect.centerx

16
super_bullet.py Normal file
View File

@ -0,0 +1,16 @@
import pygame
from bullet import Bullet
class SuperBullet(Bullet):
"""一个对飞船发射的超级子弹进行管理的类"""
def __init__(self, ai_settings, screen, ship):
"""在飞船所处的位置创建一个子弹对象"""
super().__init__(ai_settings, screen, ship)
# 设置超级子弹宽高,颜色及速度
self.rect.width = ai_settings.super_bullet_width
self.rect.height = ai_settings.super_bullet_height
self.color = ai_settings.super_bullet_color
self.speed_factor = ai_settings.super_bullet_speed_factor

28
使用说明.txt Normal file
View File

@ -0,0 +1,28 @@
配置:
pygame版本 1.9.4
python版本 3.6.0
主文件为alien_invasion.py
---------------------------------
游戏指南:
鼠标点击白色“Your Name”输入框输入你的名字
点击“play”开始游戏
操作:
方向左右键控制移动
空格键发射子弹
每消灭一个敌人会获得一定积分(右上角显示)随Level提高游戏难度会加大
相应的击中奖励积分会增加,每累计一定积分可获得一点能量值。
右下角的Power值表示剩余能量值有两种可选用途(每次均消耗1点能量)
1. 按方向上键获得5秒无敌状态不会被敌人子弹击中
2. 按左Alt键发射超级子弹比普通子弹更大且命中一个敌人后不会
立刻消失使用得当可消灭整列4个敌人
游戏结束会显示5秒排行榜Top10, 期间不可操作过后可再次点击Play重新开始
游戏。(没有注销系统,游戏期间无法更改用户名)