Python学习笔记(九)--游戏项目(4)

创建外星人

在这里插入图片描述
我们将使用这个位图来作为外星人
下面我们来编写Alien

alien.py

import pygame
from pygame.sprite import Sprite

class Alien(Sprite):
    """初始化单个外星人的类"""
    
    def __init__(self, ai_settings, screen):
        """初始化外星人并设置其初始位置"""
        super(Alien, self).__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.height
        
        # 存储外星人的准确位置
        self.x = float(self.rect.x)
        
    def blitme(self):
        """在指定位置绘制外星人"""
        self.screen.blit(self.image, self.rect)

除位置不同外,这个类的大部分代码都与Ship类相似。每个外星人最初都位于屏幕左上角附近,我们将每个外星人的左边距都设置为外星人的宽度,并将上边距设置为外星人的高度。

同时我们要在alien_invasion.py中创建一个Alien类:

import pygame
from settings import Settings
from ship import Ship
from aline import Alien
import game_functions as gf
from pygame.sprite import Group
def run_game():
    # 初始化游戏并创建一个屏幕对象,设置和pygame
    pygame.init()
    # setting类
    ai_settings = Settings()

    screen = pygame.display.set_mode(
        (ai_settings.screen_width, ai_settings.screen_height))
    pygame.display.set_caption("Aline Invasion")

    # 创建一艘飞船
    ship = Ship(ai_settings, screen)

    # 创建一个用于存储子弹的编组
    bullets = Group()


    # 创建一个外星人
    alien = Alien(ai_settings, screen)
    
    # 游戏主循环
    while True:
        gf.check_events(ai_settings, screen, ship, bullets)
        ship.update()
        bullets.update()
        gf.update_screen(ai_settings, screen, ship, alien, bullets)
run_game()

同时要注意到
同时要注意到我们修改了gf函数的传参,所以我们继续去game_functions.py文件中修改函数update_screen

def update_screen(ai_settings,screen,ship, alien, bullets):
    # 每次循环时都重绘屏幕
    screen.fill(ai_settings.bg_color)

    # 在飞船和外星人后面重绘所有子弹
    for bullet in bullets.sprites():
        bullet.draw_bullet()

    ship.blitme()  # 重绘飞船
    alien.blitme() # 重绘外星人

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

在这里插入图片描述

创建一群外星人

要绘制一群外星人,需要确定一行能容纳多少个外星人以及要绘制多少行外星人。我们将首先计算外星人之间的水平间距,并创建一行外星人,再确定可用的垂直空间,并创建整群外星人。

为确定一行可容纳多少个外星人,我们来看看可用的水平空间有多大。屏幕宽度存储在ai_settings.screen_width中,但需要在屏幕两边都留下一定的边距,把它设置为外星人的宽度。

由于有两个边距,因此可用于放置外星人的水平空间为屏幕宽度减去外星人宽度的两倍:

available_space_x = ai_settings.screen_width – (2 * alien_width)

我们还需要在外星人之间留出一定的空间,即外星人宽度。因此,显示一个外星人所需的水平空间为外星人宽度的两倍:一个宽度用于放置外星人,另一个宽度为外星人右边的空白区域。
为确定一行可容纳多少个外星人,我们将可用空间除以外星人宽度的两倍:

number_aliens_x = available_space_x / (2 * alien_width)

我们将在创建外星人群时使用这些公式。
为创建一行外星人,首先在alien_invasion.py中创建一个名为aliens的空编组,用于存储全部外星人,再调用game_functions.py中创建外星人群的函数:

我们更改了之前外星人的代码:

import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
from pygame.sprite import Group
def run_game():
    # 初始化游戏并创建一个屏幕对象,设置和pygame
    pygame.init()
    # setting类
    ai_settings = Settings()

    screen = pygame.display.set_mode(
        (ai_settings.screen_width, ai_settings.screen_height))
    pygame.display.set_caption("Aline Invasion")

    # 创建一艘飞船
    ship = Ship(ai_settings, screen)

    # 创建一个用于存储子弹的编组
    bullets = Group()
    # 创建一个用于存储外星人的编组
    aliens = Group()
    # 创建外星人群
    gf.creat_fleet(ai_settings, screen, aliens)

    # 游戏主循环
    while True:
        gf.check_events(ai_settings, screen, ship, bullets)
        ship.update()
        bullets.update()
        gf.update_screen(ai_settings, screen, ship, aliens, bullets)
