宅在家里,沉迷于pygame编程,这篇文章给大家分享一下基于pygame实现一些简单的小功能,这些功能可以很好的嵌入在游戏中增加游戏的交互性。
这篇文章主要讲述用pygame实现虚拟键盘的方式。
目录
1. 效果 & 功能
2. 代码
2.1. 按钮
2.2. 处理输入
2.3. 显示
2.3. 运行
3. 结语
1. 效果 & 功能
- 主要实现功能有:
- 输入0-9a-z间的字符
- ‘del’进行删除
- ‘end’结束输入
demo演示
2. 代码
首先引用基础库和声明一些常量方便之后更改。
SCREEN_SIZE = 1000, 500 # 屏幕大小# 一些常用颜色
WHITE = 255, 255, 255
GRAY = 190, 190, 190
BLACK = 0, 0, 0
LINEN = 250, 240, 230
DARKSLATEGRAY = 47, 79, 79PAD = 10 # 各物块,按钮之间的 padding
FPS = 60 # pygame显示的fpsDISPLAY_FONT = (None, 40) # 显示打印文字的字体
DISPLAY_BG_COLOR = LINEN # 显示打印文字区域的背景色
DISPLAY_TEXT_COLOR = DARKSLATEGRAY # 打印文字的颜色KEYBOARD_FONT = (None, 30) # 按钮字体
KEYBOARD_BUTTON_SIZE = 40, 40 # 按钮大小
KEYBOARD_BG_COLOR = WHITE # 按钮背景色
KEYBOARD_BG_COLOR_CLICKED = GRAY # 按钮被选中时的背景色
KEYBOARD_TEXT_COLOR = BLACK # 按钮文字颜色
2.1. 按钮
首先时虚拟按钮的实现,我们在这里将每一个按钮都当作一个pygame.sprite.Sprite类,具体代码如下:
class KeyboardButton(pygame.sprite.Sprite):def __init__(self, **kwargs):# 创建按钮时需要有多个参数# size :按钮的大小# value :按钮的显示值# id : 按钮的idpygame.sprite.Sprite.__init__(self)self.size = kwargs.get('size')self.value = kwargs.get('value')if kwargs.get('id'):self.id = kwargs.get('id')else :# 若没有id,则我们默认self.value为按钮的self.idself.id = self.valueself.clicked = False # 按钮是否被选中self.render_image() # 渲染按钮显示图像def render_image(self):# 主要渲染两个图像:# self.image_org为原始图像# self.image_clicked为选中时的图像font = pygame.font.Font(*KEYBOARD_FONT)w, h = font.size(self.value)# 初始化Surfaceself.rect = Rect(0, 0, *self.size)self.image_org = pygame.Surface(self.size).convert()self.image_org.fill(KEYBOARD_BG_COLOR)# 居中渲染self.valueself.image_org.blit(font.render(self.value, True, KEYBOARD_TEXT_COLOR),((self.size[0] - w) // 2, (self.size[1] - h) // 2))self.image_clicked = self.image_org.copy()self.image_clicked.fill(KEYBOARD_BG_COLOR_CLICKED)self.image_clicked.blit(font.render(self.value, True, KEYBOARD_TEXT_COLOR),((self.size[0] - w) // 2, (self.size[1] - h) // 2))self.image = self.image_orgdef update(self):# 根据该按钮是否被选中决定显示图像if self.clicked:self.image = self.image_clickedelse:self.image = self.image_org
我们将把按钮都放入一个SpriteGroup中进行update, update时我们需要三个参数 (args = mouse_x, mouse_y, mouse_clicked) :
mouse_x, mouse_y, mouse_clicked (鼠标的位置,以及鼠标点击与否)
mouse_clicked = True (鼠标按下) | False (鼠标按上) | None (其它)
class KeyboardButtonGroup(pygame.sprite.Group):def __init__(self):pygame.sprite.Group.__init__(self)def update(self, *args):mouse_x, mouse_y, mouse_clicked = argsfor s in self.sprites():if s.rect.collidepoint(mouse_x, mouse_y):# 鼠标触碰按钮# 若鼠标按下if mouse_clicked == True:s.clicked = True# 若鼠标按上elif mouse_clicked == False:if s.clicked:# 若鼠标按上且之前按下时点击的该按钮s.clicked = Falseadd_input(s.id)else:if mouse_clicked == False:s.clicked = Falses.update() # 更新按钮的显示
2.2. 处理输入
在这里,我们定义一个类用于存放输入的字符并进行处理,注意在 KeyboardButtonGroup 中,我们通过 add_input(s.id) 用于处理得到的输入,这一部分我们讲述如何实现该功能。
class Keyboard():keyboard_input = [] # 存放inputoutput = False # 是否最终输出
def empty_keyboard():# 初始化Keyboard中的变量Keyboard.keyboard_input = []Keyboard.output = Falsedef add_input(value):# 新的输入if value == 'del': # 删除if Keyboard.keyboard_input:Keyboard.keyboard_input.pop()elif value == 'end': # 输入完毕Keyboard.output = Trueelse: # 普通输入Keyboard.keyboard_input.append(value)def get_keyboard_input():return Keyboard.keyboard_inputdef end_of_input():return Keyboard.output
2.3. 显示
显示有两个区域,一个是显示输入区域,一个是按钮区域
def keyboard(screen):empty_keyboard()mouse_x, mouse_y, mouse_clicked = 0, 0, Nonekeyboard_button_grp = KeyboardButtonGroup() # 初始化按钮for value in [str(i) for i in range(10)] + [chr(i) for i in range(ord('a'), ord('a') + 26)] + ['del', 'end']:keyboard_button_grp.add(KeyboardButton(size=KEYBOARD_BUTTON_SIZE, value=value))KEYBOARD_BUTTON_PER_ROW = 10 # 每行的按钮数量keyboard_rows = (len(keyboard_button_grp) - 1) // KEYBOARD_BUTTON_PER_ROW + 1 # 按钮的总行数KEYBOARD_SIZE = KEYBOARD_BUTTON_SIZE[0] * KEYBOARD_BUTTON_PER_ROW + PAD * (KEYBOARD_BUTTON_PER_ROW - 1), \KEYBOARD_BUTTON_SIZE[1] * keyboard_rows + PAD * (keyboard_rows - 1) # 按钮区域的总大小DISPLAY_POSITION = (SCREEN_SIZE[0] - KEYBOARD_SIZE[0]) // 2, SCREEN_SIZE[1] // 10 # 显示输入区域的位置display_font = pygame.font.Font(*DISPLAY_FONT) # 显示输入区域字体display_height = display_font.get_height() + 2 * PAD # 显示输入区域高度x, y = DISPLAY_POSITION[0], DISPLAY_POSITION[1] + display_height + PAD # 按钮区域的位置start_x = x# 对每个按钮位置进行排列for i, button in enumerate(keyboard_button_grp):button.rect.topleft = x, yif (i + 1) % KEYBOARD_BUTTON_PER_ROW:x += KEYBOARD_BUTTON_SIZE[0] + PADelse:x = start_xy += KEYBOARD_BUTTON_SIZE[1] + PADdef draw_area_display(screen):# 绘显示输入区域img = pygame.Surface((KEYBOARD_SIZE[0], display_height)).convert()img.fill(DISPLAY_BG_COLOR)img.blit(display_font.render(''.join(get_keyboard_input()), True, DISPLAY_TEXT_COLOR), (PAD, PAD))screen.blit(img, DISPLAY_POSITION)def draw_area_keyboard(screen, keyboard_button_grp):# 绘按钮区域keyboard_button_grp.draw(screen)fps_clock = pygame.time.Clock()while True:# 判断是否最终输出if end_of_input():return get_keyboard_input()mouse_clicked = None# 获取 mouse_x, mouse_y, mouse_clickedfor event in pygame.event.get():if event.type == QUIT:exit()if event.type == MOUSEBUTTONDOWN:mouse_clicked = Trueelif event.type == MOUSEBUTTONUP:mouse_clicked = Falseelif event.type == MOUSEMOTION:mouse_x, mouse_y = event.posscreen.fill(BLACK)draw_area_display(screen)keyboard_button_grp.update(mouse_x, mouse_y, mouse_clicked)draw_area_keyboard(screen, keyboard_button_grp)fps_clock.tick(FPS)pygame.display.update()
2.3. 运行
if __name__ == '__main__':pygame.init()screen = pygame.display.set_mode(SCREEN_SIZE)result = keyboard(screen)print(result)pygame.quit()
3. 结语
这篇文章给大家一个简单的展示如何通过pygame绘制和实现虚拟键盘,当然这里只是实现了简单的打字功能。通过修改 add_input(), 为特殊 id 的 KeyboardButton 定制一些特殊的功能都是可以尝试的。祝大家游戏愉快!