目录
pygame介绍:
Pygame 是一个专门用来开发游戏的 Python 模块,主要为开发、设计 2D 电子游戏而生,它是一个免费、开源的第三方软件包,支持多种操作系统,具有良好的跨平台性(比如 Windows、Linux、Mac 等)。Pygame 是 Pete Shinners 在 SDL(Simple DirectMedia Layer,一套开源的跨平台多媒体开发库)基础上开发而来,其目的是取代 PySDL。
pygame提供了丰富的功能和工具,用于创建2D游戏、交互式应用程序和媒体项目。它建立在Simple DirectMedia Layer (SDL) 库之上,提供了一套简单易用的接口,使开发人员可以方便地使用Python来开发游戏。
Pygame提供了许多功能,包括图形渲染、图像处理、音频播放、键盘鼠标事件处理、碰撞检测等。开发人员可以使用Pygame来创建各种类型的游戏,包括平台游戏、射击游戏、迷宫游戏等。
使用Pygame,开发人员可以轻松地处理游戏的图形和声音方面的需求,同时也可以与其他Python库和工具进行集成。它具有跨平台的特性,可以在不同操作系统下(如Windows、MacOS和Linux)运行。
(每个代码都是可以单独拿出来在pycharm中运行,主要的是在目录同级下有的需要图片或字体)
1.创建一个可以关闭的空白窗体
# 导入所需的模块
import sys
import pygame
class GameManage:
def __init__(self):
# 导入所需的模块
pygame.init()
# 创建一个空白窗口
self.screen = pygame.display.set_mode((480, 700))
def run(self):
while True:
# 循环获取事件,监听事件状态
for event in pygame.event.get():
# 判断鼠标是否点了"X"关闭按钮
if event.type == pygame.QUIT:
# 卸载所有模块
pygame.quit()
# 退出程序
sys.exit()
# 一直更新屏幕
pygame.display.flip()
gm = GameManage()
gm.run()
运行效果,创建一个可自控关闭的空白窗口self.screen = pygame.display.set_mode((480, 700)),元组是填写窗口的宽和高,若想填充屏幕颜色可以在while中使用self.screen.fill()来设置,run中死循环中获取事件,这个是检测鼠标是否点击窗口右上角的叉号,事件检测在下面会有介绍
2.使用精灵显示背景, 背景的循环展示
Sprite类
在 Pygame 中,Sprite 是用于管理和绘制游戏对象的类。Sprite 类提供了一种方便的方式来组织游戏中的图形元素,并且提供了一些常用的功能和方法,如碰撞检测和绘制。
Pygame 的 Sprite 类是通过继承自 pygame.sprite.Sprite 类来创建自定义的 Sprite 类。每个自定义的 Sprite 类都必须包含两个主要的成员:图像(image)和位置(rect)。
在 Pygame 中,Sprite 是用于管理和绘制游戏对象的基类。它提供了一种方便的方式来组织游戏中的图形元素,并提供了一些常用的功能和方法,如碰撞检测和绘制。
Pygame 中的 Sprite 类是通过继承自 pygame.sprite.Sprite 类来创建自定义的 Sprite 类。每个自定义的 Sprite 类都必须包含两个主要的成员:图像(image)和位置(rect)。图像用于绘制精灵对象的外观,位置用于确定精灵对象在游戏窗口中的位置和尺寸。
Sprite 类还提供了一些常用的方法,如 `update()` 方法用于更新精灵对象的状态,`draw()` 方法用于在游戏窗口中绘制精灵对象。
通过使用 Sprite 类,可以方便地创建和管理多个游戏对象。
import sys
import pygame
class BaseSprite(pygame.sprite.Sprite):
"""
精灵基础类
"""
def __init__(self, name):
super().__init__()
# 初始化image
self.image = pygame.image.load(name)
self.rect = self.image.get_rect()
class BGSprite(BaseSprite):
"""
背景精灵类
"""
def __init__(self, name, topleft):
super().__init__(name)
self.rect.topleft = topleft
def update(self):
self.rect.top += 10
if self.rect.top > 700:
self.rect.top = -700
class BGManage:
"""
背景管理类
"""
def __init__(self, gm):
self.gm = gm
self.bg_group = pygame.sprite.Group()
BGSprite("background.png", (0, 0)).add(self.bg_group)
BGSprite("background.png", (0, -700)).add(self.bg_group)
def update(self):
self.bg_group.update()
self.bg_group.draw(self.gm.screen)
class GameManage:
def __init__(self):
pygame.init()
# 创建一个空白窗口
self.screen = pygame.display.set_mode((480, 700))
# 调用计算游戏循环中帧率的类
self.clock = pygame.time.Clock()
self.bg_manage = BGManage(self)
def run(self):
while True:
self.clock.tick(24)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
self.bg_manage.update()
pygame.display.flip()
gm = GameManage()
gm.run()
创建精灵基础类,在创建背景精灵类,调用基础类,初始化父类属性,在背景管理类中,创建update方法刷新背景精灵组并把它绘制到屏幕上,刷新精灵组调用精灵组的update()方法
在里面写入背景移动的像素规则,(图片需要自己添加在同等级目录下)
在游戏循环中,为了保持稳定的帧率并控制游戏运行速度,需要使用pygame.time.Clock()
对象来创建一个时钟对象。这个时钟对象可以让我们按照指定的帧率刷新屏幕,以避免游戏的运行速度过快或过慢。
在初始化Pygame后,创建一个时钟对象
# 调用计算游戏循环中帧率的类
self.clock = pygame.time.Clock()
设置游戏帧率,防止刷新过快
3.使用精灵玩家,玩家可以移动
键盘事件
Pygame提供了键盘事件来检测和响应玩家在键盘上的按键操作。当用户按下或释放键盘上的键时,Pygame会生成相应的事件,程序可以通过处理这些事件来实现对键盘操作的响应。
常见的键盘事件包括:
-
pygame.KEYDOWN
:表示键盘按下事件,当用户按下某个键时触发。可以使用event.key
属性获取按下的键的值。 -
pygame.KEYUP
:表示键盘抬起事件,当用户释放某个键时触发。同样可以使用event.key
属性获取抬起的键的值。
通常在游戏的主循环中使用pygame.event.get()
来获取当前发生的所有事件,然后通过判断事件类型和键的值来响应用户的键盘操作。
import sys
import pygame
class BaseSprite(pygame.sprite.Sprite):
"""
精灵基础类
"""
def __init__(self, name):
super().__init__()
# 初始化image
self.image = pygame.image.load(name)
self.rect = self.image.get_rect()
class BGSprite(BaseSprite):
"""
背景精灵类
"""
def __init__(self, name, topleft):
super().__init__(name)
self.rect.topleft = topleft
def update(self):
self.rect.top += 10
if self.rect.top > 700:
self.rect.top = -700
class BGManage:
"""
背景管理类
"""
def __init__(self, gm):
self.gm = gm
# 创建精灵组
self.bg_group = pygame.sprite.Group()
# 创建精灵
BGSprite("background.png", (0, 0)).add(self.bg_group)
BGSprite("background.png", (0, -700)).add(self.bg_group)
def update(self):
# 更新精灵组
self.bg_group.update()
# 精灵组绘制到屏幕上
self.bg_group.draw(self.gm.screen)
class PlayerSprite(BaseSprite):
"""
玩家精灵类
"""
def __init__(self, name, center, gm):
super().__init__(name)
self.gm = gm
self.rect.center = center
self.speed = 10
def update(self):
# 获得键盘事件
key_pressed = pygame.key.get_pressed()
# 判断是否按下左键,判断左边距
if key_pressed[pygame.K_LEFT] and self.rect.left > 0:
self.rect.left -= self.speed
# 判断是否按下右键,判断右边距
if key_pressed[pygame.K_RIGHT] and self.rect.right < 480:
self.rect.left += self.speed
# 判断是否按下上键,判断顶部边距
if key_pressed[pygame.K_UP] and self.rect.top > 0:
self.rect.top -= self.speed
# 判断是否按下下键,判断底部边距
if key_pressed[pygame.K_DOWN] and self.rect.bottom < 700:
self.rect.top += self.speed
class PlayerManage:
def __init__(self, gm):
self.gm = gm
# 创建玩家精灵组
self.player_group = pygame.sprite.Group()
# 创建玩家精灵
self.player = PlayerSprite("me1.png", (240, 600), self.gm)
# 玩家精灵加入到精灵组中
self.player.add(self.player_group)
def update(self):
# 更新精灵组
self.player_group.update()
# 精灵组绘制到屏幕上
self.player_group.draw(self.gm.screen)
class GameManage:
def __init__(self):
pygame.init()
# 创建一个空白窗口
self.screen = pygame.display.set_mode((480, 700))
# 调用计算游戏循环中帧率的类
self.clock = pygame.time.Clock()
# 实例调用类BGManage传入gm
self.bg_manage = BGManage(self)
# 实例调用类PlayerManage传入gm
self.player_manage = PlayerManage(self)
def run(self):
while True:
# 更改游戏帧率
self.clock.tick(24)
# 循环获取事件,监听事件状态
for event in pygame.event.get():
# 判断鼠标是否点了"X"关闭按钮
if event.type == pygame.QUIT:
# 卸载所有模块
pygame.quit()
# 退出程序
sys.exit()
# 调用背景管理类中的update方法
self.bg_manage.update()
# 调用玩家管理类中的update方法
self.player_manage.update()
# 一直刷新屏幕
pygame.display.flip()
gm = GameManage()
gm.run()
创建玩家精灵类继承精灵父类,在update方法中获得键盘事件,根据键盘操作飞机的移动方向
在玩家管理类中初始玩家精灵组,创建玩家精灵并加入到精灵组中。
效果图:
4.使用精灵显示道具,玩家与道具碰撞检测
精灵之间碰撞检测
在Pygame中,精灵碰撞是指两个精灵对象相互接触或重叠的情况。Pygame提供了用于检测和处理精灵碰撞的功能,以便在游戏中实现碰撞检测和相应的逻辑。
Pygame中的精灵(Sprite)是一个图像对象,可以在游戏中移动和与其他对象进行交互。通过使用Pygame中的碰撞检测函数和方法,可以判断两个精灵是否相互碰撞,从而触发相应的行为或事件。
常用的精灵碰撞检测方法和函数包括:
-
pygame.sprite.spritecollide()
:这是一个方法,用于检测一个精灵对象是否与一个精灵组中的其他精灵对象发生碰撞。它返回与指定精灵碰撞的所有精灵对象的列表。 -
pygame.sprite.collide_rect()
:这是一个方法,用于检测两个精灵对象的矩形边界是否相交。如果相交,则认为两个精灵碰撞。 -
pygame.sprite.collide_rect_ratio()
:这是一个函数,与collide_rect()
类似,但可以通过设置一个比率来调整矩形边界的大小。
除了上述方法和函数,Pygame还提供了其他碰撞检测的函数和方法,如collide_circle()
、collide_mask()
等,可以根据具体需求选择使用。
使用精灵碰撞检测功能,可以实现例如角色与敌人的碰撞、子弹与敌人的碰撞等游戏中常见的碰撞效果,从而为游戏增加更多的交互性和挑战性。
import sys
import pygame
import random
class BaseSprite(pygame.sprite.Sprite):
"""
精灵基础类
"""
def __init__(self, name):
super().__init__()
# 初始化image
self.image = pygame.image.load(name)
self.rect = self.image.get_rect()
class BGSprite(BaseSprite):
"""
背景精灵类
"""
def __init__(self, name, topleft):
super().__init__(name)
self.rect.topleft = topleft
def update(self):
self.rect.top += 10
if self.rect.top > 700:
self.rect.top = -700
class BGManage:
"""
背景管理类
"""
def __init__(self, gm):
self.gm = gm
# 创建精灵组
self.bg_group = pygame.sprite.Group()
# 创建精灵
BGSprite("background.png", (0, 0)).add(self.bg_group)
BGSprite("background.png", (0, -700)).add(self.bg_group)
def update(self):
# 更新精灵组
self.bg_group.update()
# 精灵组绘制到屏幕上
self.bg_group.draw(self.gm.screen)
class PlayerSprite(BaseSprite):
"""
玩家精灵类
"""
def __init__(self, name, center, gm):
super().__init__(name)
self.gm = gm
self.rect.center = center
self.speed = 10
def update(self):
# 获得键盘事件
key_pressed = pygame.key.get_pressed()
# 判断是否按下左键,判断左边距
if key_pressed[pygame.K_LEFT] and self.rect.left > 0:
self.rect.left -= self.speed
# 判断是否按下右键,判断右边距
if key_pressed[pygame.K_RIGHT] and self.rect.right < 480:
self.rect.left += self.speed
# 判断是否按下上键,判断顶部边距
if key_pressed[pygame.K_UP] and self.rect.top > 0:
self.rect.top -= self.speed
# 判断是否按下下键,判断底部边距
if key_pressed[pygame.K_DOWN] and self.rect.bottom < 700:
self.rect.top += self.speed
class PlayerManage:
def __init__(self, gm):
self.gm = gm
# 创建玩家精灵组
self.player_group = pygame.sprite.Group()
# 创建玩家精灵
self.player = PlayerSprite("me1.png", (240, 600), self.gm)
# 玩家精灵加入到精灵组中
self.player.add(self.player_group)
def update(self):
# 更新精灵组
self.player_group.update()
# 精灵组绘制到屏幕上
self.player_group.draw(self.gm.screen)
class PropSprite(BaseSprite):
"""
道具精灵类
"""
def __init__(self, name, speed):
super().__init__(name)
# 随机定义初始值x坐标,在屏幕上显示,y默认为空零,在道具底部在屏幕顶部显示
self.rect.left = random.randint(0, 480 - self.rect.width)
self.rect.bottom = 0
self.speed = speed
def update(self):
# 向下移动
self.rect.top += self.speed
if self.rect.top > 700:
# 清除道具精灵
self.kill()
class PropManage:
"""
道具管理类
"""
def __init__(self, gm):
self.gm = gm
# 创建精灵组
self.prop_group = pygame.sprite.Group()
# 设定时间块
self.time_count = 5
# 生成道具
def generate(self):
# 设定每种道具出现的概率
value = random.random()
if value > 0.7:
PropSprite("bomb_supply.png", 8).add(self.prop_group)
elif value > 0.4:
PropSprite("bullet_supply.png", 8).add(self.prop_group)
else:
PropSprite("life.png", 8).add(self.prop_group)
def update(self):
# 规定时间出现一个道具
self.time_count -= 0.1
if self.time_count <= 0:
self.time_count = 5
self.generate()
# 更新精灵组
self.prop_group.update()
# 道具绘制到屏幕上
self.prop_group.draw(self.gm.screen)
class GameManage:
def __init__(self):
pygame.init()
# 创建一个空白窗口
self.screen = pygame.display.set_mode((480, 700))
# 调用计算游戏循环中帧率的类
self.clock = pygame.time.Clock()
# 实例调用类BGManage传入gm
self.bg_manage = BGManage(self)
# 实例调用类PlayerManage传入gm
self.player_manage = PlayerManage(self)
# 实例调用类PropManage传入gm
self.prop_manage = PropManage(self)
# 检测玩家是否与道具发生碰撞
def check_collider(self):
# 玩家和物资的碰撞,返回值是一个bool类型,碰撞后道具消失
player_prop_collider = pygame.sprite.groupcollide(self.player_manage.player_group, self.prop_manage.prop_group,
False, True)
if player_prop_collider:
for props in player_prop_collider.values():
for prop in props:
print("吃到道具")
def run(self):
while True:
# 更改游戏帧率
self.clock.tick(24)
# 循环获取事件,监听事件状态
for event in pygame.event.get():
# 判断鼠标是否点了"X"关闭按钮
if event.type == pygame.QUIT:
# 卸载所有模块
pygame.quit()
# 退出程序
sys.exit()
# 调用背景管理类中的update方法
self.bg_manage.update()
# 调用玩家管理类中的update方法
self.player_manage.update()
# 调用道具管理类中的update方法
self.prop_manage.update()
# 调用方法,检测碰撞
self.check_collider()
# 一直刷新屏幕
pygame.display.flip()
gm = GameManage()
gm.run()
添加道具精灵组和添加玩家精灵组是一样的,主要不同的是玩家的精灵组中只添加玩家一个,所以初始化的时候就添加一个精灵,而道具是不同的,道具首先是随机显示,坐标不确定。其次道具是要一直生成所以要一直向道具组中添加新的精灵。道具管理类中有一个generate方法,用来是生成道具,在update调用,随着时间钟的读秒,每五秒查收·产生一个道具,根据random.random()返回值是一个大于等于0,小于1 的小数,不同的概率产生不同的道具。
检测精灵的碰撞在管理类中定义一个方法check_collider(),用来判断精灵组之间的碰撞pygame.sprite.groupcollide(self.player_manage.player_group, self.prop_manage.prop_group,
False, True)
使用pygame.sprite.groupcollide()方法,里面传入两个精灵组,碰撞后时候消失,根据第三个和第四个位置形参的bool值来定义。
pygame.sprite.groupcollide()方法返回值是一个bool型。发生碰撞返回真,反之返回false。
效果图:
5.UI的使用 (字体,鼠标点击检测)
捕捉鼠标点击检测
class Util:
@staticmethod
def click_check(sprite):
if pygame.mouse.get_pressed()[0]:
if sprite.rect.collidepoint(pygame.mouse.get_pos()):
return True
return False
类Util 用来检测鼠标点击,是否与精灵组碰撞,get_pos()获得鼠标点击事件,传入一个精灵参数判断是否被鼠标点击。被点击返回真反之返回假。
ui精灵类,主要是三种状态的判断(ready,gaming, end),根据不同的状态调用不同的类update方法,实现画面的切换。
import sys
import pygame
import random
class BaseSprite(pygame.sprite.Sprite):
"""
精灵基础类
"""
def __init__(self, name):
super().__init__()
# 初始化image
self.image = pygame.image.load(name)
self.rect = self.image.get_rect()
class BGSprite(BaseSprite):
"""
背景精灵类
"""
def __init__(self, name, topleft):
super().__init__(name)
self.rect.topleft = topleft
def update(self):
self.rect.top += 10
if self.rect.top > 700:
self.rect.top = -700
class BGManage:
"""
背景管理类
"""
def __init__(self, gm):
self.gm = gm
# 创建精灵组
self.bg_group = pygame.sprite.Group()
# 创建精灵
BGSprite("background.png", (0, 0)).add(self.bg_group)
BGSprite("background.png", (0, -700)).add(self.bg_group)
def update(self):
# 更新精灵组
self.bg_group.update()
# 精灵组绘制到屏幕上
self.bg_group.draw(self.gm.screen)
class PlayerSprite(BaseSprite):
"""
玩家精灵类
"""
def __init__(self, name, center, gm):
super().__init__(name)
self.gm = gm
self.rect.center = center
self.speed = 10
def update(self):
# 获得键盘事件
key_pressed = pygame.key.get_pressed()
# 判断是否按下左键,判断左边距
if key_pressed[pygame.K_LEFT] and self.rect.left > 0:
self.rect.left -= self.speed
# 判断是否按下右键,判断右边距
if key_pressed[pygame.K_RIGHT] and self.rect.right < 480:
self.rect.left += self.speed
# 判断是否按下上键,判断顶部边距
if key_pressed[pygame.K_UP] and self.rect.top > 0:
self.rect.top -= self.speed
# 判断是否按下下键,判断底部边距
if key_pressed[pygame.K_DOWN] and self.rect.bottom < 700:
self.rect.top += self.speed
class PlayerManage:
def __init__(self, gm):
self.gm = gm
# 创建玩家精灵组
self.player_group = pygame.sprite.Group()
# 创建玩家精灵
self.player = PlayerSprite("me1.png", (240, 600), self.gm)
# 玩家精灵加入到精灵组中
self.player.add(self.player_group)
def update(self):
# 更新精灵组
self.player_group.update()
# 精灵组绘制到屏幕上
self.player_group.draw(self.gm.screen)
class PropSprite(BaseSprite):
"""
道具精灵类
"""
def __init__(self, name, speed):
super().__init__(name)
# 随机定义初始值x坐标,在屏幕上显示,y默认为空零,在道具底部在屏幕顶部显示
self.rect.left = random.randint(0, 480 - self.rect.width)
self.rect.bottom = 0
self.speed = speed
def update(self):
# 向下移动
self.rect.top += self.speed
if self.rect.top > 700:
# 清除道具精灵
self.kill()
class PropManage:
"""
道具管理类
"""
def __init__(self, gm):
self.gm = gm
# 创建精灵组
self.prop_group = pygame.sprite.Group()
# 设定时间块
self.time_count = 5
# 生成道具
def generate(self):
# 设定每种道具出现的概率
value = random.random()
if value > 0.7:
PropSprite("bomb_supply.png", 8).add(self.prop_group)
elif value > 0.4:
PropSprite("bullet_supply.png", 8).add(self.prop_group)
else:
PropSprite("life.png", 8).add(self.prop_group)
def update(self):
# 规定时间出现一个道具
self.time_count -= 0.1
if self.time_count <= 0:
self.time_count = 5
self.generate()
# 更新精灵组
self.prop_group.update()
# 道具绘制到屏幕上
self.prop_group.draw(self.gm.screen)
class Util:
@staticmethod
def click_check(sprite):
if pygame.mouse.get_pressed()[0]:
if sprite.rect.collidepoint(pygame.mouse.get_pos()):
return True
return False
class UISprite(BaseSprite):
def __init__(self, name, center):
super().__init__(name)
self.rect.center = center
class UIManage:
def __init__(self, gm):
self.gm = gm
# UI字体
self.font = pygame.font.Font("font/font.ttf", 32)
# 开始前UI元素
self.ready_group = pygame.sprite.Group()
self.begin_btn = UISprite("again.png", (240, 300))
self.begin_btn.add(self.ready_group)
# 游戏中UI元素
self.score_surface = self.font.render(f"Score:{0}", True, "#FF4500")
# 游戏结束UI元素
self.end_group = pygame.sprite.Group()
self.replay_btn = UISprite("begin.png", (240, 300))
self.replay_btn.add(self.end_group)
def update(self):
if self.gm.state == "ready":
# print("更新未开始游戏UI")
self.ready_group.draw(self.gm.screen)
if Util.click_check(self.begin_btn):
self.gm.state = "gaming"
elif self.gm.state == "gaming":
# print("更新游戏中UI")
self.gm.bg_manage.update()
self.gm.player_manage.update()
self.gm.prop_manage.update()
elif self.gm.state == "end":
# print("更新游戏结束UI")
self.end_group.draw(self.gm.screen)
if Util.click_check(self.replay_btn):
self.gm.state = "gaming"
class GameManage:
def __init__(self):
pygame.init()
# 创建一个空白窗口
self.screen = pygame.display.set_mode((480, 700))
self.screen.fill((127, 127, 127))
self.state = "ready"
# 调用计算游戏循环中帧率的类
self.clock = pygame.time.Clock()
# 实例调用类BGManage传入gm
self.bg_manage = BGManage(self)
# 实例调用类PlayerManage传入gm
self.player_manage = PlayerManage(self)
# 实例调用类PropManage传入gm
self.prop_manage = PropManage(self)
# 实例调用类UIManage传入gm
self.ui_manage = UIManage(self)
# 检测玩家是否与道具发生碰撞
def check_collider(self):
# 玩家和物资的碰撞,返回值是一个bool类型,碰撞后道具消失
player_prop_collider = pygame.sprite.groupcollide(self.player_manage.player_group, self.prop_manage.prop_group,
False, True)
if player_prop_collider:
for props in player_prop_collider.values():
for prop in props:
print("吃到道具")
def run(self):
while True:
# 更改游戏帧率
self.clock.tick(24)
# 循环获取事件,监听事件状态
for event in pygame.event.get():
# 判断鼠标是否点了"X"关闭按钮
if event.type == pygame.QUIT:
# 卸载所有模块
pygame.quit()
# 退出程序
sys.exit()
self.ui_manage.update()
# 调用方法,检测碰撞
self.check_collider()
# 一直刷新屏幕
pygame.display.flip()
gm = GameManage()
gm.run()
感谢观看,留下个赞b( ̄▽ ̄)d再走呗!!!!