run_game()

由于我们不再在alien_invasion.py中直接创建外星人,因此无需在这个文件中导入Alien类。

我们创建了一个空编组,用于储存所有的外星人。接下来调用稍后编写的函数creat_fleet(),接着我们修改了update_screen()的调用,让它传递的参数中包括外星人编组

接着我们修改update_screen()
game_functions.py

def update_screen(ai_settings,screen,ship, aliens, bullets):
    # 每次循环时都重绘屏幕
    screen.fill(ai_settings.bg_color)

    # 在飞船和外星人后面重绘所有子弹
    for bullet in bullets.sprites():
        bullet.draw_bullet()

    ship.blitme()  # 重绘飞船
    
    aliens.draw(screen) # 重绘外星人

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

对编组调用draw()时,Pygame自动绘制编组的每个元素,绘制位置由元素的属性rect决定。在这里,aliens.draw(screen)在屏幕上绘制编组中的每个外星人。

下面我们来创建外星人群,我们把新函数create_fleet()放在在game_functions.py的末尾。注意我们要导入Alien类,需要在文件game_functions.py开头添加相应的import语句:

def create_fleet(ai_settngs, screen, aliens):
    """创建外星人群"""
    # 创建一个外星人,并计算一行可容纳多少个外星人
    # 外星人间距为外星人宽度
    alien = Alien(ai_settngs, screen)
    alien_width = alien.rect.width
    available_space_x = ai_settngs.screen_width - 2 * alien_width
    number_aliens_x = int(available_space_x / (2 * alien_width))

    # 创建第一行外星人
    for alien_number in range(number_aliens_x):# 创建一个外星人并将其加入当前行
        alien = Alien(ai_settngs, screen)
        alien.x = alien_width + 2 * alien_width * alien_number
        alien.rect.x = alien.x
        aliens.add(alien)

这些代码大都在前面详细介绍过。为放置外星人,我们需要知道外星人的宽度和高度,因此在执行计算前,我们先创建一个外星人。这个外星人不是外星人群的成员,因此没有将它加入到编组aliens中。我们从外星人的rect属性中获取外星人宽度,并将这个值存储到alien_width中,以免反复访问属性rect。我们计算可用于放置外星人的水平空间,以及其中可容纳多少个外星人。

接下来,我们编写了一个循环,它从零数到要创建的外星人数。在这个循环的主体中,我们创建一个新的外星人,并通过设置x坐标将其加入当前行。将每个外星人都往右推一个外星人的宽度。接下来,我们将外星人宽度乘以2,得到每个外星人占据的空间(其中包括其右边的空白区域),再据此计算当前外星人在当前行的位置。最后,我们将每个新创建的外星人都添加到编组aliens中。

在这里插入图片描述
现在的运行结果如上图所示。

重构create_fleet()

倘若我们创建了外星人群,也许应该让create_fleet()保持原样,但鉴于创建外星人的工作还未完成,我们稍微清理一下这个函数。下面是create_fleet()和两个新函数,get_number_aliens_x()create_alien()

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 create_alien(ai_settings, screen, aliens, alien_number):
    """创建一个外星人并将其放在当前行"""
    alien = Alien(ai_settings, screen)
    alien_width = alien.rect.width
    alien.x = alien_width + 2 * alien_width * alien_number
    alien.rect.x = alien.x
    aliens.add(alien)

def create_fleet(ai_settings, screen, aliens):
    """创建外星人群"""
    # 创建一个外星人,并计算一行可容纳多少个外星人
    # 外星人间距为外星人宽度
    alien = Alien(ai_settings, screen)
    alien_width = alien.rect.width
    number_aliens_x = get_number_aliens_x(ai_settings, alien_width)

    # 创建第一行外星人
    for alien_number in range(number_aliens_x):# 创建一个外星人并将其加入当前行
        create_alien(ai_settings, screen, aliens, alien_number)

函数get_number_aliens_x()的代码都来自create_fleet(),且未做任何修改。函数create_alien()的代码也都来自create_fleet(),且未做任何修改,只是使用刚创建的外星人来获取外星人宽度。

通过这样的重构,添加新行进而创建整群外星人将更容易。

后续内容详见下节博客。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chiaki_0ff

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值