欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

《python编程:从入门到实践的》外星人入侵的代码

程序员文章站 2022-09-21 15:09:08
alien.py#管理外星人的类import pygamefrom pygame.sprite import Spriteclass Alien(Sprite): def __init__(self,ai_settings,screen): super(Alien,self).__init__() self.ai_settings = ai_settings self.screen = screen #加载外星人图片,并设...

alien.py

#管理外星人的类

import pygame
from pygame.sprite import Sprite

class Alien(Sprite):
    def __init__(self,ai_settings,screen):
        super(Alien,self).__init__()
        self.ai_settings = ai_settings
        self.screen = screen

        #加载外星人图片,并设置rect属性,类类前面加载飞船图片
        self.image = pygame.image.load('images/alien.bmp')
        self.rect = self.image.get_rect()

        #将外星人放在屏幕的左上角附近(距离左边和上边有一个外星人的距离),若是要设置在左上角可以直接赋值0
        self.rect.x = self.rect.width
        self.rect.y = self.rect.height

        #将外星人的坐标转化成可以存储小数的float类型,这样位置更加准确
        self.x = float(self.rect.x)
        self.y = float(self.rect.y)

    def blitme(self):
        #绘制外星人
        self.screen.blit(self.image,self.rect)

    #检查外星人是否撞到边缘
    def check_edges(self):
        """ 如果外星人位于屏幕边缘,就返回 True"""
        screen_rect = self.screen.get_rect()
        #如果外星人的 rect 的 right 属性大于或等于屏幕的 rect 的 right 属性,则位于右边缘
        if self.rect.right >= screen_rect.right:
            return True
        #如果外星人的 rect 的 left 属性小于或等于 0,则位于左边缘
        elif self.rect.left <= 0:
            return True

    def update(self):
        """ 向右或向左移动外星人 """
        self.x += (self.ai_settings.alien_speed_factor *
                   self.ai_settings.fleet_direction)
        self.rect.x = self.x

alien_invasion.py

#窗口居中需要
import os

#pygame包含游戏需要的功能
import pygame

from settings import Settings
from ship import Ship
import game_functions as gf
from alien import Alien
from game_stats import Gamestats
from button import Button
from scoreboard import Scoreboard

#导入了 pygame.sprite 中的 Group 类
from pygame.sprite import Group

def run_game():
    #初始化背景设置,让pygame可以正常工作
    pygame.init()
    #创建Settings的实例
    ai_settings = Settings()

    #设置窗口居中显示
    os.environ['SDL_VIDEO_CENTERED'] = '1'

    #创建显示窗口,(1200,800)是元组,要注意添加括号;创建了一个宽 1200 像素、高 800 像素的游戏窗口
    #screen是一个surface, surface 是屏幕的一部分,用于显示游戏元素,每个游戏元素都是一个surface(外星人或飞船)
    #激活动画循环后,每次循环都会重绘这个surface
    #screen = pygame.display.set_mode((1200,800))
    #设置背景色后会有黑色闪过,可以先初始化一个小窗口然后再初始化创建的窗口:screen = pygame.display.set_mode((1,1))
    screen = pygame.display.set_mode((1,1))
    screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
    #设置窗口标题
    pygame.display.set_caption('外星人入侵')

    # 创建ship的实例:创建一艘飞船
    ship = Ship(screen,ai_settings)

    #创建外星人实例
    alien = Alien(ai_settings,screen)

    #创建一个编组group,用于存储所有有效的子弹,以便能够管理发射出去的所有子弹。这个编组将是 pygame.sprite.Group 类的一个实例
    #pygame.sprite.Group类类似于列表,但提供了有助于开发游戏的额外功能
    bullets = Group()

    #创建很多外星人,类似创建很多子弹
    aliens = Group()

    #默认的是黑色的,可以设置屏幕背景色
    #bg_color = (230,230,230)

    # 创建外星人群,这个不能放在while中,不然移动会很慢
    gf.creat_fleet(ai_settings, screen, ship, aliens)

    #创建存储游戏信息的类的实例
    stats = Gamestats(ai_settings)

    # 创建分数
    sb = Scoreboard(ai_settings, screen, stats)

    # 创建Play按钮
    play_button = Button(ai_settings, screen, "Play")

    #开始游戏主循环
    while True:
        #管理事件
        gf.check_events(ai_settings,screen,stats,sb, play_button,ship,aliens,bullets)
        #若是为True,这些都会更新,但若是为False,则飞船、子弹、外星人不会重新更新
        if stats.game_active:
            #飞船位置更新
            ship.update()
            #更新子弹
            gf.update_bullets(ai_settings, screen, stats, sb, ship, aliens, bullets)
            #更新外星人
            #在更新子弹后再更新外星人的位置,因为稍后要检查是否有子弹撞到了外星人
            gf.update_aliens(ai_settings, stats, screen, sb, ship, aliens, bullets)
        #更新屏幕
        gf.update_screen(ai_settings, screen, stats, sb, ship,aliens, bullets, play_button)

