栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

python从入门到实践13章答案

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

python从入门到实践13章答案

目录

前言

一、13-1星星

二、13-2更逼真的星星

三、13-3雨滴

四、13-4连绵细雨

五、13-5 侧面射击2

六、13-6游戏结束

总结


前言

这里是Python从入门到实践的练习答案,本人也是初学python,在这里把我的答案记录下来。如果有错误或者可以改进的地方欢迎在评论区留言。另外,所有代码均按照书上方式重构,便于阅读和理解。

后两题的答案是根据12章答案改进而来,感兴趣的uu们可以去专栏里找找看。

另外注意相对路径问题。


一、13-1星星

在网上找的图片 没找到合适大小的( 尺寸小就美观一些

图片命名为 star.png

 新建star.py

import pygame
from pygame.sprite import Sprite

class Star(Sprite):
    """表示单个星星的类"""
    def __init__(self, ai_game):
        """初始化星星"""
        super().__init__()
        self.screen = ai_game

        #加载星星图像并设置其rect
        self.image = pygame.image.load('star.png')
        self.rect = self.image.get_rect()

        #每个星星一开始都在屏幕左上角附近
        self.rect.x = self.rect.width - 50
        self.rect.y = self.rect.height - 50

        #储存星星的精确位置
        self.x = float(self.rect.x)
        self.y = float(self.rect.y)

新建sky.py

import sys
import pygame
from star import Star

class Sky:
    """管理天空的类"""
    def __init__(self):
        """初始化界面"""
        pygame.init()
        self.screen = pygame.display.set_mode((1000, 800))
        self.screen_rect = self.screen.get_rect()
        pygame.display.set_caption("Star Sky")

        self.stars = pygame.sprite.Group()
        self._create_fleet()

    def _create_fleet(self):
        """创建星云"""
        #计算一行可以容纳多少星星
        star = Star(self)
        star_width = star.rect.width
        available_space_x = self.screen_rect.width - 100
        number_stars_x = available_space_x // (star_width * 2)

        for row_number in range(3):
            #创建一行星星
            for star_number in range(number_stars_x):
                #创建一个星星并加入当前行
                self._create_star(star_number, row_number)

    def _create_star(self, star_number, row_number):
        #创建一个星星
        star = Star(self)
        star_width = star.rect.width
        star_height = star.rect.height

        star.x = 50 + star_width * star_number * 2
        star.rect.x = star.x

        star.y = 50 + star_height * row_number * 2
        star.rect.y = star.y

        self.stars.add(star)

    def _update_screen(self):
        """绘制屏幕"""
        self.screen.fill((0, 190, 230))
        self.stars.draw(self.screen)
        pygame.display.flip()

    def run_game(self):
        """主循环"""
        while True:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit()
            self._update_screen()

if __name__ == "__main__":
    ai = Sky()
    ai.run_game()

 结果是这样的 星星小点就好了(


二、13-2更逼真的星星

只需对 sky.py 做少许修改

import sys
import pygame
from star import Star
from random import randint

class Sky:
    """管理天空的类"""
    def __init__(self):
        """初始化界面"""
        pygame.init()
        self.screen = pygame.display.set_mode((1000, 800))
        self.screen_rect = self.screen.get_rect()
        pygame.display.set_caption("Star Sky")

        self.stars = pygame.sprite.Group()
        self._create_fleet()

    def _create_fleet(self):
        """创建星云"""
        #计算一行可以容纳多少星星
        star = Star(self)
        star_width = star.rect.width
        available_space_x = self.screen_rect.width - 100
        number_stars_x = available_space_x // (star_width * 2)

        for row_number in range(3):
            #创建一行星星
            for star_number in range(number_stars_x):
                #创建一个星星并加入当前行
                star_number = randint(0, number_stars_x)
                self._create_star(star_number, row_number)

    def _create_star(self, star_number, row_number):
        #创建一个星星
        star = Star(self)
        star_width = star.rect.width
        star_height = star.rect.height

        star.x = 50 + star_width * star_number * 2
        star.rect.x = star.x

        star.y = 50 + star_height * row_number * 2
        star.rect.y = star.y

        if star.rect.right < self.screen_rect.right:
            self.stars.add(star)

    def _update_screen(self):
        """绘制屏幕"""
        self.screen.fill((0, 190, 230))
        self.stars.draw(self.screen)
        pygame.display.flip()

    def run_game(self):
        """主循环"""
        while True:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit()
            self._update_screen()

if __name__ == "__main__":
    ai = Sky()
    ai.run_game()

结果是这样的:


三、13-3雨滴

雨滴和星星差不多,这里直接修改 star.py 将星星都换成雨滴就行

将背景改为白色

在 raindrop.py里直接设置速度,就不新建settings.py文件专门储存设置了

另外稍微修改raindrop.py

 raindrop.py

import pygame
from pygame.sprite import Sprite

class Raindrop(Sprite):
    """表示单个雨滴的类"""
    def __init__(self, ai_game):
        """初始化雨滴"""
        super().__init__()
        self.screen = ai_game

        #加载雨滴图像并设置其rect
        self.image = pygame.image.load('raindrop.png')
        self.rect = self.image.get_rect()

        #每个雨滴一开始都在屏幕左上角附近
        self.rect.x = self.rect.width - 50
        self.rect.y = self.rect.height - 50

        #储存雨滴的精确位置
        self.x = float(self.rect.x)
        self.y = float(self.rect.y)

        #雨滴下降速度
        self.speed = 0.3

    def update(self):
        """向下移动雨滴"""
        self.y += self.speed
        self.rect.y = self.y

sky.py

import sys
import pygame
from raindrop import Raindrop

class Sky:
    """管理天空的类"""
    def __init__(self):
        """初始化界面"""
        pygame.init()
        self.screen = pygame.display.set_mode((1000, 800))
        self.screen_rect = self.screen.get_rect()
        pygame.display.set_caption("Star Sky")

        self.raindrops = pygame.sprite.Group()
        self._create_fleet()

    def _create_fleet(self):
        """创建大雨"""
        #计算一行可以容纳多少雨滴
        raindrop = Raindrop(self)
        raindrop_width = raindrop.rect.width
        available_space_x = self.screen_rect.width - 100
        number_raindrop_x = available_space_x // (raindrop_width * 2)

        for row_number in range(3):
            #创建一行雨滴
            for raindrop_number in range(number_raindrop_x):
                #创建一个雨滴并加入当前行
                self._create_raindrop(raindrop_number, row_number)

    def _create_raindrop(self, raindrop_number, row_number):
        #创建一个雨滴
        raindrop = Raindrop(self)
        raindrop_width = raindrop.rect.width
        raindrop_height = raindrop.rect.height

        raindrop.x = 50 + raindrop_width * raindrop_number * 2
        raindrop.rect.x = raindrop.x

        raindrop.y = 50 + raindrop_height * row_number * 2
        raindrop.rect.y = raindrop.y

        self.raindrops.add(raindrop)

    def _update_raindrops(self):
        """更新所有雨滴的位置"""
        self.raindrops.update()

    def _update_screen(self):
        """绘制屏幕"""
        self.screen.fill((255, 255, 255))
        self.raindrops.draw(self.screen)
        pygame.display.flip()

    def run_game(self):
        """主循环"""
        while True:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit()
            self._update_raindrops()
            self._update_screen()

if __name__ == "__main__":
    ai = Sky()
    ai.run_game()

结果是这样的:


四、13-4连绵细雨

修改 raindrop.py

import pygame
from pygame.sprite import Sprite

class Raindrop(Sprite):
    """表示单个雨滴的类"""
    def __init__(self, ai_game):
        """初始化雨滴"""
        super().__init__()
        self.screen = ai_game.screen

        #加载雨滴图像并设置其rect
        self.image = pygame.image.load('raindrop.png')
        self.rect = self.image.get_rect()

        #每个雨滴一开始都在屏幕左上角附近
        self.rect.x = self.rect.width - 50
        self.rect.y = self.rect.height - 50

        #储存雨滴的精确位置
        self.x = float(self.rect.x)
        self.y = float(self.rect.y)

        #雨滴下降速度
        self.speed = 0.3

    def update(self):
        """向下移动雨滴"""
        self.y += self.speed
        self.rect.y = self.y

    def check_edge(self):
        """如果位于屏幕边缘则返回 True"""
        screen_rect = self.screen.get_rect()
        if self.rect.bottom > screen_rect.bottom:
            return True

sky.py

import sys
import pygame
from raindrop import Raindrop

class Sky:
    """管理天空的类"""
    def __init__(self):
        """初始化界面"""
        pygame.init()
        self.screen = pygame.display.set_mode((1000, 800))
        self.screen_rect = self.screen.get_rect()
        pygame.display.set_caption("Star Sky")

        self.raindrops = pygame.sprite.Group()
        self._create_fleet()

    def _create_fleet(self):
        """创建星云"""
        #计算一行可以容纳多少星星
        raindrop = Raindrop(self)
        raindrop_width = raindrop.rect.width
        available_space_x = self.screen_rect.width - 100
        number_raindrop_x = available_space_x // (raindrop_width * 2)

        for row_number in range(3):
            #创建一行星星
            for raindrop_number in range(number_raindrop_x):
                #创建一个星星并加入当前行
                self._create_raindrop(raindrop_number, row_number)

    def _create_raindrop(self, raindrop_number, row_number):
        #创建一个星星
        raindrop = Raindrop(self)
        raindrop_width = raindrop.rect.width
        raindrop_height = raindrop.rect.height

        raindrop.x = 50 + raindrop_width * raindrop_number * 2
        raindrop.rect.x = raindrop.x

        raindrop.y = 50 + raindrop_height * row_number * 2
        raindrop.rect.y = raindrop.y

        self.raindrops.add(raindrop)

    def _check_rain_edge(self):
        """有雨滴到达边缘时采取相应的措施"""
        for raindrop in self.raindrops.sprites():
            if raindrop.check_edge():
                raindrop.y = 0

    def _update_raindrops(self):
        """更新所有雨滴的位置"""
        self.raindrops.update()

    def _update_screen(self):
        """绘制屏幕"""
        self.screen.fill((255, 255, 255))
        self.raindrops.draw(self.screen)
        pygame.display.flip()

    def run_game(self):
        """主循环"""
        while True:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    sys.exit()
            self._check_rain_edge()
            self._update_raindrops()
            self._update_screen()

if __name__ == "__main__":
    ai = Sky()
    ai.run_game()

 结果是这样的


五、13-5 侧面射击2

外星人图片放在这里啦

命名为 enemy1.png

 遗漏的外星人到达边缘以后不会消失,只是看不见

长时间这样运行肯定不好

所以有一个额外任务:删除到达边缘的外星人

 settings.py

class Settings:
    """储存游戏《外星人入侵》中所有设置的类"""
    def __init__(self):
        """初始化游戏的设置"""
        # 屏幕设置
        self.screen_width = 1000
        self.screen_height = 600
        self.bg_color = (0, 200, 255)

        #飞船设置
        self.ship_speed = 0.5

        #子弹设置
        self.bullet_speed = 1.0
        self.bullet_width = 5
        self.bullet_hight = 15
        self.bullet_color = (60, 60, 60)

        #外星人设置
        self.alien_speed = 0.3

 alien.py

import pygame
from pygame.sprite import Sprite

class Alien(Sprite):
    """表示单个外星人的类"""

    def __init__(self, ai_game):
        """初始化外星人并设置起始位置"""
        super().__init__()
        self.screen = ai_game.screen
        self.screen_rect = self.screen.get_rect()
        self.settings = ai_game.settings

        #加载外星人图像并设置其 rect 属性
        self.image = pygame.image.load('enemy1.png')
        self.rect = self.image.get_rect()

        #每个外星人都在屏幕右上角附近
        self.rect.right = self.screen_rect.right
        self.rect.y = 30

        #储存外星人的精确位置
        self.x = float(self.rect.x)

    def update(self):
        """更新外星人的位置"""
        self.x -= self.settings.alien_speed
        self.rect.x = self.x

    def check_edge(self):
        """如果外星人到达边缘就返回 True """
        if self.rect.left < 0:
            return True

 mygame1.0.py

import sys
import pygame
from settings import Settings
from ship import Ship
from bullet import Bullet
from alien import Alien
from random import randint

class MyGame:
    """管理游戏资源和行为的类"""
    def __init__(self):
        """初始化游戏并创建游戏资源"""
        pygame.init()
        self.settings = Settings()

        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height))
        pygame.display.set_caption("MyGame 1.0")

        self.ship = Ship(self)
        self.bullets = pygame.sprite.Group()
        self.aliens = pygame.sprite.Group()

    def _check_fleet_edge(self):
        """到达边缘时对外星人的处理"""
        for alien in self.aliens.sprites():
            if alien.check_edge():
                self.aliens.remove(alien)

    def _create_fleet(self):
        """创建外星人舰队"""
        if 200 == randint(1, 300):
            for alien_num in range(8):
                if 8 == randint(0, 20):
                    num = randint(0, 7)
                    alien = Alien(self)
                    alien.y = 30 + num * (alien.rect.height + 10)
                    alien.rect.y = alien.y
                    self.aliens.add(alien)

    def _update_screen(self):
        """更新屏幕上的图像,并切换到新图像"""
        self.screen.fill(self.settings.bg_color)
        self.ship.blitme()
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()

        self._check_fleet_edge()
        self.aliens.draw(self.screen)

        # 让最近绘制的屏幕可见
        pygame.display.flip()

    def _update_bullets(self):
        """更新子弹的位置并删除消失的子弹"""
        self.bullets.update()
        # 删除消失的子弹
        for bullet in self.bullets.copy():
            if bullet.rect.x > self.settings.screen_width:
                self.bullets.remove(bullet)

        #子弹和外星人碰撞
        collisions = pygame.sprite.groupcollide(
            self.bullets, self.aliens, True, True)

    def _fire_bullet(self):
        """创建一颗子弹,并将其加入编组bullets中"""
        new_bullet = Bullet(self)
        self.bullets.add(new_bullet)

    def _check_events(self):
        """相应按键和鼠标事件"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                self._check_keydown_events(event)

            elif event.type == pygame.KEYUP:
                self._check_keyup_events(event)

    def _check_keydown_events(self, event):
        """响应按键"""
        if event.key == pygame.K_UP:
            # 向上移动角色
            self.ship.moving_up = True
        elif event.key == pygame.K_DOWN:
            # 向下移动角色
            self.ship.moving_down = True
        elif event.key == pygame.K_q:
            #按 q 退出
            sys.exit()
        elif event.key == pygame.K_SPACE:
            self._fire_bullet()

    def _check_keyup_events(self, event):
        """响应松开"""
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = False
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = False
        elif event.key == pygame.K_UP:
            self.ship.moving_up = False
        elif event.key == pygame.K_DOWN:
            self.ship.moving_down = False

    def run_game(self):
       """"开始游戏的主循环"""
       while True:

           self._create_fleet()
           self._check_events()
           self.ship.update()
           self._update_bullets()
           self.aliens.update()
           self._update_screen()

