IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python从入门到实践13章答案 -> 正文阅读

[Python知识库]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能让我们对如何管理一个项目有一个初认识,这对于初学者来说绝对是难得的体验,希望大家都能从中体会编程的乐趣。

看完了记得点个赞~?

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 22:49:56  更:2022-07-04 22:50:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 12:00:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码