PyGame快速⼊门:100⾏代码完成游戏开发
⽂章⽬录
简介
PyGame 是 SDL库的 Python包装器(wrapper)。SDL 是⼀个跨平台库,⽀持访问计算机多媒体硬件(声⾳,视频,输⼊等)。SDL ⾮常强⼤,但美中不⾜的是,它是基于 C语⾔的,⽽ C语⾔⽐较难懂,因此我们采⽤ PyGame!
在本⽂中,我们将介绍 PyGame的基本逻辑和冲突检测,以及如何在屏幕上绘图和将外部⽂件导⼊游戏中。
准备⼯作
执⾏ pip install pygame ,安装 Pygame库
新建⼀个 .py⽂件,然后输⼊如下代码takou中文
# 导⼊ pygame
import pygame
# 导⼊ pygame 中的⼀些常量
from pygame.locals import*
# 初始化所有导⼊的PyGame模块,在做其他操作之前必须调⽤该函数
pygame.init()
与其它 Python程序⼀样,我们⾸先导⼊想要使⽤的模块。这⾥,我们导⼊ pygame 和 pygame.locals ,后续我们将使⽤其中的⼀些常量。最后⼀⾏会初始化所有导⼊的 PyGame 模块,在做其它操作之前必须执⾏调⽤该函数!
基础对象
屏幕对象
⾸先,我们需要⼀张画布,我们称之为 “屏幕”,它是我们绘画的平台。为了创建⼀个屏幕,我们需要调⽤ pygame.display 中的
set_mode ⽅法,然后向 set_mode() 传递包含屏幕窗⼝宽度和⾼度的元组。
import pygame
from pygame.locals import*
pygame.init()
# 创建⼀个 800*600 的窗⼝
screen = pygame.display.set_mode((800,600))
# 设置窗⼝名称
pygame.display.set_caption("飞机⼤战")
运⾏上述代码,将会弹出⼀个窗⼝,然后⼜⽴即消失,⼀点都不酷嘛,对吧?
下⼀节,我们将介绍游戏的主循环,它将确保只有在我们给它正确的输⼊时程序才会退出。
游戏主循环
游戏主循环/事件循环是所有操作放⽣的地⽅。在游戏过程中,它不断更新游戏状态,渲染游戏画⾯和收集输⼊指令。创建循环时,需要确保我们有办法跳出循环,退出应⽤。
为此,我们将同时介绍⼀些基本的⽤户输⼊指令。所有的⽤户输⼊(和我们稍后提到的其它事件)都会进⼊ PyGame的事件队列,通过调⽤ () 可以访问该队列。这将返回⼀个包含队列⾥所有事件的列表,我们循环这个列表,并针对相应的事件类型做出反应。现在,我们只关⼼ KEYDOWN 和 QUIT 事件。
# ⽤户保证主循环运⾏的变量
running =True
# 主循环
while running:
# for 循环遍历事件队列
for event in ():
# 检测 KEYDOWN 事件:KEYDOWN 是 pygame.locals 中定义的常量
pe== KEYDOWN:
# 如果按下 ESC 那么主循环停⽌
if event.key == K_ESCAPE:
running =False
# 如果⽤户点击 X ,终⽌主循环
pe== QUIT:
running =False
将上述代码添加到之前的代码下,并运⾏。应该会看到⼀个空的窗⼝,只有你按下 ESC键 或者出发⼀个 QUIT 事件,否则这个窗⼝不会消失。
Surface 和 Rects
Surface 和 Rects 是 PyGame 中的基本构件。可以将 Surface 看作⼀张⽩纸,你可以在上⾯随意绘画。我们的屏幕对象也是⼀个Surface。它们可以包含图⽚。Rects 是 Surface 中矩形区域的表⽰。
让我们创建⼀个 50*50 像素的 Surface,然后给它涂⾊。由于屏幕是⿊⾊的,所以我们使⽤⽩⾊进⾏涂⾊,然后调⽤ get_rect() 在Surface 上得到⼀个矩形区域和 Surface 的 x 轴 和 y 轴。
# 创建 Surface 并设定它的长度和宽度
oracle中实例和数据库的关系surf = pygame.Surface((50,50))
# 设定 Surface 的颜⾊
surf.fill((255,255,255))
# 得到矩形区域及坐标
rect = _rect()
print(rect)
# <rect(0, 0, 50, 50)>
Blit 和 Flip
仅仅只是创建了 Surface 并不能在屏幕上看到它。为此我们需要将这个 Surface绘制(Bilt)到另⼀个 Surface上。Bilt是⼀个专业术语,意思就是绘图。你仅仅只能从⼀个 Surface Blit 到另⼀个 Surface 上,我们的屏幕对象就是⼀个 Surface 对象。以下是我们如何将 surf 画到屏幕上:
# 将 surf 画到屏幕 x:400 , y:300的坐标上
screen.blit(surf,(400,300))
# 更新屏幕
西安源代码软件技术服务有限公司pygame.display.flip()
blit() 有两个参数:要画的 Surface 和在 源Surface 上的坐标。此处我们使⽤屏幕的中⼼,但是当你运⾏代码是,你会发现我们的 surf 并没有出现在屏幕的中⼼。这是因为 blit() 是从左上⾓开始画 surf。
注意在 blit之后的 pygame.display.filp() 的调⽤。flip将会更新⾃上次 flip后的整个屏幕,两次 flip之间发⽣的修改都会在屏幕上显⽰。没有调⽤ flip() 那就什么也不会出现!
Sprites
什么是 Sprites ? 从编程术语来讲,Sprites 是屏幕上事物的⼆维表法。本质上来讲,Sprites就是⼀个图⽚。
Pygame提供⼀个叫做 Sprites 的基础类,他就是⽤来扩展的,可以包含想要在屏幕上呈现的对象⼀个或多个图形表⽰。我们将会扩展Sprite 类,这样可以使⽤它的内建⽅法。我们称这个新的对象为 Player。
Player将扩展 Sprite,现在只有两个属性:surd 和 rect,我们也会给 surf 涂⾊,如之前 Surface 例⼦,只是现在 Surface 属于 Player
class Player(pygame.sprite.Sprite):
def__init__(self):
python基础代码100例super(Player,self).__init__()
self.surf = pygame.Surface((25,25))
self.surf.fill((255,255,255))
< = _rect()
现在我们将上述代码整合在⼀起:
import pygame
from pygame.locals import*
pygame.init()
screen = pygame.display.set_mode((800,600))
pygame.display.set_caption("飞机⼤战")
class Player(pygame.sprite.Sprite):
def__init__(self):
super(Player, self).__init__()
self.surf = pygame.Surface((25,25))
self.surf.fill((255,255,255))
< = _rect()
player = Player()
running =True
while running:
for event in ():
pe== KEYDOWN:
if event.key == K_ESCAPE:
running =False
pe== QUIT:
running =False
# 将 surf 画到屏幕上
screen.blit(player.surf,(400,300))
pygame.display.flip()
运⾏上述代码,你会在屏幕中⼼看到⼀个⽩⾊的矩形
如果将 screen.blit(player.surf, (400, 300)) 改成 screen.blit(player.surf, ) , 你觉得会发⽣什么?rect 的前两个属性分别是rect 左上⾓的 x 和 y 轴坐标。当你将rect传递给blit,它会根据这个坐标画 surface。我们后续将使⽤它控制 player移动。帝国套用模板
⽤户输⼊
现在开始才是最有趣的部分,我们要把 player 变得可控制。PyGame中有⼀个事件⽅法 _pressed(),get_pressed()⽅法返回⼀个队列,其中包含了所有按键事件组成的元组,我们把它放在循环中,这样我们将获取每⼀帧的按键。
pressed_keys = _pressed()
现在我们写⼀个⽅法,接收上⾯那个元组,并根据按下键定义 sprite的⾏为,代码如下:
def update(self, keys):
if keys[K_UP]:
方法上加了bean注解if keys[K_DOWN]:
if keys[K_LEFT]:
if keys[K_RIGHT]:
K_UP,K_DOWN,K_LEFT,K_RIGHT 对应键盘上的 上,下,左,右 ⽅向键。我们判断这些键是否按下,如果它为真,那么我们使⽤move_ip() ⽅法朝响应的⽅向移动 rect。
现在你可以使⽤⽅向键移动矩形块了,也许你注意到了,你可以将矩形块移出屏幕,这可能并不是你想要的,所以我们需要在 update() ⽅法中添加⼀些逻辑,检测矩阵的坐标是移出了屏幕;如果移出了边界,那么就将它放回在边界上。
def update(self, keys):
if keys[K_UP]:
# 如果 rect 的顶部超出边界,那么将它放回边界上
if keys[K_DOWN]:
if keys[K_LEFT]:
if keys[K_RIGHT]:
现在我们添加⼀些敌⼈!
⾸先我们创建⼀个新的 sprite类,命名为 Enemy,依照创建 player的格式创建:
class Enemy(pygame.sprite.Sprite):
def__init__(self):
super(Enemy, self).__init__()
self.surf = pygame.Surface((25,25))
self.surf.fill((68,236,44))
< = _rect(x=random.randint(50,400), y=400)
self.speed = random.randint(5,15)
def update(self):
bottom <=0:
self.kill()
以上有⼏点需要说明。⾸先,当我们在 surface 上调⽤ get_rect 时,我们将 y 坐标设置为 400 , x 坐标为⼀个随机数,因为我们希望敌⼈随机出现。我们还是⽤ random 设置敌⼈的速度属性,这样敌⼈就有快有慢!
敌⼈的 update() ⽅法没有参数限制(我们不关⼼敌⼈的输⼊),只要让它们向着屏幕上⽅以⼀定的速度移动就可以了。update ⽅法最后有⼀个 if语句检测敌⼈是否通过了屏幕上⽅边界。当它们通过边界后,我们调⽤ Sprite的内建⽅法 kill()删除它们,这样它们就不会再被渲染出来。
kill不会释放被它们占⽤的内存,需要你确保不在引⽤它们,以便 Python的垃圾回收器回收。
Groups
PyGame 提供的另⼀个很有⽤的对象时 sprite的 Groups。诚如其名,是 Sprite的集合。为什么我们要使⽤ sprite.Groups ⽽不是列表呢?因为 sprite.Groups它有⼀些内建的⽅法,有助于解决碰撞和更新问题。
那现在就创建⼀个 Group,⽤来包含游戏中所有的 Sprite。我们也可以为敌⼈创建⼀个 Group。当我们调⽤ Sprite 的 kill() ⽅法时,会将其从所在的全部 Group 中删除。
enemies = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
# 将 player 添加到 all_sprites 中
all_sprites.add(player)
现在有了 all_sprites 的 group,我们接着改变对象渲染⽅式,只要渲染 group中的所有对象即可:
for entity in all_sprites:
screen.blit(entity.surf, )
现在,任何放到 all_sprites 中的对象对会被渲染出来。
⾃定义事件
现在我们为敌⼈创建了⼀个 sprite.Group,但是并没有实际的敌⼈。那怎样才能在屏幕上出现敌⼈呢?我们当然可以在刚开始的时候创建⼀堆的敌⼈,但是这样游戏玩不了⼏秒。
为此,我们创建⼀个⾃定义事件,它每隔⼏秒就会触发创建⼀批敌⼈。
创建⾃定义事件⼗分容易,只要命名即可:
ADDENEMY = pygame.USEREVENT +1
注意:⾃定义事件本质上就是整数常量,⼜因为⽐ USEREVENT ⼩的数值已经被内置函数占据,所以创建的⾃定义事件都要⽐
USEREVENT ⼤,这就是我们为什么设定它为 USEREVENT+1
定义好事件之后,我们需要将它插⼊事件队列中,因为整个游戏过程中都要创建它们,所有我们还要设置⼀个定时器,可以通过 PyGame 的 time() 实现
pygame.time.set_timer(ADDENEMY,250)
注意:set_timer() 只能⽤来将事件插⼊到 PyGame 事件队列中,不能做其它任何事情。
这⾏代码告诉 PyGame 每隔250毫秒触发⼀次 ADDENEMY 事件。这是在主游戏循环之外执⾏的,不过在整个游戏中都处于执⾏状态。现在我们添加⼀些监听事件的代码:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。