if __name__ == '__main__':
    ai = MyGame()
    ai.run_game()

来看看结果吧:


六、13-6游戏结束

我的游戏规则:

玩家有三艘飞船,与外星人碰撞会损失一艘并停顿0.5秒,没有飞船时游戏结束

外星人飞出屏幕不会损失飞船

增加了一点设置

settings.py

class Settings:
    """储存游戏《外星人入侵》中所有设置的类"""
    def __init__(self):
        """初始化游戏的设置"""
        # 屏幕设置
        self.screen_width = 1000
        self.screen_height = 600
        self.bg_color = (0, 200, 255)

        #飞船设置
        self.ship_speed = 0.5
        self.ship_limit = 3

        #子弹设置
        self.bullet_speed = 0.75
        self.bullet_width = 5
        self.bullet_hight = 15
        self.bullet_color = (60, 60, 60)

        #外星人设置
        self.alien_speed = 0.3

 新建game_stats.py

class GameStats:
    """跟踪游戏的统计信息"""

    def __init__(self, ai_game):
        """初始化统计信息"""
        self.settings = ai_game.settings
        self.reset_stats()

        #游戏刚开始时处于活动状态
        self.game_active = True

    def reset_stats(self):
        """初始化在游戏运行期间可能变化的统计信息"""
        self.ship_left = self.settings.ship_limit