#初始化游戏,开始运行主循环
run_game()

bullet.py

#子弹的类

import pygame
from pygame.sprite import Sprite

#Bullet继承了从模块pygame.sprite中导入的类Sprite
#在pygame.sprite模块里面包含了一个名为Sprite类,他是pygame本身自带的一个精灵
# 通过使用精灵,可将游戏中相关的元素编组,进而同时操作编组中的所有元素
class Bullet(Sprite):
    def __init__(self,ai_setings,screen,ship):
        #python3也可以这样写: super().__init__()
        super(Bullet,self).__init__()
        self.screen = screen

        #创建一个子弹,但是子弹并非是基于图像的(跟前面的飞船不同),因此必须使用pygame.Rect()类从空白开始创建一个矩形
        #创建时必须提供矩形左上角x,y的坐标以及宽和高
        self.rect = pygame.Rect(0,0,ai_setings.bullet_screen_width,ai_setings.bullet_screen_height)
        #将子弹的x位置设置的与飞船的相同
        self.rect.centerx = ship.rect.centerx
        #将子弹的top设置的与飞行的top相同,这样看起来子弹是从飞船射出的
        self.rect.top = ship.rect.top

        #将子弹的y坐标设置成小数(移动的速度不一定是整数)
        self.y = float(self.rect.y)

        #获取子弹的颜色
        self.color = ai_setings.bullet_bg_color
        #获取子弹的速度
        self.speed_factor = ai_setings.bullet_speed_factor

    def update(self):
        #子弹向上移动,y会变小
        self.y -= self.speed_factor
        #更新子弹的位置
        self.rect.y = self.y

    def draw_bullet(self):
        #在屏幕上绘制子弹
        pygame.draw.rect(self.screen,self.color,self.rect)

button.py

#创建按钮

import pygame

class Button():
    def __init__(self, ai_settings,screen,msg):
        """初始化按钮的属性"""
        self.screen = screen
        self.screen_rect = screen.get_rect()

        # 设置按钮的尺寸
        self.width, self.height = 200, 50
        self.button_color = (120, 255, 100)
        self.text_color = (255, 255, 255)
        #字体
        self.font = pygame.font.SysFont(None, 48)

        # 创建按钮的rect对象,并使其居中
        self.rect = pygame.Rect(0, 0, self.width, self.height)
        self.rect.center = self.screen_rect.center

        # 按钮的标签只需创建一次
        #Pygame通过将你要显示的字符串渲染为图像来处理文本
        self.prep_msg(msg)

    #将msg渲染为图像,并使其在按钮上居中
    def prep_msg(self, msg):
        #将存储在msg中的文本转换为图像,然后将该图像存储在msg_image中
        #方法font.render()还接受一个布尔实参,该实参指定开启还是关闭反锯齿功能(反锯齿让文本的边缘更平滑)。余下的两个实参分别是文本颜色和背景色
        #启用了反锯齿功能,并将文本的背景色设置为按钮的颜色
        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):
        #调用screen.fill()来绘制表示按钮的矩形
        self.screen.fill(self.button_color, self.rect)
        #调用screen.blit(),并向它传递一幅图像以及与该图像相关联的rect对象,从而在屏幕上绘制文本图像
        self.screen.blit(self.msg_image, self.msg_image_rect)

game_functions.py

#管理函数,避免 alien_invasion.py 太长

