在树莓派和python社区,pygame是爱好者们常用的开发复古小游戏的工具,通过简单的python代码就可以给自己写个游戏啦。下面的截图是我写的飞机射击游戏:
移动、射击
吃到一个强力道具
Game Over
1 游戏主循环
首先通过pip把pygame库装好pip install pygame
;然后我们先写个最简单的游戏主体,如果你经常玩游戏的话,应该知道“帧”这个概念吧,我们的游戏主题就是一个循环结构,每一次循环都是在更新一个游戏帧的内容:
import pygame
from pygame.locals import (
RLEACCEL,
K_UP,
K_DOWN,
K_LEFT,
K_RIGHT,
K_ESCAPE,
KEYDOWN,
QUIT,
K_SPACE,
K_p,
JOYAXISMOTION,
JOYBALLMOTION,
JOYBUTTONDOWN,
JOYBUTTONUP,
JOYHATMOTION,
)
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
FPS = 60
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
pygame.display.flip()
clock.tick(FPS)
set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
这个方法创建了一个800X600的游戏屏幕,然后就进入一个主循环;每个主循环内会首先对可能的游戏事件进行处理,上面只对按下“ESC”按钮和关闭窗口进行了处理,就是把running置成False来终止循环;在循环的最后,pygame.display.flip()
这句代码会把屏幕的内容进行更新;此外我们设置了一个FPS变量,并在每个循环最后执行clock.tick(FPS)
,这是为了控制一下帧率,FPS为60就是说每秒刷新60帧,如果不加这个帧速控制,电脑执行的太快,游戏效果会太过“灵活”
现在执行这个程序,只会出现一个黑色的窗口,因为我们什么元素也没加呢;按下ESC可以关闭掉窗口
2 游戏背景
现在让我们先给游戏加上一个背景,因为是飞行设计游戏,我们找一幅太空背景的图片,然后在程序里加载并显示
import pygame
from pygame.locals import (
RLEACCEL,
K_UP,
K_DOWN,
K_LEFT,
K_RIGHT,
K_ESCAPE,
KEYDOWN,
QUIT,
K_SPACE,
K_p,
JOYAXISMOTION,
JOYBALLMOTION,
JOYBUTTONDOWN,
JOYBUTTONUP,
JOYHATMOTION,
)
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
FPS = 60
background = pygame.image.load('./images/blue.png') #加载背景图片
background_rect = background.get_rect()
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
screen.blit(background, (background_rect))#把背景图片显示在游戏屏幕上
pygame.display.flip()
clock.tick(FPS)
再次执行程序, 现在窗口不再是无聊的黑色了:
不过一个静态的背景还是太单调了,作为一个射击游戏,背景要有卷轴移动效果才行。我们通过一个小技巧来实现背景的卷轴效果。卷轴效果实际就是在每一帧里把背景图片向下面移动一点点,这样人眼就感觉背景动起来了,不过有个问题,只把这个背景图向下移动,屏幕上面的部分就没有图片覆盖又变成黑色了,因此我们采取用两张相同的背景图交替渲染的方式:
更新下代码:
import pygame
from pygame.locals import (
RLEACCEL,
K_UP,
K_DOWN,
K_LEFT,
K_RIGHT,
K_ESCAPE,
KEYDOWN,
QUIT,
K_SPACE,
K_p,
JOYAXISMOTION,
JOYBALLMOTION,
JOYBUTTONDOWN,
JOYBUTTONUP,
JOYHATMOTION,
)
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
FPS = 60
bgY1 = 0 #第一幅背景图的Y轴坐标
bgY2 = -SCREEN_HEIGHT #第二幅背景图的Y轴坐标
BACKGROUND_SCROLL_SPEED=0.5 #背景的移动速度
background = pygame.image.load('./images/blue.png')
background_rect = background.get_rect()
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
screen.blit(background, (0, bgY1)) #绘制第一幅背景图
screen.blit(background, (0, bgY2)) #绘制第二幅背景图, 刚开始的时候,第二幅背景图实际上绘制在窗口外面上方的
bgY1 += BACKGROUND_SCROLL_SPEED #更新两副背景图的Y轴坐标
bgY2 += BACKGROUND_SCROLL_SPEED
if bgY1 > SCREEN_HEIGHT:
bgY1 = -SCREEN_HEIGHT #当一副背景图完全向下离开窗口区域时,把它的Y轴坐标重新定位到最上方
if bgY2 > SCREEN_HEIGHT:
bgY2 = -SCREEN_HEIGHT
#screen.blit(background, (background_rect))
pygame.display.flip()
clock.tick(FPS)
看看效果:
3 添加主角飞机和敌人
现在可以创建我们要控制的主角了。首先需要了解"精灵"(Spirit)的概念,精灵是游戏开发中相对高层的抽象,每个具体的游戏对象都是一个精灵实例,一个精灵其实就是一个图形块,我们需要给它填充图形、赋予行为。
先定义一个Player类来代表玩家, 它继承自Sprite类。我们给它加载一副飞机图片:
player_img = pygame.transform.scale(pygame.image.load('./images/playerShip1_orange.png'),(61,41)) #加载玩家飞机的图片并调整大小
class Player(pygame.sprite.Sprite): #定义Player类, 继承自Sprite类
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = player_img
self.rect = self.image.get_rect()
self.rect.centerx = int(SCREEN_WIDTH/2) #初始位置
self.rect.bottom = SCREEN_HEIGHT
实例化这个Player对象,并且加到一个Sprite队列里; 在游戏主循环内把所有的Sprite对象渲染在背景图之上
import pygame
from pygame.locals import (
RLEACCEL,
K_UP,
K_DOWN,
K_LEFT,
K_RIGHT,
K_ESCAPE,
KEYDOWN,
QUIT,
K_SPACE,
K_p,
JOYAXISMOTION,
JOYBALLMOTION,
JOYBUTTONDOWN,
JOYBUTTONUP,
JOYHATMOTION,
)
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
FPS = 60
bgY1 = 0
bgY2 = -SCREEN_HEIGHT
BACKGROUND_SCROLL_SPEED=0.5
background = pygame.image.load('./images/blue.png')
background_rect = background.get_rect()
player_img = pygame.transform.scale(pygame.image.load('./images/playerShip1_orange.png'),(61,41)) #加载玩家飞机的图片并调整大小
class Player(pygame.sprite.Sprite): #定义Player类, 继承自Sprite类
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = player_img
self.rect = self.image.get_rect()
self.rect.centerx = int(SCREEN_WIDTH/2) #初始位置
self.rect.bottom = SCREEN_HEIGHT
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
player = Player() #实例化玩家飞机
all_sprites = pygame.sprite.Group() #存放所有精灵的引用
all_sprites.add(player)
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
screen.blit(background, (0, bgY1))
screen.blit(background, (0, bgY2))
bgY1 += BACKGROUND_SCROLL_SPEED
bgY2 += BACKGROUND_SCROLL_SPEED
if bgY1 > SCREEN_HEIGHT:
bgY1 = -SCREEN_HEIGHT
if bgY2 > SCREEN_HEIGHT:
bgY2 = -SCREEN_HEIGHT
all_sprites.draw(screen) #在背景之上渲染所有精灵
pygame.display.flip()
clock.tick(FPS)
现在运行程序,可以看到玩家飞机出现在屏幕正下方。现在给飞机添加动作行为, 我们计划用上下左右的箭头来控制飞机各方向移动,在PyGame中,小键盘的上下左右按键对应的了K_UP、K_DOWN、K_LEFT和K_RIGHT事件,我们在Player类中添加update方法,根据事件类型进行相应的处理;同时在游戏主循环内我们实时更新玩家飞机的动作:
import pygame
from pygame.locals import (
RLEACCEL,
K_UP,
K_DOWN,
K_LEFT,
K_RIGHT,
K_ESCAPE,
KEYDOWN,
QUIT,
K_SPACE,
K_p,
JOYAXISMOTION,
JOYBALLMOTION,
JOYBUTTONDOWN,
JOYBUTTONUP,