mygame1.0.py

import sys
import pygame
from settings import Settings
from ship import Ship
from bullet import Bullet
from alien import Alien
from random import randint
from game_stats import GameStats
from time import sleep

class MyGame:
    """管理游戏资源和行为的类"""
    def __init__(self):
        """初始化游戏并创建游戏资源"""
        pygame.init()
        self.settings = Settings()

        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height))
        pygame.display.set_caption("MyGame 1.0")

        # 创建一个用于游戏储存的统计信息的实例
        self.stats = GameStats(self)

        self.ship = Ship(self)
        self.bullets = pygame.sprite.Group()
        self.aliens = pygame.sprite.Group()

    def _check_fleet_edge(self):
        """到达边缘时对外星人的处理"""
        for alien in self.aliens.sprites():
            if alien.check_edge():
                self.aliens.remove(alien)

    def _create_fleet(self):
        """创建外星人舰队"""
        if 100 == randint(1, 250):
            for alien_num in range(8):
                if 8 == randint(0, 20):
                    num = randint(0, 7)
                    alien = Alien(self)
                    alien.y = 30 + num * (alien.rect.height + 10)
                    alien.rect.y = alien.y
                    self.aliens.add(alien)

    def _update_screen(self):
        """更新屏幕上的图像,并切换到新图像"""
        self.screen.fill(self.settings.bg_color)
        self.ship.blitme()
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()

        self._check_fleet_edge()
        self.aliens.draw(self.screen)

        # 让最近绘制的屏幕可见
        pygame.display.flip()

    def _update_bullets(self):
        """更新子弹的位置并删除消失的子弹"""
        self.bullets.update()
        # 删除消失的子弹
        for bullet in self.bullets.copy():
            if bullet.rect.x > self.settings.screen_width:
                self.bullets.remove(bullet)

        #子弹和外星人碰撞
        collisions = pygame.sprite.groupcollide(
            self.bullets, self.aliens, True, True)

    def _update_aliens(self):
        """更新外星人的类"""
        self._create_fleet()
        self.aliens.update()

        #检测飞船和外星人的碰撞
        if pygame.sprite.spritecollideany(self.ship, self.aliens):
            if self.stats.ship_left > 0:
                self.stats.ship_left -= 1
                #暂停
                sleep(0.5)

                #清空余下的外星人和子弹
                self.aliens.empty()
                self.bullets.empty()
            else:
                self.stats.game_active = False

    def _fire_bullet(self):
        """创建一颗子弹,并将其加入编组bullets中"""
        new_bullet = Bullet(self)
        self.bullets.add(new_bullet)

    def _check_events(self):
        """相应按键和鼠标事件"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                self._check_keydown_events(event)

            elif event.type == pygame.KEYUP:
                self._check_keyup_events(event)

    def _check_keydown_events(self, event):
        """响应按键"""
        if event.key == pygame.K_UP:
            # 向上移动角色
            self.ship.moving_up = True
        elif event.key == pygame.K_DOWN:
            # 向下移动角色
            self.ship.moving_down = True
        elif event.key == pygame.K_q:
            #按 q 退出
            sys.exit()
        elif event.key == pygame.K_SPACE:
            self._fire_bullet()

    def _check_keyup_events(self, event):
        """响应松开"""
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = False
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = False
        elif event.key == pygame.K_UP:
            self.ship.moving_up = False
        elif event.key == pygame.K_DOWN:
            self.ship.moving_down = False

    def run_game(self):
       """"开始游戏的主循环"""
       while True:
           self._check_events()
           if self.stats.game_active:
               self.ship.update()
               self._update_bullets()
               self._update_aliens()

           self._update_screen()