#退出游戏时需要用sys.exit()
import sys
import pygame
from bullet import Bullet
from alien import Alien
from time import sleep

#按下按键
def check_keydown_events(event,ai_settings,screen,ship,bullets):
    # 如果按右箭头,移动标志为True
    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_bullets(ai_settings, bullets, screen, ship)
    #按q键退出游戏
    elif event.key == pygame.K_q:
        sys.exit()

#松开按键
def check_keyup_events(event,ship):
    # 如果松开右箭头,移动标志位False
    if event.key == pygame.K_RIGHT:
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:
        ship.moving_left = False

#发射子弹
def fire_bullets(ai_settings,bullets,screen,ship):
    # 若是屏幕上的子弹数目少于设置的数目,则可以创建新的子弹,否则点击空格无效
    if len(bullets) < ai_settings.bullet_allowed:
        # 按下空格键后,创建一个子弹
        new_bullet = Bullet(ai_settings, screen, ship)
        # 将子弹加入编组中
        bullets.add(new_bullet)

#检查鼠标点击位置是否在按钮的区域内
def check_play_button(ai_settings, screen, stats, sb,play_button, ship, aliens, bullets, mouse_x, mouse_y):
    """在玩家单击Play按钮时开始新游戏"""
    # 重置游戏设置,将游戏中的子弹等速度重置
    ai_settings.initialize_dynamic_settings()
    # 开始游戏,隐藏光标
    pygame.mouse.set_visible(False)
    button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
    #判断当点击了按钮且游戏的状态为不活跃状态时
    if button_clicked and not stats.game_active:
        # 重置游戏统计信息
        stats.reset_stats()
        #分数重置
        sb.prep_score()
        #等级重置
        sb.prep_level()
        #刷新飞船数目
        sb.prep_ships()
        #游戏状态为活跃
        stats.game_active = True
        # 清空外星人列表和子弹列表
        aliens.empty()
        bullets.empty()

        # 创建一群新的外星人,并让飞船居中
        creat_fleet(ai_settings, screen, ship, aliens)
        ship.center_ship()

#管理事件的函数
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)
        #松开按键
        elif event.type == pygame.KEYUP:
            check_keyup_events(event,ship)

        #点击开始按钮
        elif event.type == pygame.MOUSEBUTTONDOWN:
            #获取点击鼠标时的x和y坐标
            mouse_x, mouse_y = pygame.mouse.get_pos()
            #检查是否点击鼠标,若是则开始游戏
            check_play_button(ai_settings, screen, stats,sb, play_button, ship, aliens, bullets, mouse_x, mouse_y)

#更新屏幕
def update_screen(ai_settings,screen,stats,sb,ship,aliens,bullets,play_button):
    # 每次循环都重绘屏幕的背景色
    # screen.fill(bg_color)
    screen.fill(ai_settings.bg_color)
    # 绘制飞船,并确保在背景色前面,不然会被遮挡
    ship.blitme()
    #绘制外星人
    #aliens.blitme()
    aliens.draw(screen)
    # 方法bullets.sprites() 返回一个列表,其中包含编组bullets 中的所有精灵
    # 在屏幕上发射所有子弹,在飞船和外星人后面绘制
    for bullet in bullets.sprites():
        bullet.draw_bullet()

    # 显示得分
    sb.show_score()
    # 如果游戏处于非活动状态,就绘制Play按钮
    if not stats.game_active:
        play_button.draw_button()

    # 不断更新屏幕,来显示元素的新位置
    # 每次运行while时都显示一个新屏幕,并擦去旧屏幕
    pygame.display.flip()

#更新子弹
def update_bullets(ai_settings, screen, stats, sb, ship, aliens,bullets):
    # 子弹位置更新,对编组调用 update() 时,编组将自动对其中的每个精灵调用 update()
    bullets.update()
    # 删除已经消失的子弹
    # 不能在列表或者编组中删除,可以用copy()来遍历编组的副本
    for bullet in bullets.copy():
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)
    check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship, aliens, bullets)

