python应用篇之外星人入侵项目——外星人(上)

Posted 一计之长

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python应用篇之外星人入侵项目——外星人(上)相关的知识,希望对你有一定的参考价值。

前言

  我们之前通过四篇文章给大家详细介绍了武装飞船的相关内容。这是我们外星人入侵项目的第一个环节,首先要有飞船,并且能够射出子弹。并且初步给大家介绍了游戏开发过程中计划的制定;使用pygame编写游戏的基本框架;包括设置背景色的方式、将设置存储在可供游戏的各个部分访问的独立类中的具体实现方式。另外在屏幕上绘制了图像、让玩家控制游戏元素的移动;创建自动移动的元素,在屏幕中间向上飞驰的子弹,最后删除不再需要的对象;如何定期对项目的代码撒进行重构,让我们代码耦合性较低,代码利用率高。为我们接下来功能的实现提供方便。

外星人需求分析

  当我们开发较大的项目的时候,我们每进入开发阶段就应该清楚我们相应的开发计划,要搞清楚接下来要通过编写代码来完成哪些任务都是不错的想法的主意。我们接下来的具体步骤如下:

   研究既有代码,确实实现新功能前是否要进行重构
  在屏幕上左上角添加一个外星人,并指定合适的边距
  根据第一个外星人的边距和屏幕上尺寸计算屏幕上可容纳多少个外星人,我们将编写一个循环来创建一些列外星人,这些外星人填满了屏幕的上半部分。
  让外星人群向两边和下方移动,直到外星人被全部击落,有外星人撞到飞船,或有外星人抵达屏幕低端。如果整群外星人都被击落,我们将再创建一群外星人。如果有外星人撞到了飞船或抵达屏幕低端,我们将销毁飞船并创建一群外星人。
  限制玩家可用的飞船数量,配给的飞船用完后,游戏结束。

  本文将在实现功能的同时完善这个计划,但就目前而言,这个思路足以支撑我们去实现该需求。
  在给我们项目添加新功能前,还应审核既有代码。每进入一个新阶段,通常项目都会更复杂,因此,最好对混乱或低效的代码进行清理。
  我们在开发的时候不断地重构,因此,当需要做的清理工作不多,但每次为测试新功能而运行这个游戏时,都必须使用鼠标来关闭它,这对于一个资深的程序员来说也太业余了。下面我们通过一行代码让它更加的专业:

import sys
import pygame
from bullet import Bullet
def check_keydown_events(event, ai_settings, screen, ship, bullets):
    """响应按键"""
    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:
        # 创建一颗子弹,并将其加入到编组bullets中
        fire_bullet(ai_settings, screen, ship, bullets)
    elif event.key == pygame.K_q:
        sys.exit()
def fire_bullet(ai_settings, screen, ship, bullets):
    """如果还没有到达限制,就发射一颗子弹"""
    if len(bullets) < ai_settings.bullets_allowed:
        new_bullet = Bullet(ai_settings, screen, ship)
        bullets.add(new_bullet)
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_events(ai_settings, screen, ship, 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)

def update_screen(ai_settings, screen, ship, bullets):
    """更新屏幕上的图像,并切换到新屏幕"""
    # 每次循环时都重绘屏幕
    screen.fill(ai_settings.bg_color)
    # 在飞船和外星人后面重绘所有子弹
    for bullet in bullets.sprites():
        bullet.draw_bullet()
    ship.blitme()
    # 让最近绘制的屏幕可见
    pygame.display.flip()
def update_bullets(bullets):
    """更新子弹的位置,并删除已消失的子弹"""
    # 更新子弹的位置
    bullets.update()
    # 删除已消失的子弹
    for bullet in bullets.copy():
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)

  在check_keydown_events()中,我们添加了一个代码块,以便在玩家按Q时结束游戏。这样的修改很安全,因为Q键离箭头和空格键很远,玩家不小心按Q键而导致游戏结束的可能性不大。现在测试时可按Q关闭游戏,而无需使用鼠标来关闭窗口了。具体如下:

创建第一个外星人

  在屏幕上放置外星人与放置飞船其实是差不多的。每个外星人的行为都由Alien类控制,我们将像创建Ship类那样创建这个类。处于简化考虑,我们也使用位图来表示外星人。这个资料大家在下载飞船的时候应该一起都下载好了,相应的外星人图片如下:

1、创建Alien类

  接下来,我们实现Alien类的实现。我们在创建alien.py之间首先要搞清楚项目层级关系,即我们在代码哪里创建其类,并且将alien.bmp文件放到/images下。具体创建位置如下:

  接下来我们实现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.rect.height
        # 存储外星人的准确位置
        self.x = float(self.rect.x)
    def blitme(self):
        """在指定位置绘制外星人"""
        self.screen.blit(self.image, self.rect)

  我们从代码编写情况来看,此代码与飞船Ship类实现除了位置不同之外,其他代码还是很类似。每个外星人最初都位于屏幕左上角附近,我们将每个外星人的左边距都设置为外星人的宽度,并将上边距设置为外星人的高度。

2、创建Alien实例

  下面在alien_invasion.py中创建一个Alien实例:

import sys
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
from pygame.sprite import Group
from alien import Alien

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("Alian 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()
        gf.update_bullets(bullets)
        gf.update_screen(ai_settings, screen, ship, alien, bullets)
run_game()

  在这里,我们导入了新创建的Alien类,并在进入主while循环前创建了一个Alien实例。我们没有修改外星人的位置,因此,该while循环没有任何新的东西,但我们修改了对update_screen()的调用,传递了一个外星人的实例。

3、让外星人出现在屏幕上

  为了让外星人出现在屏幕上,我们在update_screen()中调用其方法blitme()即可:

import sys
import pygame
from bullet import Bullet
def check_keydown_events(event, ai_settings, screen, ship, bullets):
    """响应按键"""
    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:
        # 创建一颗子弹,并将其加入到编组bullets中
        fire_bullet(ai_settings, screen, ship, bullets)
    elif event.key == pygame.K_q:
        sys.exit()
def fire_bullet(ai_settings, screen, ship, bullets):
    """如果还没有到达限制,就发射一颗子弹"""
    if len(bullets) < ai_settings.bullets_allowed:
        new_bullet = Bullet(ai_settings, screen, ship)
        bullets.add(new_bullet)
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_events(ai_settings, screen, ship, 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)

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()
def update_bullets(bullets):
    """更新子弹的位置,并删除已消失的子弹"""
    # 更新子弹的位置
    bullets.update()
    # 删除已消失的子弹
    for bullet in bullets.copy():
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)

  我们先绘制飞船和子弹,在绘制外星人,让外星人在屏幕上位于最前面,具体实现效果如下:

  第一个外星人正确地出现后,下面来编写绘制一群外星人的代码。

总结

  我们之前通过四篇文章给大家详细介绍了武装飞船的相关内容。这是我们外星人入侵项目的第一个环节,首先要有飞船,并且能够射出子弹。并且初步给大家介绍了游戏开发过程中计划的制定;使用pygame编写游戏的基本框架;包括设置背景色的方式、将设置存储在可供游戏的各个部分访问的独立类中的具体实现方式。另外在屏幕上绘制了图像、让玩家控制游戏元素的移动;创建自动移动的元素,在屏幕中间向上飞驰的子弹,最后删除不再需要的对象;如何定期对项目的代码撒进行重构,让我们代码耦合性较低,代码利用率高。为我们接下来功能的实现提供方便。本文给大家介绍了外星人创建的思路,然后创建了第一个外星人,包括创建Alien类、创建Alien实例以及让外星人出现在屏幕上。为了让大家更好的吸收项目所用到的知识点,我们每一篇文章只给大家实现《外星人入侵》的一个功能,所以,希望大家能够仔细阅读,认真跟着写代码,理解其中的深入含义,吧这个项目的价值发挥到最大。其实这个项目已经很典型,代码到处都是,但是,如果你只是简单的粘贴复制,对你知识的学习没有任何的价值,你还是得跟着过一遍,然后要知道每行代码的含义或者是用到了前面我们介绍的哪一块知识点,只有这样,这个项目才会发挥不一样的价值,希望大家认真学习,把基础知识打扎实一点。Python是一门注重实际操作的语言,它是众多编程语言中最简单,也是最好入门的。当你把这门语言学会了,再去学习java、go以及C语言就比较简单了。当然,Python也是一门热门语言,对于人工智能的实现有着很大的帮助,因此,值得大家花时间去学习。生命不息,奋斗不止,我们每天努力,好好学习,不断提高自己的能力,相信自己一定会学有所获。加油!!!临近中秋,提前祝大家中秋快乐!阖家欢乐!!!

以上是关于python应用篇之外星人入侵项目——外星人(上)的主要内容,如果未能解决你的问题,请参考以下文章

python应用篇之外星人入侵项目——记分(上)

python应用篇之外星人入侵项目——外星人(中)

python应用篇之外星人入侵项目——武装飞船(下)

python应用篇之数据可视化——生成数据(上)

pygame外星人入侵

简单的Python项目——《外星人入侵》(关键词:pygame,类,函数,编组,图像)