if __name__ == '__main__':
    ai = MyGame()
    ai.run_game()

结果跟上一题看不出差别

但是测试撞击、结束是成功的

接下来做记分系统

先对游戏画面做点优化

换掉子弹和背景

图片放在这里 背景命名为 background.png 子弹命名为 bullet0.png

 为了便于管理,新建一个image文件夹存放照片

这次改动较大,我把所有文件都贴一下 目录如下图所示

 alien.py

import pygame
from pygame.sprite import Sprite

class Alien(Sprite):
    """表示单个外星人的类"""

    def __init__(self, ai_game):
        """初始化外星人并设置起始位置"""
        super().__init__()
        self.screen = ai_game.screen
        self.screen_rect = self.screen.get_rect()
        self.settings = ai_game.settings

        #加载外星人图像并设置其 rect 属性
        self.image = pygame.image.load('image/enemy1.png')
        self.rect = self.image.get_rect()

        #每个外星人都在屏幕右上角附近
        self.rect.right = self.screen_rect.right
        self.rect.y = 30

        #储存外星人的精确位置
        self.x = float(self.rect.x)

    def update(self):
        """更新外星人的位置"""
        self.x -= self.settings.alien_speed
        self.rect.x = self.x

    def check_edge(self):
        """如果外星人到达边缘就返回 True """
        if self.rect.left < 0:
            return True

