欢迎来到“只读课堂”!
In [1]:
#这节课我们来实战python:Python游戏开发
In [2]:
#飞机大战
In [3]:
#以下是我们今天的课件以及项目规划,如果想直接进入课堂,就往下拉。
飞机大战
创建游戏是趣学语言的理想方式。看别人玩你编写的游戏让你很有满足感,而编写简单的游戏有助于你明白专业级游戏是怎么编写出来的。在阅读本章的过程中,请动手输入并运行代码,以明白各个代码块对整个游戏所做的贡献,并尝试不同的值和设置,这样你将对如何改进游戏的交互性有更深入的认识。
> 游戏《飞机大战》将包含很多不同的文件,因此请在你的系统中新建一个文件夹,并将其命名为
PlaneFight
。请务必将这个项目的所有文件都存储到这个文件夹中,这样相关的
import
语句才能正确地工作。
规划项目
开发大型项目时,做好规划后再动手编写项目很重要。规划可确保你不偏离轨道,从而提高项目成功的可能性。
> 在游戏《飞机大战》中,你可以控制着一架最初出现在屏幕底部中央的飞机。玩家可以使用箭头键左右移动飞机,还可使用空格键进行射击。游戏开始时,一群外星人出现在天空中,他们在屏幕中向下移动。玩家的任务是射杀这些外星人。只要有外星人撞到了玩家的飞机或到达了屏幕底部,游戏结束。
安装 Pygame
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
窗口。使用
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()
首先把管理事件的代码移到一个名为
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
另外把更新屏幕的代码移植到
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教程就到这了,欢迎下一次的收看!