天天看点

Python高级第2课——飞机大战(只读课堂)

欢迎来到“只读课堂”!

In [1]:

#这节课我们来实战python:Python游戏开发
           

In [2]:

#飞机大战
           

In [3]:

#以下是我们今天的课件以及项目规划,如果想直接进入课堂,就往下拉。
           

飞机大战

创建游戏是趣学语言的理想方式。看别人玩你编写的游戏让你很有满足感,而编写简单的游戏有助于你明白专业级游戏是怎么编写出来的。在阅读本章的过程中,请动手输入并运行代码,以明白各个代码块对整个游戏所做的贡献,并尝试不同的值和设置,这样你将对如何改进游戏的交互性有更深入的认识。

> 游戏《飞机大战》将包含很多不同的文件,因此请在你的系统中新建一个文件夹,并将其命名为

PlaneFight

。请务必将这个项目的所有文件都存储到这个文件夹中,这样相关的

import

语句才能正确地工作。

规划项目

开发大型项目时,做好规划后再动手编写项目很重要。规划可确保你不偏离轨道,从而提高项目成功的可能性。

> 在游戏《飞机大战》中,你可以控制着一架最初出现在屏幕底部中央的飞机。玩家可以使用箭头键左右移动飞机,还可使用空格键进行射击。游戏开始时,一群外星人出现在天空中,他们在屏幕中向下移动。玩家的任务是射杀这些外星人。只要有外星人撞到了玩家的飞机或到达了屏幕底部,游戏结束。

安装

Pygame

1. 手动安装

- 先下载

whl

文件

> 下载地址: https://www.lfd.uci.edu/~gohlke/pythonlibs/#pygame

- 手动安装

pip install pygame‑1.9.3‑cp36‑cp36m‑win_amd64.whl

2. 

pip

安装

pip3 install pygame

> 以上可以使用Linux和Windows系统

Linux系统也可以使用

sudo apt install python3-pygame

 安装Python3的版本。

检测安装

进入Python环境,执行:

```python

>>> import pygame

>>>

```

如果没有任何输出,就说明Python导入了

Pygame

开始游戏项目

首先创建一个空的

Pygame

窗口,供后面用来绘制游戏元素,如飞机和外星人。我们还将让这个游戏响应用户输入、设置背景色以及加载飞机图像。

创建

Pygame

窗口以及响应用户输入

首先,我们创建一个空的

Pygame

窗口。使用

Pygame

编写的游戏的基本结构如下:

```python

import sys

import pygame

def run_game():

初始化游戏并创建一个屏幕对象

pygame.init()

screen = pygame.display.set_mode((800, 600))

pygame.display.set_caption('PlaneFight')

开始游戏主循环

while True:

监控键盘和鼠标事件

for event in pygame.event.get():

if event.type == pygame.QUIT:

sys.exit()

让最近绘制的屏幕可见

pygame.display.flip()

run_game()

```

我们导入了模块

sys

pygame

。模块

pygame

包含开发游戏所需的功能。玩家退出时,我们将使用模块

sys

来退出游戏。

开头是函数

run_game()

 ,代码行

pygame.init()

初始化背景设置,让

Pygame

能够正确地工作。

调用

pygame.display.set_mode()

来创建一个名为

screen

的显示窗口,这个游戏的所有图形元素都将在其中绘制。实参

(800, 600)

是一个元组,指定了游戏窗口的尺寸。通过将这些尺寸值传递给

pygame.display.set_mode()

,我们创建了一个宽800像素、高600像素的游戏窗口(你可以根据自己的显示器尺寸调整这些值)。

对象

screen

是一个

surface

。在

Pygame

中,

surface

是屏幕的一部分,用于显示游戏元素。在这个游戏中,每个元素(如外星人或飞机)都是一个

surface

display.set_mode()

返回的

surface

表示整个游戏窗口。我们激活游戏的动画循环后,每经过一次循环都将自动重绘这个

surface

为访问

Pygame

检测到的事件,我们使用方法

pygame.event.get()

。所有键盘和鼠标事件都将促使for循环运行。在这个循环中,我们将编写一系列的

if

语句来检测并响应特定的事件。例如,玩家单击游戏窗口的关闭按钮时,将检测到

pygame.QUIT

事件,而我们调用

sys.exit()