bullet.py

import pygame
from pygame.sprite import Sprite

class Bullet(Sprite):
    """管理飞船所发射子弹的类"""

    def __init__(self, ai_game):
        """在飞船当前位置创建一个子弹对象"""
        super().__init__()

        self.screen = ai_game.screen
        self.settings = ai_game.settings

        #在(0,0)处创建一个表示子弹的矩形,再设置正确的位置
        self.buImg = pygame.image.load('image/bullet0.png')
        self.rect = self.buImg.get_rect()
        self.rect.midleft = ai_game.ship.rect.midleft
        self.rect.x = ai_game.ship.rect.right

        #使用小数表示的子弹的位置
        self.x = float(self.rect.x)

    def draw_bullet(self):
        """在屏幕上绘制子弹"""
        self.screen.blit(self.buImg, (self.rect.x, self.rect.y))

    def update(self):
        """向右移动子弹"""
        #更新表示子弹位置的小数值
        self.x += self.settings.bullet_speed
        #更新表示 rect 的位置
        self.rect.x = self.x

gamestats.py

class GameStats:
    """跟踪游戏的统计信息"""

    def __init__(self, ai_game):
        """初始化统计信息"""
        self.settings = ai_game.settings
        self.reset_stats()

        #游戏刚开始时处于活动状态
        self.game_active = True

    def reset_stats(self):
        """初始化在游戏运行期间可能变化的统计信息"""
        self.ship_left = self.settings.ship_limit
        self.score = 0

 mygame1.0.py

