上一篇文章:https://blog.csdn.net/qq_48979387/article/details/129219749
参考资料:
https://pyga.me/docs/ref/joystick.html
如图是一个游戏手柄(XBox 360 Controller),是一种外接输入设备。不同的游戏手柄包含的按键功能不同,按键发送的事件也不同。大多数游戏手柄包含几个部分:轴(axis)、球(ball)、按钮(button)、帽子(hat),数量各有不同。
轴是一个具有调节数值功能的组件,数值范围在-1.0到1.0之间,0表示轴在中间值。轴有时候只能调节三个值:-1,0,1。
球是一个具有自由改变方向功能的组件,有时候被用于替代鼠标。球可以朝向任何一个平面上的方向。有一些电脑的键盘上有一个圆形的按钮,可以往不同方向按压它来操纵鼠标,这个按钮的功能就和球类似。
按钮是一个可以按下松开的组件。
帽子是一个控制上下左右四个方向的组件,类似于方向键。
pg.joystick模块用于管理游戏手柄。接入同一个设备的游戏手柄可能有多个,首先需要将它们全部导入进来。每个游戏手柄都由一个Joystick对象进行管理。
joysticks = [pg.joystick.Joystick(x) for x in range(pg.joystick.get_count())]
每个Joystick对象都有一个用于标识的id,范围是0到pygame.joystick.get_count() - 1。
游戏手柄支持一些事件:JOYAXISMOTION, JOYBALLMOTION, JOYBUTTONDOWN, JOYBUTTONUP, JOYHATMOTION。
JOYAXISMOTION |
游戏手柄的轴移动 |
instance_id(游戏手柄标识符), axis, value |
JOYBALLMOTION |
游戏手柄的球移动 |
instance_id, ball, rel(相对移动距离(x, y)) |
JOYHATMOTION |
游戏手柄的帽子移动 |
instance_id, hat, value |
JOYBUTTONUP |
游戏手柄按钮松开 |
instance_id, button |
JOYBUTTONDOWN |
游戏手柄按钮按下 |
instance_id, button |
JOYDEVICEADDED |
连接到新的游戏手柄 |
device_index |
JOYDEVICEREMOVED |
游戏手柄断开连接 |
instance_id |
此代码来自pygame.examples,有兴趣的读者可以自行研究。
import pygame
pygame.init()
# 这是一个简单的类,用于把文字显示到屏幕上。
# 它与joysticks无关,只是为了输出一些信息。
class TextPrint:
def __init__(self):
self.reset()
self.font = pygame.font.Font(None, 25)
def tprint(self, screen, text):
text_bitmap = self.font.render(text, True, (0, 0, 0))
screen.blit(text_bitmap, (self.x, self.y))
self.y += self.line_height
def reset(self):
self.x = 10
self.y = 10
self.line_height = 15
def indent(self):
self.x += 10
def unindent(self):
self.x -= 10
def main():
# 设置窗口尺寸,并设置标题
screen = pygame.display.set_mode((500, 700))
pygame.display.set_caption("Joystick example")
# 用于控制屏幕的刷新速度
clock = pygame.time.Clock()
# 准备打印
text_print = TextPrint()
# 这个字典可以保持原样,
# 因为pygame将为程序开始时连接的每个操纵杆生成一个
# pygame.JOYDEVICEADDED事件。
joysticks = {}
done = False
while not done:
# 处理事件
# 可能的游戏手柄事件:JOYAXISMOTION, JOYBALLMOTION, JOYBUTTONDOWN,
# JOYBUTTONUP, JOYHATMOTION, JOYDEVICEADDED, JOYDEVICEREMOVED
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True # 退出循环
if event.type == pygame.JOYBUTTONDOWN:
print("Joystick button pressed.")
if event.button == 0:
joystick = joysticks[event.instance_id]
if joystick.rumble(0, 0.7, 500):
print(f"Rumble effect played on joystick {event.instance_id}")
if event.type == pygame.JOYBUTTONUP:
print("Joystick button released.")
# 处理游戏手柄的热插拔
if event.type == pygame.JOYDEVICEADDED:
# 该事件将在程序启动每个操纵杆时生成,无需手动创建即可填充列表。
joy = pygame.joystick.Joystick(event.device_index)
joysticks[joy.get_instance_id()] = joy
print(f"Joystick {joy.get_instance_id()} connencted")
if event.type == pygame.JOYDEVICEREMOVED:
del joysticks[event.instance_id]
print(f"Joystick {event.instance_id} disconnected")
# 清除屏幕为白色
screen.fill((255, 255, 255))
text_print.reset()
# 获取游戏手柄的数量
joystick_count = pygame.joystick.get_count()
text_print.tprint(screen, f"Number of joysticks: {joystick_count}")
text_print.indent()
# 遍历所有的游戏手柄
for joystick in joysticks.values():
jid = joystick.get_instance_id()
text_print.tprint(screen, f"Joystick {jid}")
text_print.indent()
# 从操作系统中获取控制器/操纵杆的名称
name = joystick.get_name()
text_print.tprint(screen, f"Joystick name: {name}")
guid = joystick.get_guid()
text_print.tprint(screen, f"GUID: {guid}")
power_level = joystick.get_power_level()
text_print.tprint(screen, f"Joystick's power level: {power_level}")
# 通常轴是成对运行的,一个是上/下,另一个是左/右。触发器算作轴。
axes = joystick.get_numaxes()
text_print.tprint(screen, f"Number of axes: {axes}")
text_print.indent()
for i in range(axes):
axis = joystick.get_axis(i)
text_print.tprint(screen, f"Axis {i} value: {axis:>6.3f}")
text_print.unindent()
buttons = joystick.get_numbuttons()
text_print.tprint(screen, f"Number of buttons: {buttons}")
text_print.indent()
for i in range(buttons):
button = joystick.get_button(i)
text_print.tprint(screen, f"Button {i:>2} value: {button}")
text_print.unindent()
hats = joystick.get_numhats()
text_print.tprint(screen, f"Number of hats: {hats}")
text_print.indent()
# 帽子的位置。方向要么全有要么全无,而不是像get_axis()那样的浮点数。
# Position是一个由int值(x, y)组成的元组。
for i in range(hats):
hat = joystick.get_hat(i)
text_print.tprint(screen, f"Hat {i} value: {str(hat)}")
text_print.unindent()
text_print.unindent()
# 刷新屏幕
pygame.display.flip()
# 控制30帧每秒
clock.tick(30)
if __name__ == "__main__":
main()
pygame.quit()
get_count() -> count
返回连接的游戏手柄数量
Joystick(id) -> Joystick
游戏手柄对象。
Joystick.get_instance_id() -> int
返回游戏手柄的标识符
Joystick.get_power_level() -> str
返回游戏手柄的电量情况,可能的返回值有:empty, low, medium, full, wired, max, unknown(字符串)
Joystick.get_name() -> string
返回游戏手柄的系统名称
Joystick.get_numaxes() -> int
返回游戏手柄“轴”的数量
Joystick.get_axis(axis_number) -> float
根据指定的轴返回它的值,范围在-1到1之间。0表示轴位于中间。
Joystick.get_numballs() -> int
返回游戏手柄“球”的数量
Joystick.get_ball(ball_number) -> x, y
根据指定的球返回它的值,x, y表示球相对移动的位置。
Joystick.get_numbuttons() -> int
返回游戏手柄“按钮”的数量
Joystick.get_button(button) -> bool
根据指定的按钮返回它的值,表示是否按下按钮。
Joystick.get_numhats() -> int
返回游戏手柄“帽子”的数量
Joystick.get_hat(hat_number) -> x, y
根据指定的帽子返回它的值。(0,0)表示居中。-1表示左或下,1表示右或上,所以(- 1,0)表示左;(1,0)表示右;(0,1)表示向上;(1,1)表示右上角;等等。
rumble(low_frequency, high_frequency, duration) -> bool
使游戏手柄振动。duration表示持续的时间,单位为ms
stop_rumble() -> None
停止振动。
参考资料:https://pyga.me/docs/ref/camera.html
pg.camera.Camera对象用于管理摄像头。在使用camera前,首先需要导入pg.camera模块。camera虽然是pygame的一个子模块,但是并不是pygame中一个属性,需要额外进行导入,并且还需要额外地进行初始化。
下面的例子打印出当前系统中所有的摄像头:
import pygame as pg
from pygame import camera
camera.init()
cameras = camera.list_cameras() #获取摄像头列表
print(cameras)
list_cameras返回系统中所有摄像头的名称。如果系统没有摄像头返回[0]。
下面的示例中,从摄像头获取的图片将被显示在pygame窗口上。
import pygame as pg
from pygame import camera
pg.init()
screen = pg.display.set_mode()
camera.init()
cameras = camera.list_cameras() #获取摄像头列表
if cameras[0] != 0: #如果列表中只有0表示没有摄像头,载入为0的摄像头不会报错但是无法运行
current_camera = camera.Camera(cameras[0]) #载入摄像头
else:
print("没有摄像头")
exit()
current_camera.start() #开始使用摄像头
while True:
screen.fill((0, 0, 0))
im = current_camera.get_image() #获取摄像头图像(只有开始使用摄像头后才能获取,否则报错)
screen.blit(im, (0, 0))
for event in pg.event.get():
if event.type == pg.QUIT:
current_camera.stop() #停止使用摄像头
pg.quit()
pg.display.flip()
init(backend = None) -> None
初始化摄像头模块。
list_cameras() -> [cameras]
返回一系列摄像头名称列表(如果没有摄像头返回[0])
Camera(device, (width, height), format) -> Camera
摄像头对象
Camera.start() -> None
开启摄像头(如果需要通过摄像头获取图片,开启是必需的)
Camera.stop() -> None
关闭摄像头
Camera.set_controls(hflip = bool, vflip = bool, brightness) -> (hflip = bool, vflip = bool, brightness)
设置摄像头是否进行水平翻转、垂直翻转,brightness表示设置亮度。部分摄像头可能不支持其中部分的功能。
Camera.get_controls() -> (hflip = bool, vflip = bool, brightness)
获取摄像头的水平翻转、垂直翻转、亮度。不支持的摄像头将返回默认值(0, 0, 0)
Camera.get_size() -> (width, height)
获取摄像头拍摄的图像大小
Camera.query_image() -> bool
判断摄像头是否已经准备好了图像(拍摄需要时间)
Camera.get_image(Surface = None) -> Surface
从摄像头拍摄一张图片,并返回这张图片的表面对象。如果指定Surface,则将该Surface替换为拍摄的图片以节省计算时间。
Camera.get_raw() -> bytes
从摄像头拍摄一张图片,并返回原始码
参考资料:https://pyga.me/docs/ref/system.html
大部分的游戏都需要存储玩家信息。常用的存储方式有:存储到服务器(暂不介绍)或存储到本机。
将游戏信息存储到本机的原理很简单,只需在玩家首次进入游戏时创建一个文件,之后就可以对这个文件进行读写。这个存档文件的格式可以自行选择,如*.txt,*.json,*.p文件,常用于存储游戏信息。
将游戏数据文件存储在当前游戏文件夹中也是一个比较好的选择,而且玩家在卸载游戏时数据只需要把整个文件夹删除,同时游戏数据文件会连带着一起被卸载。但如果想要保留数据,使玩家重装游戏时存档不变,那么就需要把数据存储到一个特定的地方,独立于游戏文件夹。这个用于专门存储应用数据的文件夹在不同系统上位于不同的位置,如Windows上,这个路径默认位于C:\Users\Administrator\AppData\Roaming\
pg.system模块提供了一些针对当前系统的操作。pg.system.get_pref_path(org, app)方法返回分配好的应用数据文件夹。org表示游戏作者,app表示游戏名称(用于区分不同的应用数据)。例如:
>>> path = pg.system.get_pref_path("my_company", "app_name") #返回一个路径
>>> print(path)
C:\Users\Administrator\AppData\Roaming\my_company\app_name\
get_pref_path函数将系统应用数据文件夹与公司名、应用名组合起来,形成一个路径。如果该路径的文件夹不存在,将会新建一个。
系统区域设置指的是一个系统的位置及语言信息,如位置:中国;语言:中文这些设置。
pg.system.get_pref_locales函数返回一个列表,包含多个字典,每个字典都含有键"language"和"country",表示语言,以及这个语言所属的国家。返回的列表按语言的首选项集降序排列。
>>> pg.system.get_pref_locales()
[{'language': 'zh', 'country': 'CN'}, {'language': 'en', 'country': 'US'}]
比如在我的系统上,位于第一个字典中的zh(中文)是第一选择;但如果没有中文,那下一个选项是en(英语)。这些语言的顺序排列是可以在系统设置中进行更改的。
为什么要有语言首选项的设定呢?
假如有一个应用,只支持中文和英文。有一位用户安装了该应用,这位用户最擅长法语,只会一点英语。在这位用户的语言排列中有法语-英语的顺序。当用户打开应用时,应用检测到了他的首选语言是法语,但这个应用并不支持法语,于是只能退而求其次选择位于第二首选的英语。
这样,就使得语言的设置更加人性化。
如果希望游戏支持多语言,那么可以通过这个方法确定当前系统使用的语言。
此外还需要注意,这个函数比较耗时,所以应该在游戏开始之前提前加载好并且将语言数据储存起来。避免循环加载。
在pygame运行时,如果检测到用户更改了当前的系统区域设置,会生成一个事件LOCALECHANGED。
参考资料:https://pyga.me/docs/ref/scrap.html
pg.scrap.get_text()方法返回剪贴板中刚刚复制的文本。
如果想要知道剪贴板中是否有文本,则应使用pg.scrap.has_text()方法,这个方法将返回一个布尔值。
pg.scrap.put_text(text)用于将text字符串复制到剪贴板。
>>> pg.scrap.put_text("Hello, pygame world!") #复制
>>> pg.scrap.get_text()
'Hello, pygame world!'
>>> pg.scrap.has_text()
True
制作中……有问题请联系作者
停更一段时间,作者正在弄游戏引擎