#击中外星人后清除子弹和外星人,当外星人为0时再生成新的外星人
def check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship, aliens, bullets):
    # 检查是否有子弹击中外星人,有则删除相应的子弹和外星人
    # 码遍历编组bullets中的每颗子弹,再遍历编组aliens中的每个外星人。每当有子弹和外星人的rect重叠时,groupcollide()就在它返回的字典中添加一个键值对
    # 两个实参True告诉Pygame删除发生碰撞的子弹和外星人
    # 若是要模拟能够穿行到屏幕顶端的高能子弹——消灭它击中的每个外星人,可将第一个布尔实参设置为False,并让第二个布尔实参为True。这样被击中的外星人将消失,但所有的子弹都始终有效,直到抵达屏幕顶端后消失。
    collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
    #有子弹撞到外星人时,Pygame返回一个字典(collisions)。我们检查这个字典是否存在,如果存在,就将得分加上一个外星人值的点数
    if collisions:
        #遍历字典,确保每个外星人都会计分
        for aliens in collisions.values():
            stats.score += ai_settings.alien_points * len(aliens)
            sb.prep_score()
        #每次有外星人被消灭都会重新更新最高分
        check_high_score(stats, sb)
    # 判断外星人是否为0,若是进行下面的操作
    if len(aliens) == 0:
        # 清空子弹
        bullets.empty()
        #增加飞船,子弹,外星人的速度
        ai_settings.increase_speed()
        # 提高等级,所有外星人被消灭就提升一个等级
        stats.level += 1
        sb.prep_level()
        # 创建新的外星人
        creat_fleet(ai_settings, screen, ship, aliens)

#计算可以放多少行外星人
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 get_number_aliens_x(ai_settings,alien_width):
    # 除去屏幕2边的间距(一个外星人的距离),剩余可以放外星人的宽度
    available_space_x = ai_settings.screen_width - 2 * alien_width
    # 每个外星人之间有一个外星人宽度的距离,用int获取可以放外星人的数目(整数)
    number_aliens_x = int(available_space_x / (2 * alien_width))
    return number_aliens_x

def create_alien(ai_settings, screen, aliens, alien_number, row_number):
    # 创建一个外星人实例
    alien = Alien(ai_settings, screen)
    # 获取外星人的宽度
    alien_width = alien.rect.width
    # 计算每个外星人的x坐标
    alien.x = alien_width + 2 * alien_width * alien_number
    alien.rect.x = alien.x
    # 计算每个外星人的y坐标
    alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
    aliens.add(alien)

#创建外星人
def creat_fleet(ai_settings, screen, ship, aliens):
    alien = Alien(ai_settings, screen)
    #number_aliens_x = get_number_aliens_x(ai_settings,alien.rect.width)


    #一行创建多个外星人
    #for alien_number in range(number_aliens_x):
        #create_alien(ai_settings,screen,alien_number,aliens)

    number_aliens_x = get_number_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():
        #如果外星人位于边缘则返回True
        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
    #将外星人左右移动的值乘-1,以此来改变左右移动的方向
    ai_settings.fleet_direction *= -1

#如果外星人和飞船相撞,则清空屏幕,重新开始游戏
def ship_hit(ai_settings,stats,screen,sb,ship,aliens,bullets):
    #若是飞船数大于0,则可以重新开始
    if stats.ships_left > 0:
        #若外星人和飞船相撞则减去一个飞船
        stats.ships_left -= 1
        # 更新飞船
        sb.prep_ships()
        #清空飞船和子弹
        aliens.empty()
        bullets.empty()
        #重新创建外星人
        creat_fleet(ai_settings,screen,ship,aliens)
        #将飞船放到屏幕中间
        ship.center_ship()
        #休眠1s
        sleep(1)
    #若飞船数没有大于0,游戏结束
    else:
        stats.game_active = False
        #游戏为不活跃状态时,显示光标
        pygame.mouse.set_visible(True)

#如果外星人到达屏幕底部,游戏结束
def check_aliens_bottom(ai_settings,stats,screen,sb,ship,aliens,bullets):
    #屏幕属性
    screen_rect = screen.get_rect()
    #遍历外星人
    for alien in aliens.sprites():
        #若外星人的rect.bottom大于屏幕的rect.bottom,则外星人到达屏幕底部
        if alien.rect.bottom >= screen_rect.bottom:
            #外星人到达底部,则相当于外星人和飞船相撞
            ship_hit(ai_settings, stats, screen, sb,ship, aliens, bullets)
            #结束循环
            break