import sys
import pygame
from settings import Settings
from ship import Ship
from bullet import Bullet
from alien import Alien
from random import randint
from game_stats import GameStats
from time import sleep
from scoreboard import Scoreboard

class MyGame:
    """管理游戏资源和行为的类"""
    def __init__(self):
        """初始化游戏并创建游戏资源"""
        pygame.init()
        self.settings = Settings()

        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height))
        pygame.display.set_caption("MyGame 1.0")

        # 创建一个用于游戏储存的统计信息的实例
        self.stats = GameStats(self)
        self.sb = Scoreboard(self)

        self.ship = Ship(self)
        self.bullets = pygame.sprite.Group()
        self.aliens = pygame.sprite.Group()

    def _check_fleet_edge(self):
        """到达边缘时对外星人的处理"""
        for alien in self.aliens.sprites():
            if alien.check_edge():
                self.aliens.remove(alien)

    def _check_bullet_alien_collision(self):
        #子弹和外星人碰撞
        collisions = pygame.sprite.groupcollide(
            self.bullets, self.aliens, True, True)
        if collisions:
            self.stats.score += self.settings.alien_points
            self.sb.prep_score()

    def _create_fleet(self):
        """创建外星人舰队"""
        if 1 == randint(1, 15):
            for alien_num in range(8):
                if 8 == randint(0, 20):
                    num = randint(0, 5)
                    alien = Alien(self)
                    alien.y = 30 + num * (alien.rect.height + 10)
                    alien.rect.y = alien.y
                    self.aliens.add(alien)

    def _update_screen(self):  
        """更新屏幕上的图像,并切换到新图像"""
        bmImg = pygame.image.load('image/background.png')
        self.screen.blit(bmImg, (0, 0))
        self.sb.show_score()
        self.ship.blitme()
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()

        self._check_fleet_edge()
        self.aliens.draw(self.screen)

        # 让最近绘制的屏幕可见
        pygame.display.flip()

    def _update_bullets(self):
        """更新子弹的位置并删除消失的子弹"""
        self.bullets.update()
        # 删除消失的子弹
        for bullet in self.bullets.copy():
            if bullet.rect.x > self.settings.screen_width:
                self.bullets.remove(bullet)
            self._check_bullet_alien_collision()

    def _update_aliens(self):
        """更新外星人的类"""
        self._create_fleet()
        self.aliens.update()

        #检测飞船和外星人的碰撞
        if pygame.sprite.spritecollideany(self.ship, self.aliens):
            if self.stats.ship_left > 0:
                #暂停
                sleep(0.5)
                self.stats.ship_left -= 1
                self.sb.prep_ships()
                #清空余下的外星人和子弹
                self.aliens.empty()
                self.bullets.empty()
            else:
                self.stats.game_active = False

    def _fire_bullet(self):
        """创建一颗子弹,并将其加入编组bullets中"""
        new_bullet = Bullet(self)
        self.bullets.add(new_bullet)

    def _check_events(self):
        """相应按键和鼠标事件"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                self._check_keydown_events(event)

            elif event.type == pygame.KEYUP:
                self._check_keyup_events(event)

    def _check_keydown_events(self, event):
        """响应按键"""
        if event.key == pygame.K_UP:
            # 向上移动角色
            self.ship.moving_up = True
        elif event.key == pygame.K_DOWN:
            # 向下移动角色
            self.ship.moving_down = True
        elif event.key == pygame.K_q:
            #按 q 退出
            sys.exit()
        elif event.key == pygame.K_SPACE:
            self._fire_bullet()

    def _check_keyup_events(self, event):
        """响应松开"""
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = False
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = False
        elif event.key == pygame.K_UP:
            self.ship.moving_up = False
        elif event.key == pygame.K_DOWN:
            self.ship.moving_down = False

    def run_game(self):
       """"开始游戏的主循环"""
       while True:
           self._check_events()
           if self.stats.game_active:
               self.ship.update()
               self._update_bullets()
               self._update_aliens()

           self._update_screen()