来退出游戏。

调用了

pygame.display.flip()

,命令

Pygame

让最近绘制的屏幕可见。在这里,它在每次执行

while

循环时都绘制一个空屏幕,并擦去旧屏幕,使得只有新屏幕可见。在我们移动游戏元素时,

pygame.display.flip()

将不断更新屏幕,以显示元素的新位置,并在原来的位置隐藏元素,从而营造平滑移动的效果。

设置背景色

Pygame

默认创建一个黑色屏幕,太乏味了。下面来将背景设置为另一种颜色:

```python

import sys

import pygame

def run_game():

初始化游戏并创建一个屏幕对象

pygame.init()

screen = pygame.display.set_mode((800, 600))

pygame.display.set_caption('PlaneFight')

设置背景色

bg_color = (255, 255 ,255) # R G B 0-255

开始游戏主循环

while True:

监控键盘和鼠标事件

for event in pygame.event.get():

if event.type == pygame.QUIT:

sys.exit()

每次循环都重绘屏幕

screen.fill(bg_color)

让最近绘制的屏幕可见

pygame.display.flip()

run_game()

```

Pygame

中,颜色是以

RGB

值指定的。这种颜色由红色、绿色和蓝色值组成,其中每个值的可能取值范围都为0~255。颜色值(255, 0, 0)表示红色,(0, 255, 0)表示绿色,而(0, 0, 255)表示蓝色。通过组合不同的

RGB

值,可创建1600万种颜色。在颜色值(230, 230, 230)中,红色、蓝色和绿色量相同,它将背景设置为一种浅灰色。

我们调用方法

screen.fill()

,用背景色填充屏幕;这个方法只接受一个实参:一种颜色。

创建游戏设置类/重构代码

每次给游戏添加新功能时,通常也将引入一些新设置。下面来编写一个名为

settings

的模块,其中包含一个名为

Settings

的类,用于将所有设置存储在一个地方,以免在代码中到处添加设置。这样,我们就能传递一个设置对象,而不是众多不同的设置。另外,这让函数调用更简单,且在项目增大时修改游戏的外观更容易:要修改游戏,只需修改

settings.py

中的一些值,而无需查找散布在文件中的不同设置。

```python

class Settings():

'''存储《飞机大战》的所有设置的类'''

def init(self):

'''初始化游戏的设置'''

屏幕设置

self.screen_width = 800

self.screen_height = 600

self.bg_color = (230, 230, 230)

planefight.py

文件下面是这样的:

```python

import sys

import pygame

from settings import Settings

def run_game():

初始化游戏并创建一个屏幕对象

pygame.init()

game_settings = Settings()

screen = pygame.display.set_mode((game_settings.screen_width, game_settings.screen_height))

pygame.display.set_caption('flygame')

设置背景色

bg_color = (230, 230 ,230)

开始游戏主循环

while True:

监控键盘和鼠标事件

for event in pygame.event.get():

if event.type == pygame.QUIT:

sys.exit()

每次循环都重绘屏幕

screen.fill(game_settings.bg_color)

让最近绘制的屏幕可见

pygame.display.flip()

run_game()

添加飞机图像

在游戏中几乎可以使用任何类型的图像文件,但使用位图(

.bmp

)文件最为简单,因为

Pygame

默认加载位图。

下面将飞机加入到游戏中。为了在屏幕上绘制玩家的飞机,我们将加载一幅图像,再使用

Pygame

方法

blit()

绘制它。

当选择用于表示飞机的图像后,需要将其显示到屏幕上。我们将创建一个名为

plane

的模块,其中包含

Plane

类,它负责管理飞机的大部分行为。

```python

import pygame

class Plane():

def init(self, screen):

'''初始化飞机并设置其初始位置'''

self.screen = screen

加载飞机图像并获取其外接矩形

self.image = pygame.image.load('images/ship.bmp')

self.rect = self.image.get_rect()

self.screen_rect = screen.get_rect

将每架新飞机放在屏幕底部中央

self.rect.centerx = self.screen_rect.centerx

self.rect.bottom = self.screen_rect.bottom

def blitme(self):

"""在指定位置绘制飞机"""

将背景图画上去,blit是个重要函数,第一个参数为一个Surface对象,第二个为左上角位置。

self.screen.blit(self.image, self.rect)

重构代码

在大型项目中,经常需要在添加新代码前重构既有代码。重构旨在简化既有代码的结构,使其更容易扩展。我们将创建一个名为

gamefunctions

的新模块,它将存储大量让游戏《飞机大战》运行的函数。通过创建模块

gamefunctions

,可避免

planefight.py

太长,并使其逻辑更容易理解。

函数

check_events()

首先把管理事件的代码移到一个名为

check_events()

的函数中,以简化

run_game()

并隔离事件管理循环。

```python