#更新外星人的位置
def update_aliens(ai_settings,stats,screen,sb,ship,aliens,bullets):
    # 检查是否有外星人位于边缘,若有则更新外星人的位置
    check_fleet_edges(ai_settings, aliens)
    aliens.update()
    #若是外星人和飞船碰到了就执行后面的
    #方法spritecollideany()接受两个实参:一个精灵和一个编组,在这里,它遍历编组aliens,并返回它找到的第一个与飞船发生了碰撞的外星人
    if pygame.sprite.spritecollideany(ship,aliens):
        ship_hit(ai_settings,stats,screen,sb,ship,aliens,bullets)
    #外星人到达底部,则相当于外星人和飞船相撞
    check_aliens_bottom(ai_settings, stats, screen, 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()

game_stats.py

#根据游戏统计信息的类

class Gamestats():
    def __init__(self,ai_settings):
        self.ai_setting = ai_settings
        self.reset_stats()
        #游戏刚开始时游戏处于非活跃状态
        self.game_active = False
        # 在任何情况下都不应重置最高得分
        self.high_score = 0

    def reset_stats(self):
        #ships_left是飞船的数目
        self.ships_left = self.ai_setting.ship_limit
        #分数
        self.score = 0
        #等级
        self.level = 1

scoreboard.py

#计分

import pygame.font
from pygame.sprite import Group
from ship import Ship

class Scoreboard():
    """显示得分信息的类"""
    def __init__(self, ai_settings, screen, stats):
        """初始化显示得分涉及的属性"""
        self.screen = screen
        self.screen_rect = screen.get_rect()
        self.ai_settings = ai_settings
        self.stats = stats

        # 显示得分信息时使用的字体设置
        self.text_color = (30, 30, 30)
        #实例化一个字体对象
        self.font = pygame.font.SysFont(None, 48)
        # 准备初始得分图像
        self.prep_score()
        #最高分展示
        self.prep_high_score()
        #展示等级
        self.prep_level()
        #显示还剩多少飞船
        self.prep_ships()

    def prep_score(self):
        """将得分转换为一幅渲染的图像"""
        #将stats.score的值圆整到最近的10的整数倍
        rounded_score = int(round(self.stats.score, -1))
        #将数值转换为字符串时在其中插入逗号
        score_str = "{:,}".format(rounded_score)
        #将数字转换成字符串
        #score_str = str(self.stats.score)
        #将字符串传递成创建图片的render()
        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()
        #右边缘与屏幕右边缘相距20像素
        self.score_rect.right = self.screen_rect.right - 20
        #上边缘与屏幕上边缘也相距20像素
        self.score_rect.top = 20

    def prep_high_score(self):
        """将最高得分转换为渲染的图像"""
        high_score = int(round(self.stats.high_score, -1))
        high_score_str = "{:,}".format(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.centerx = self.screen_rect.centerx
        self.high_score_rect.top = self.score_rect.top

    def prep_level(self):
        """将等级转换为渲染的图像"""
        self.level_image = self.font.render(str(self.stats.level), True,self.text_color, self.ai_settings.bg_color)

        '''将等级放在得分下方'''
        #方法prep_level()根据存储在stats.level中的值创建一幅图像
        self.level_rect = self.level_image.get_rect()
        #将其right属性设置为得分的right属性
        self.level_rect.right = self.score_rect.right
        #将top属性设置为比得分图像的bottom属性大10像素,以便在得分和等级之间留出一定的空间
        self.level_rect.top = self.score_rect.bottom + 10

    def prep_ships(self):
        """显示还余下多少艘飞船"""
        #创建一个空编组,存储飞船实例
        self.ships = Group()
        for ship_number in range(self.stats.ships_left):
            ship = Ship(self.screen,self.ai_settings)
            #x坐标,整个飞船编组都位于屏幕左边,且每艘飞船的左边距都为10像素
            ship.rect.x = 10 + ship_number * ship.rect.width
            #将y坐标设置为离屏幕上边缘10像素,让所有飞船都与得分图像对齐
            ship.rect.y = 10
            #将每艘新飞船都添加到编组ships中
            self.ships.add(ship)

    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.ships.draw(self.screen)

settings.py

#设置类,将所有的设置都放在一起,方便后续的修改

class Settings():
    def __init__(self):
        """初始化游戏的静态设置"""
        #屏幕设置(大小,背景色)
        self.screen_width = 840
        self.screen_height = 600
        self.bg_color = (230,230,230)

        #飞船的数目
        self.ship_limit = 3

        #设置子弹的大小,速度,颜色
        self.bullet_screen_width = 200
        self.bullet_screen_height = 15
        #self.bullet_ship_speed_factor = 1
        self.bullet_bg_color = (60, 60, 60)
        #子弹数目(用来限制屏幕上的子弹的数目)
        self.bullet_allowed = 5

        #外星人向下速度
        self.fleet_drop_speed = 20

        # 以什么样的速度加快游戏节奏,后面速度改变会乘以这个数值
        self.speedup_scale = 1.1
        # 外星人点数的提高速度
        self.score_scale = 1.5
        self.initialize_dynamic_settings()

        # 记分
        self.alien_points = 50

    def initialize_dynamic_settings(self):
        """初始化随游戏进行而变化的设置"""
        # 设置飞船的移动速度
        self.ship_speed_factor = 1.5
        #子弹的速度
        self.bullet_speed_factor = 1
        # 外星人水平速度
        self.alien_speed_factor = 1
        # 外星人,fleet_direction 为 1 表示向右移,为 -1 表示向左移
        self.fleet_direction = 1

    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
        #为了使分数为整数,使用int()
        self.alien_points = int(self.alien_points * self.score_scale)

ship.py

#创建管理飞船大部分行为的类

import pygame
from pygame.sprite import Sprite

#Ship继承Sprite,以便能够创建飞船编组
class Ship(Sprite):
    #screen指定飞船绘制到哪个地方
    def __init__(self,screen,ai_settings):
        super(Ship, self).__init__()
        self.screen = screen
        self.ai_settings = ai_settings

        #加载飞船图片,表示返回一个飞船的surface
        self.image = pygame.image.load('images/ship.bmp')
        #获取surface的属性rect:get_rect()
        self.rect = self.image.get_rect()
        self.screen_rect = screen.get_rect()

        #把飞船放在屏幕的中间:飞船中心=屏幕X方向的中心
        self.rect.centerx = self.screen_rect.centerx
        #self.rect.centerx只能存储整数,若是移动的速度有小数,可将此数值转化成float类型,并赋值给另一个变量
        self.center = float(self.rect.centerx)
        #飞船在屏幕底部:飞船底部=屏幕底部
        self.rect.bottom = self.screen_rect.bottom

        #移动标志,向右移动
        self.moving_right = False
        # 移动标志,向左移动
        self.moving_left = False

    #如果移动标志为True,则向右/左移动
    def update(self):
        #控制飞船不会右移到屏幕外面,self.rect.right表示飞船外接矩形右边缘x的位置,这个值小于屏幕的self.screen_rect.right说明没有未到边缘
        if self.moving_right and self.rect.right < self.screen_rect.right:
            #self.rect.centerx不能存储小数,可用self.center
            self.center += self.ai_settings.ship_speed_factor
        #self.rect.left左边缘的x坐标大于0,说明没有到屏幕左边缘
        if self.moving_left and self.rect.left > 0:
            self.center -= self.ai_settings.ship_speed_factor

        #再将self.center的数赋值给self.rect.centerx,虽然只存储整数位,但整体位置的影响不大
        self.rect.centerx = self.center

    def blitme(self):
        #在指定的位置绘制飞船
        self.screen.blit(self.image,self.rect)

    #让飞船在屏幕上居中
    def center_ship(self):
        self.center = self.screen_rect.centerx

直接运行alien_invasion.py即可
《python编程:从入门到实践的》外星人入侵的代码

图片:
ship.bmp
《python编程:从入门到实践的》外星人入侵的代码
alien.bmp
《python编程:从入门到实践的》外星人入侵的代码

本文地址:https://blog.csdn.net/qq_41917061/article/details/108979419

相关标签: python