Pygame是一组专门编写游戏的python模块,具有高度的可移植性。下面将介绍Pygame中提供的方法,实现一个简单的飞机大战小demo,扫描下方二维码关注我的公众号中回复“飞机大战”,即可获取demo的代码地址、本demo素材(彩色图片素材、微信经典黑白素材、音效)
本文主要内容
- 通过例子示范窗口绘制及其所需函数简要说明
- 图片移动、通过用户事件移动图片及所需函数简要说明
- 碰撞检测及所需函数简要说明
- 音频加载及所需函数简要说明
- 成果展示
环境
模块安装
pip install pygame
游戏窗口建立及所需函数简要说明
import os
import time
import pygame
SCREEN_WIDTH = 500
SCREEN_HEIGHT = 250
IMG_PATH = os.path.join(os.getcwd(), "img")
def main():
pygame.display.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("python小demo 飞机大战")
pygame.display.set_icon(pygame.image.load(os.path.join(IMG_PATH, "icon.jpg")))
background = pygame.image.load(os.path.join(IMG_PATH, "test_bj.png"))
while True:
screen.blit(background, (0, 0))
pygame.display.update()
time.sleep(0.02)
if __name__ == "__main__":
main()
查看下效果:
x、y是我手动绘制的,让大家可以更加直观的看到窗口坐标轴情况
所需函数简要说明
display.init() -> None
display.set_mode(size=(0, 0), flags=0, depth=0, display=0, vsync=0) -> Surface
display.set_caption(title, icontitle=None) -> None
display.set_icon(Surface) -> None
display.update(rectangle=None) -> None
display.update(rectangle_list) -> None
image.load(filename) -> Surface
Surface.blit(source, dest, area=None, special_flags=0) -> Rect
Surface.get_rect(**kwargs) -> Rect
图片移动、通过用户事件移动图片 上面代码已经能够建立游戏窗口和加载背景图,现在创建英雄,通过改变坐标实现移动
import os
import time
import pygame
SCREEN_WIDTH = 500
SCREEN_HEIGHT = 250
IMG_PATH = os.path.join(os.getcwd(), "img")
class HeroPlane(object):
def __init__(self):
super(HeroPlane, self).__init__()
self.image = pygame.image.load(os.path.join(IMG_PATH, "hero_show_1.png"))
self.rect = self.image.get_rect()
self.rect.x = 0
self.rect.y = int(SCREEN_HEIGHT - self.rect.height) / 2
self.is_running = True
self.bullet_list = pygame.sprite.Group()
self.last_time = time.time()
def move_level(self, level):
add_level = self.rect.x + level
if 0 <= add_level <= SCREEN_WIDTH - self.rect.width:
self.rect.x = add_level
elif add_level < 0:
self.rect.x = 0
elif add_level > SCREEN_WIDTH - self.rect.width:
self.rect.x = SCREEN_WIDTH - self.rect.width
def move_vertical(self, vertical):
add_vertical = self.rect.y + vertical
if 0 <= add_vertical <= SCREEN_HEIGHT - self.rect.height:
self.rect.y = add_vertical
elif add_vertical < 0:
self.rect.y = 0
elif add_vertical > SCREEN_HEIGHT - self.rect.height:
self.rect.y = SCREEN_HEIGHT - self.rect.height
def main():
pygame.display.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("python小demo 飞机大战")
pygame.display.set_icon(pygame.image.load(os.path.join(IMG_PATH, "icon.jpg")))
background = pygame.image.load(os.path.join(IMG_PATH, "test_bj.png"))
hero = HeroPlane()
def update_hero():
hero.move_level(2)
screen.blit(hero.image, (hero.rect.x, hero.rect.y))
while True:
screen.blit(background, (0, 0))
update_hero()
pygame.display.update()
time.sleep(0.02)
if __name__ == "__main__":
main()
执行效果如下:
上面加载英雄并且实现英雄移动,其实就是不断改变图片在屏幕中的绘制位置。主函数的time.sleep也可以替换成pygame.time.Clock.tick方法,但本例子中,效果偏差不远,就没有使用pygame.time提供的时间模块
上面代码虽然能够实现英雄的移动,但是无法根据玩家操作控制英雄的移动,这时候我们就需要提供特定的键盘或者鼠标事件控制英雄移动,下面示例按住鼠标实现飞机移动
import os
import sys
import time
import pygame
SCREEN_WIDTH = 500
SCREEN_HEIGHT = 250
IMG_PATH = os.path.join(os.getcwd(), "img")
MOUSE_MOVE = False
class HeroPlane(object):
def __init__(self):
super(HeroPlane, self).__init__()
self.image = pygame.image.load(os.path.join(IMG_PATH, "hero_show_1.png"))
self.rect = self.image.get_rect()
self.rect.x = 0
self.rect.y = int(SCREEN_HEIGHT - self.rect.height) / 2
self.is_running = True
self.bullet_list = pygame.sprite.Group()
self.last_time = time.time()
def move_level(self, level):
if 0 <= level <= SCREEN_WIDTH - self.rect.width:
self.rect.x = level
elif level < 0:
self.rect.x = 0
elif level > SCREEN_WIDTH - self.rect.width:
self.rect.x = SCREEN_WIDTH - self.rect.width
def move_vertical(self, vertical):
if 0 <= vertical <= SCREEN_HEIGHT - self.rect.height:
self.rect.y = vertical
elif vertical < 0:
self.rect.y = 0
elif vertical > SCREEN_HEIGHT - self.rect.height:
self.rect.y = SCREEN_HEIGHT - self.rect.height
def main():
pygame.init()
pygame.display.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("python小demo 飞机大战")
pygame.display.set_icon(pygame.image.load(os.path.join(IMG_PATH, "icon.jpg")))
background = pygame.image.load(os.path.join(IMG_PATH, "test_bj.png"))
hero = HeroPlane()
def event_check():
"""
事件检测,这边做了一个简单的示例
return:
"""
global MOUSE_MOVE
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
MOUSE_MOVE = True
elif event.type == pygame.MOUSEBUTTONUP:
MOUSE_MOVE = False
if MOUSE_MOVE:
x, y = pygame.mouse.get_pos()
hero.move_level(x)
hero.move_vertical(y)
def update_hero():
screen.blit(hero.image, (hero.rect.x, hero.rect.y))
while True:
event_check()
screen.blit(background, (0, 0))
update_hero()
pygame.display.update()
time.sleep(0.02)
if __name__ == "__main__":
main()
执行效果如下:
所需函数简要说明
event.get(eventtype=None) -> Eventlist
event.get(eventtype=None, pump=True) -> Eventlist
- pygame.key用于处理键盘的模块,当键盘按下或者释放时,pygame.event.get()就能获取pygame.KEYDOWN或pygame.KEYUP事件,这两个事件都有key和mod属性:key代表键盘上每个整数ID;mod代表事件发生时修饰建位掩码。
上述例子中,如果想通过长按键盘?、?、?、?控制英雄,可将事件处理函数修改为:
def event_check():
"""
事件检测,这边做了一个简单的示例
return:
"""
global KEYDOWN
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
KEYDOWN = 1
elif event.key == pygame.K_UP:
KEYDOWN = 2
elif event.key == pygame.K_DOWN:
KEYDOWN = 3
elif event.key == pygame.K_RIGHT:
KEYDOWN = 4
elif event.type == pygame.KEYUP:
KEYDOWN = 0
if KEYDOWN:
if KEYDOWN == 1:
hero.move_level(hero.rect.x - 5)
elif KEYDOWN == 2:
hero.move_vertical(hero.rect.y - 5)
elif KEYDOWN == 3:
hero.move_vertical(hero.rect.y + 5)
else:
hero.move_level(hero.rect.x + 5)
下面列举常见的键盘常量(更多键盘常量可点击上方链接查阅文档):
KeyASCII | 描述 |
---|
K_BACKSPACE | 退格键(Backspace) | K_TAB | 制表键(Tab) | K_CLEAR | 清除键(Clear) | K_RETURN | 回车键(Enter) | K_ESCAPE | 退出键(Escape) | K_DELETE | 删除键(delete) | K_0 - K_9 | 0 - 9 | K_a - K_z | a - z | K_KP0 - K_KP9 | 0 - 9(小键盘) | K_UP | 向上箭头(up arrow) | K_DOWN | 向下箭头(down arrow) | K_RIGHT | 向右箭头(right arrow) | K_LEFT | 向左箭头(left arrow) |
碰撞检测及所需函数简要说明 上面代码中,已经实现创建英雄,并且能通过事件去控制英雄的移动,下面我们可以按照创建英雄的方法,创建一个敌机,并通过让英雄与敌机碰撞发生爆炸
import os
import sys
import time
import pygame
SCREEN_WIDTH = 500
SCREEN_HEIGHT = 250
IMG_PATH = os.path.join(os.getcwd(), "img")
MOUSE_MOVE = False
KEYDOWN = 0
class HeroPlane(object):
def __init__(self):
super(HeroPlane, self).__init__()
self.image = pygame.image.load(os.path.join(IMG_PATH, "hero_show_1.png"))
self.rect = self.image.get_rect()
self.rect.x = 0
self.rect.y = int(SCREEN_HEIGHT - self.rect.height) / 2
self.is_running = True
def move_level(self, level):
if 0 <= level <= SCREEN_WIDTH - self.rect.width:
self.rect.x = level
elif level < 0:
self.rect.x = 0
elif level > SCREEN_WIDTH - self.rect.width:
self.rect.x = SCREEN_WIDTH - self.rect.width
def move_vertical(self, vertical):
if 0 <= vertical <= SCREEN_HEIGHT - self.rect.height:
self.rect.y = vertical
elif vertical < 0:
self.rect.y = 0
elif vertical > SCREEN_HEIGHT - self.rect.height:
self.rect.y = SCREEN_HEIGHT - self.rect.height
class EnemyPlane(pygame.sprite.Sprite):
def __init__(self):
super(EnemyPlane, self).__init__()
self.image = pygame.image.load(os.path.join(IMG_PATH, "mp_show_3.png"))
self.rect = self.image.get_rect()
self.rect = self.image.get_rect()
self.rect.x = int(SCREEN_WIDTH - self.rect.width)
self.rect.y = int(SCREEN_HEIGHT - self.rect.height) / 2
self.is_running = True
def main():
pygame.init()
pygame.display.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("python小demo 飞机大战")
pygame.display.set_icon(pygame.image.load(os.path.join(IMG_PATH, "icon.jpg")))
background = pygame.image.load(os.path.join(IMG_PATH, "test_bj.png"))
hero = HeroPlane()
enemy = EnemyPlane()
def event_check():
"""
事件检测,这边做了一个简单的示例
return:
"""
global MOUSE_MOVE
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
MOUSE_MOVE = True
elif event.type == pygame.MOUSEBUTTONUP:
MOUSE_MOVE = False
if MOUSE_MOVE:
x, y = pygame.mouse.get_pos()
hero.move_level(x)
hero.move_vertical(y)
def update_hero():
screen.blit(hero.image, (hero.rect.x, hero.rect.y))
def update_enemy():
screen.blit(enemy.image, (enemy.rect.x, enemy.rect.y))
def check_crash():
is_crash = pygame.sprite.collide_rect(hero, enemy)
if is_crash:
screen.blit(pygame.image.load(os.path.join(IMG_PATH, "ex_2.png")), (hero.rect.x, hero.rect.y))
screen.blit(pygame.image.load(os.path.join(IMG_PATH, "ex_2.png")), (enemy.rect.x, enemy.rect.y))
game_over = pygame.font.Font(None, 100)
game_over = game_over.render("game over", True, (220, 20, 60))
screen.blit(game_over, [int(SCREEN_WIDTH / 2 - game_over.get_width() / 2), int(SCREEN_HEIGHT / 2)])
while True:
event_check()
screen.blit(background, (0, 0))
update_hero()
update_enemy()
check_crash()
pygame.display.update()
time.sleep(0.02)
if __name__ == "__main__":
main()
执行效果如下:
所需函数简要说明
- pygame.sprite 基本游戏对象类,上面例子中,我们英雄跟敌机都继承了pygame.sprite.Sprite,这是方便我们省略了造轮子的步骤,比如碰撞检测。
sprite.collide_rect(left, right) -> bool
sprite.Group() -> Group
sprite.Group.add(*sprites) -> None
sprite.spritecollide(sprite, group, dokill, collided = None) -> Sprite_list
sprite.groupcollide(group1, group2, dokill1, dokill2, collided = None) -> Sprite_dict
font.Font(filename, size) -> Font
font.Font(object, size) -> Font
font.Font.render(text, antialias, color, background=None) -> Surface
音频加载及所需函数简要说明
import os
import sys
import time
import pygame
SCREEN_WIDTH = 500
SCREEN_HEIGHT = 250
IMG_PATH = os.path.join(os.getcwd(), "img")
MOUSE_MOVE = False
KEYDOWN = 0
MUSIC_PATH = os.path.join(os.getcwd(), "sound")
class HeroPlane(pygame.sprite.Sprite):
def __init__(self):
super(HeroPlane, self).__init__()
self.image = pygame.image.load(os.path.join(IMG_PATH, "hero_show_1.png"))
self.rect = self.image.get_rect()
self.rect.x = 0
self.rect.y = int(SCREEN_HEIGHT - self.rect.height) / 2
self.is_running = True
def move_level(self, level):
if 0 <= level <= SCREEN_WIDTH - self.rect.width:
self.rect.x = level
elif level < 0:
self.rect.x = 0
elif level > SCREEN_WIDTH - self.rect.width:
self.rect.x = SCREEN_WIDTH - self.rect.width
def move_vertical(self, vertical):
if 0 <= vertical <= SCREEN_HEIGHT - self.rect.height:
self.rect.y = vertical
elif vertical < 0:
self.rect.y = 0
elif vertical > SCREEN_HEIGHT - self.rect.height:
self.rect.y = SCREEN_HEIGHT - self.rect.height
class EnemyPlane(pygame.sprite.Sprite):
def __init__(self):
super(EnemyPlane, self).__init__()
self.image = pygame.image.load(os.path.join(IMG_PATH, "mp_show_3.png"))
self.rect = self.image.get_rect()
self.rect = self.image.get_rect()
self.rect.x = int(SCREEN_WIDTH - self.rect.width)
self.rect.y = int(SCREEN_HEIGHT - self.rect.height) / 2
self.is_running = True
def main():
pygame.init()
pygame.display.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("python小demo 飞机大战")
pygame.display.set_icon(pygame.image.load(os.path.join(IMG_PATH, "icon.jpg")))
background = pygame.image.load(os.path.join(IMG_PATH, "test_bj.png"))
hero = HeroPlane()
enemy = EnemyPlane()
pygame.mixer.init()
pygame.mixer.music.load(os.path.join(MUSIC_PATH, "game_music.ogg"))
pygame.mixer.music.play(loops=-1)
def event_check():
"""
事件检测,这边做了一个简单的示例
return:
"""
global MOUSE_MOVE
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
MOUSE_MOVE = True
elif event.type == pygame.MOUSEBUTTONUP:
MOUSE_MOVE = False
if MOUSE_MOVE:
x, y = pygame.mouse.get_pos()
hero.move_level(x)
hero.move_vertical(y)
def update_hero():
screen.blit(hero.image, (hero.rect.x, hero.rect.y))
def update_enemy():
screen.blit(enemy.image, (enemy.rect.x, enemy.rect.y))
def check_crash():
is_crash = pygame.sprite.collide_rect(hero, enemy)
if is_crash:
screen.blit(pygame.image.load(os.path.join(IMG_PATH, "ex_2.png")), (hero.rect.x, hero.rect.y))
screen.blit(pygame.image.load(os.path.join(IMG_PATH, "ex_2.png")), (enemy.rect.x, enemy.rect.y))
pygame.mixer.Sound(os.path.join(MUSIC_PATH, "enemy1_down.wav")).play()
game_over = pygame.font.Font(None, 100)
game_over = game_over.render("game over", True, (220, 20, 60))
screen.blit(game_over, [int(SCREEN_WIDTH / 2 - game_over.get_width() / 2), int(SCREEN_HEIGHT / 2)])
while True:
event_check()
screen.blit(background, (0, 0))
update_hero()
update_enemy()
check_crash()
pygame.display.update()
time.sleep(0.02)
if __name__ == "__main__":
main()
由于博客视频条件限制,这儿就不放效果了,感兴趣的朋友可以拉下我的代码体验下
所需函数简要说明
mixer.init(
frequency=44100,
size=-16,
channels=2,
buffer=512,
devicename=None,
allowedchanges=AUDIO_ALLOW_FREQUENCY_CHANGE | AUDIO_ALLOW_CHANNELS_CHANGE
) -> None
mixer.music.load(filename) -> None
mixer.music.load(object) -> None
mixer.music.play(loops=0, start=0.0, fade_ms = 0) -> None
pygame.mixer.Sound(filename) -> Sound
pygame.mixer.Sound(buffer) -> Sound
pygame.mixer.Sound.play(loops=0, maxtime=0, fade_ms=0) -> Channel
python小demo 飞机大战完整例子
在上面,大致示范了使用pygame写一个飞机大战所需模块及函数,本人也写了一个示例,包括本推文中所使用的代码都提交至github,在公众号中回复“飞机大战”即可获取源码地址,及图片素材、音频素材,下面看下我例子图片:
|