import sys

import pygame

def check_events():

监控键盘和鼠标事件

for event in pygame.event.get():

if event.type == pygame.QUIT:

sys.exit()

函数

update_screen

另外把更新屏幕的代码移植到

update_screen

的函数中。也在

gamefunctions

文件里面。

```python

import sys

import pygame

def update_screen(game_settings, screen, plane):

"""更新屏幕上的图像,并切换到新屏幕"""

每次循环时都重绘屏幕

screen.fill(game_settings.bg_color)

plane.blitme()

让最近绘制的屏幕可见

pygame.display.flip()

这两个函数重写后主函数就是这样了:

```python

import sys

import pygame

from settings import Settings

from plane import Plane

import gamefunctions as gf

def run_game():

初始化游戏并创建一个屏幕对象

pygame.init()

game_settings = Settings()

screen = pygame.display.set_mode((game_settings.screen_width, game_settings.screen_height))

pygame.display.set_caption('PlaneFight')

创建一艘飞船

plane = Plane(screen)

开始游戏主循环

while True:

gf.check_events()

gf.update_screen(game_settings, screen, plane)

run_game()

In [4]:

#光看课件是没有用的。
           

In [5]:

#下面我们来正式开始讲课。
           

In [6]:

#今天我只能给大家讲一些。
           

In [7]:

#这节课我们来实现“控制着一脚最初出现在屏幕底部中央的飞机”。
           

In [8]:

#如果没有“Pygame”模块,那么就去安装。
           

In [9]:

pip install pygame
           
The following command must be run outside of the IPython shell:

    $ pip install pygame

The Python package manager (pip) can only be used from outside of IPython.
Please reissue the `pip` command in a separate terminal or command prompt.

See the Python documentation for more informations on how to install packages:

    https://docs.python.org/3/installing/
           

In [10]:

#主要涉及到重构代码
           

In [11]:

#你要玩飞机大战,一定要一个窗口是吧
           

In [12]:

import pygame
           

In [13]:

import sys
           

In [15]:

def run_game():
    pygame.init()
    screen = pygame.display.set_mode((800, 600))
    pygame.display.set_caption('PlaneFight')

    while True:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

        pygame.display.flip()

run_game()
           
An exception has occurred, use %tb to see the full traceback.

SystemExit
           
C:\ProgramData\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py:2918: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
  warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
           

In [1]:

#刚刚我们已经运行了一遍。
           

In [2]:

#运行的结果是会产生一个窗口。
           

下面我来详细讲一下各个代码。

In [3]:

#前面两个import就是导入了sys和pygame模块,我们后面才可以使用。
           

In [4]:

#def是初始化然后创建一个屏幕(run game)
           

In [5]:

#刚刚出现的一个屏幕就是用pygame.init()产生的。
           

In [6]:

#screen = pygame.display.set_mode((800, 600))就是设定窗口大小
           

In [7]:

#800是长度,600是高。
           

In [8]:

#如果你想变小屏幕,就可以该车成400,300
           

In [9]:

#while True是一只循环,是让程序一直死循环
           

In [10]:

#event.get可以监控到窗口里所有的事件
           

In [11]:

#sys.exit()是表示如果不按Esc那个窗口是退不掉的。
           

In [12]:

#我们再来运行试试
           

In [15]:

import sys 

import pygame 

def run_game():
    pygame.init()
    screen = pygame.display.set_mode((800, 600))
    pygame.display.set_caption('PlaneFight')

    while True:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

        pygame.display.flip()

run_game()
           
An exception has occurred, use %tb to see the full traceback.

SystemExit
           
C:\ProgramData\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py:2918: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
  warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
           

In [16]:

#我们可以看到运行窗口是上面这个样子的。
           

In [17]:

#pygame.display.flip就是绘制新的图片,也就是刷新。
           

In [18]:

#这句话的意思就是全局更新屏幕。
           

设置背景颜色

In [2]:

import sys 

import pygame 

def run_game():
    pygame.init()
    screen = pygame.display.set_mode((800, 600))
    pygame.display.set_caption('PlaneFight')

    bg_color = (255, 255 ,255)
    while True:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

        screen.fill(bg_color)


        pygame.display.flip()

run_game()
           
An exception has occurred, use %tb to see the full traceback.

SystemExit
           
C:\ProgramData\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py:2918: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
  warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
           

In [3]:

#通过以上代码我们就把窗口的背景颜色由黑色改为了白色。
           

In [4]:

#R是red的缩写,就是红色
           

In [5]:

#G是green的缩写,就是绿色
           

In [6]:

#B是blue的缩写,就是蓝色
           

In [7]:

#0-250的数值就是从黑到白,数值越接近250就越白。
           

In [10]:

import sys 

import pygame 

def run_game():
    pygame.init()
    screen = pygame.display.set_mode((800, 600))
    pygame.display.set_caption('PlaneFight')

    bg_color = (0, 255 ,0)
    while True:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

        screen.fill(bg_color)


        pygame.display.flip()

run_game()
           
An exception has occurred, use %tb to see the full traceback.

SystemExit
           
C:\ProgramData\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py:2918: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
  warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
           

In [8]:

#如果把数值改一下,改成0,250,0,那么就是绿色。
           

In [11]:

#如果改成50,150,200,会变成下面这种颜色:
           

In [12]:

import sys 

import pygame 

def run_game():
    pygame.init()
    screen = pygame.display.set_mode((800, 600))
    pygame.display.set_caption('PlaneFight')

    bg_color = (50, 150 ,200)
    while True:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

        screen.fill(bg_color)


        pygame.display.flip()

run_game()
           
An exception has occurred, use %tb to see the full traceback.

SystemExit
           
C:\ProgramData\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py:2918: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
  warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
           

In [13]:

#这款蓝色相对来说好看一些。
           

In [14]:

#screen的意思就是我们的屏幕(窗口)
           

In [15]:

#在后面可以改填充之类的surface(图层),可以重复叠加,还可以添加小的图像。
           

In [16]:

#注意,在pygame里面图形都是矩形的。
           

创建游戏设置类

In [17]:

#这里我们为了方便起见,是不再添加注释了的,要看注释的向上拉去看课件。
           

In [18]:

#建议再建一个文件,叫做"Settings"。
           

In [19]:

#它会储存关于所有窗口的设置。
           

In [20]:

import sys 

import pygame 

from settings import Settings

def run_game():
    
    pygame.init()
    game_settings = Settings()
    screen = pygame.display.set_mode((game_settings.screen_width, game_settings.screen_height))
    pygame.display.set_caption('flygame')

    
    bg_color = (230, 230 ,230)
    
    while True:

        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

        
        screen.fill(game_settings.bg_color)

        
        pygame.display.flip()

run_game()
           
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-20-1dc072ba7479> in <module>()
      3 import pygame
      4 
----> 5 from settings import Settings
      6 
      7 def run_game():

ModuleNotFoundError: No module named 'settings'
           

In [21]:

#同学们,这里记得装settings模块
           

In [22]:

pip install settings
           
The following command must be run outside of the IPython shell:

    $ pip install settings

The Python package manager (pip) can only be used from outside of IPython.
Please reissue the `pip` command in a separate terminal or command prompt.

See the Python documentation for more informations on how to install packages:

    https://docs.python.org/3/installing/
           

In [23]:

#pygame.init()就是实例化
           

添加飞机图像

In [24]:

import pygame

class Plane():

    def __init__(self, screen):
        '''初始化飞机并设置其初始位置'''
        self.screen = screen

        self.image = pygame.image.load('images/ship.bmp')
        self.rect = self.image.get_rect()
        self.screen_rect = screen.get_rect

        self.rect.centerx = self.screen_rect.centerx 
        self.rect.bottom = self.screen_rect.bottom

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

In [25]:

#建议再创建一个文件"plane"来储存。
           

好了,我们这节课就先暂时讲到这里!

本次只读课堂的python教程就到这了,欢迎下一次的收看!