if __name__ == '__main__':
    ai = MyGame()
    ai.run_game()

 scoreboard.py

import pygame.font

class Scoreboard:
    """显示得分信息的类"""

    def __init__(self, ai_game):
        """初始化显示得分涉及的属性"""
        self.ai_game = ai_game
        self.screen = ai_game.screen
        self.screen_rect = self.screen.get_rect()
        self.stats = ai_game.stats
        self.settings = ai_game.settings

        #显示得分信息时使用的字体设置
        self.color = (251, 255, 242)
        self.font = pygame.font.SysFont("./STCAIYUN.ttf", 33)
        #准备初始得分图像
        self.prep_score()
        self.prep_ships()

    def prep_ships(self):
        """显示还余下多少飞船"""
        ship_left_str = str(self.stats.ship_left)
        self.ship_left_image = self.font.render("LEFT: " + ship_left_str,
            True, self.color)
        self.ship_left_rect = self.ship_left_image.get_rect()
        self.ship_left_rect.top, self.ship_left_rect.right = 10, 700

    def prep_score(self):
        """将得分转换为一幅渲染的图像"""
        rounded_score = round(self.stats.score, -1)
        score_str = "{:,}".format(rounded_score)
        self.score_image = self.font.render("SCORE: " + score_str,
            True, self.color)
        self.score_rect = self.score_image.get_rect()
        self.score_rect.bottom, self.score_rect.right = 480, 700

    def show_score(self):
        """在屏幕上显示得分"""
        self.screen.blit(self.score_image, self.score_rect)
        self.screen.blit(self.ship_left_image, self.ship_left_rect)

 settings.py

class Settings:
    """储存游戏《外星人入侵》中所有设置的类"""
    def __init__(self):
        """初始化游戏的设置"""
        # 屏幕设置
        self.screen_width = 700
        self.screen_height = 480

        #飞船设置
        self.ship_speed = 4.0
        self.ship_limit = 3

        #子弹设置
        self.bullet_speed = 5.0

    # def initialize_dynamic_settings(self):
        """游戏动态数据"""
        #飞船设置
        self.ship_left = 3
    
        #外星人设置
        self.alien_speed = 2.0
        self.alien_points = 50

ship.py

import pygame
from pygame.sprite import Sprite

class Ship(Sprite):
    """管理角色的类"""

    def __init__(self, ai_game):
        """初始化角色并设置其初始位置"""
        super().__init__()
        self.screen = ai_game.screen
        self.settings = ai_game.settings
        self.screen_rect = ai_game.screen.get_rect()

        #加载角色图像并获取其外接矩形
        self.image = pygame.image.load('image/me.png')
        self.rect = self.image.get_rect()

        #绘制到屏幕中央
        self.rect.midleft = self.screen_rect.midleft

        # 在飞船的属性 x,y 中储存小数值
        self.y = float(self.rect.y)

        #移动标志
        self.moving_up = False
        self.moving_down = False

    def update(self):
        """根据移动标志调整角色的位置"""
        #更新角色而不是rect对象的y值
        if self.moving_up and self.rect.top > 0:
            self.y += -1 * self.settings.ship_speed
        elif self.moving_down and self.rect.bottom < self.screen_rect.bottom:
            self.y += self.settings.ship_speed

        #更新rect对象
        self.rect.y = self.y

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

 来看看结果吧:


总结

学习pygame能让我们对如何管理一个项目有一个初认识,这对于初学者来说绝对是难得的体验,希望大家都能从中体会编程的乐趣。

看完了记得点个赞~ 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1000712.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号