鱼C论坛

 找回密码
 立即注册
查看: 741|回复: 13

[技术交流] 好久不见,pygameGUI开发日志又回来啦!

[复制链接]
发表于 2024-7-10 22:56:31 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
鸽了这么长时间,大家有没有想我啊~



这次的开发目前很顺利,并且这次假期带教程的2.0正式版本会发出来

如果发不出来我就爆金币

先不公布开发进度,给大伙看个代码块(不全的)看看各位鱼油可以从代码里分析出什么来

  1. import pygame
  2. from pygame.locals import *
  3. from pygameGUI.error import UIError
  4. from pygameGUI.group import Group, BottomGroup


  5. class Widget:
  6.     """组件基类"""
  7.     # states控件状态表
  8.     NORMAL = 0  # 正常
  9.     HOVER = 1  # 激活
  10.     PRESSED = 2  # 按下

  11.     def __init__(self, group):
  12.         """自动加入group组"""

  13.         # 自身组件交互状态
  14.         self.states = self.NORMAL

  15.         # 自身矩形位置(默认
  16.         self.rect = pygame.Rect([0, 0, 0, 0])

  17.         # 属于的组
  18.         self.group = group

  19.         if type(group) is BottomGroup:  # 是底层组
  20.             self.group = group
  21.             self.group.add(self)
  22.         elif isinstance(self.group, Frame):
  23.             self.group = group.group  # 是Frame大类
  24.             self.master = group
  25.             self.group.add(self)
  26.         else:
  27.             raise UIError("group参数应该是一个Frame类")

  28.     def update(self, *args, **kwargs):
  29.         """每帧调用"""
  30.         return

  31.     def draw(self, screen):
  32.         """每帧绘制"""
  33.         pass

  34.     def get_rect(self):
  35.         """获取组件在最底层surface对象中的矩形位置(帝龟)"""
  36.         if hasattr(self, "master"):
  37.             rect = [self.rect[0] + self.master.get_rect()[0],
  38.                     self.rect[1] + self.master.get_rect()[1],
  39.                     self.rect[2],
  40.                     self.rect[3]]
  41.             return pygame.Rect(rect)
  42.         else:
  43.             screen_rect = self.group.screen.get_rect()
  44.             rect = [screen_rect[0] + self.rect[0],
  45.                     screen_rect[1] + self.rect[1],
  46.                     self.rect[2],
  47.                     self.rect[3]]
  48.             return pygame.Rect(rect)

  49.     @staticmethod
  50.     def draw_texture(texture, size):
  51.         """绘制纹理"""
  52.         image = pygame.Surface(size, pygame.SRCALPHA)
  53.         if type(texture) is tuple or type(texture) is list:
  54.             image.fill(texture)
  55.         elif callable(texture):
  56.             image = texture(image)
  57.         elif type(texture) is pygame.Surface:
  58.             image = texture
  59.         else:
  60.             raise UIError("texture的类型应该是一个元组/列表、返回image函数 或 一个Surface对象")
  61.         return image

  62.     @staticmethod
  63.     def replace_rect(rect, image):
  64.         """在改变纹理后刷新矩形位置
  65.         | rect : 原位置
  66.         | image : 新图片
  67.         ~ 新位置中心点设为与原位置的中心点重合"""
  68.         x, y = rect.center
  69.         rect = image.get_rect()
  70.         rect.center = x, y
  71.         return rect

  72.     @staticmethod
  73.     def default_rect_detection(widget, *args, **kwargs):
  74.         if (not BottomGroup.block or widget.unblock) \
  75.                 and widget.get_rect().collidepoint(kwargs["pos"]):
  76.             # 开启阻断
  77.             if widget.block is True:
  78.                 BottomGroup.block = True
  79.             return widget.HOVER
  80.         else:
  81.             return widget.NORMAL


  82. class Frame(Widget):
  83.     """框架结构"""
  84.     def __init__(self, group, pos=(0, 0), size=(100, 100), texture=(0, 0, 0), block=True, unblock=False):
  85.         super().__init__(group)

  86.         # 阻断与阻断免疫
  87.         self.block = block
  88.         self.unblock = unblock

  89.         # 默认交互检测
  90.         self.detection = super().default_rect_detection

  91.         # 默认控制行为
  92.         def command(states, *args, **kwargs):
  93.             if states == self.HOVER:
  94.                 pass
  95.             self.states = states
  96.         self.command = command

  97.         # 生成图像和纹理
  98.         self.image = self.draw_texture(texture, size)

  99.         # 设置矩形
  100.         self.rect = self.image.get_rect()
  101.         self.rect.x, self.rect.y = pos

  102.         # 内置组
  103.         self.widgets = Group(self)

  104.     def update(self, *args, **kwargs):
  105.         """刷新"""
  106.         # 刷新内部组的组件
  107.         self.widgets.update(*args, **kwargs)

  108.         # 判定
  109.         states = self.detection(self, *args, **kwargs)

  110.         # 执行交互行为
  111.         self.command(states)

  112.     def draw(self, surface):
  113.         """绘制"""
  114.         image = self.image.copy()
  115.         self.widgets.draw(image)
  116.         surface.blit(image, [self.rect.x, self.rect.y])

  117.     def set_image(self, size=(100, 100), texture=(0, 0, 0)):
  118.         """设置图片,自动将新图片的中心与就图片中心重合"""
  119.         self.image = self.draw_texture(texture, size)
  120.         self.rect = self.replace_rect(self.rect, self.image)

  121.     def delete(self):
  122.         self.group.widgets.remove(self)


  123. class Button(Widget):
  124.     def __init__(self, group, pos=(0, 0), size=(50, 25), texture=(230, 230, 230),
  125.                  block=True, unblock=False):
  126.         super().__init__(group)

  127.         # 阻断与阻断免疫
  128.         self.block = block
  129.         self.unblock = unblock

  130.         # 生成图像和纹理
  131.         self.image = self.draw_texture(texture, size)

  132.         # 设置矩形
  133.         self.rect = self.image.get_rect()
  134.         self.rect.x, self.rect.y = pos

  135.         # 默认的交互检测
  136.         def detection(widget, *args, **kwargs):
  137.             if widget.default_rect_detection(widget, *args, **kwargs):
  138.                 # 判断输出交互状态
  139.                 if pygame.mouse.get_pressed()[0]:
  140.                     return widget.PRESSED
  141.                 else:
  142.                     return widget.HOVER
  143.             else:
  144.                 return widget.NORMAL
  145.         self.detection = detection

  146.         # 默认控制行为
  147.         def command(states, *args, **kwargs):
  148.             if states == self.NORMAL:  # 正常
  149.                 self.set_image()
  150.             elif states == self.HOVER:  # 交互状态
  151.                 self.set_image(texture=(240, 240, 240))
  152.                 if self.states == self.PRESSED:  # 从按下状态返回交互状态
  153.                     print("按钮完成了一次点击")
  154.             elif states == self.PRESSED:  # 按下状态
  155.                 self.set_image(texture=(220, 220, 220))
  156.             self.states = states

  157.         self.command = command

  158.     def update(self, *args, **kwargs):
  159.         """刷新"""
  160.         # 判定
  161.         states = self.detection(self, *args, **kwargs)

  162.         # 执行交互行为
  163.         self.command(states)

  164.     def draw(self, surface):
  165.         """绘制"""
  166.         surface.blit(self.image, [self.rect.x, self.rect.y])

  167.     def set_image(self, size=(50, 25), texture=(230, 230, 230)):
  168.         """设置图片,自动将新图片的中心与就图片中心重合"""
  169.         self.image = self.draw_texture(texture, size)
  170.         self.rect = self.replace_rect(self.rect, self.image)
复制代码


游客,如果您要查看本帖隐藏内容请回复
[/hide]


由于这次使用了pycharm作为编辑器,所以效率提高了不少





点评

我很赞同!: 5.0
我很赞同!: 5
PyCharm效率确实比VS Code要好很多  发表于 2024-7-12 15:43

评分

参与人数 4荣誉 +17 鱼币 +17 贡献 +6 收起 理由
zhangchenyvn + 5 + 5 + 3 上一次好像还是三个月前,现在这个项目仍然.
weiter + 5 + 5 鱼C有你更精彩^_^
python爱好者. + 5 + 5 + 3 鱼C有你更精彩^_^
某一个“天” + 2 + 2 鱼C有你更精彩^_^

查看全部评分

本帖被以下淘专辑推荐:

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-7-10 22:57:50 | 显示全部楼层
哈哈,鱼油们,好久不见啊!咱们的pygameGUI开发日志又回来啦!鸽了这么久,你们有没有想我呀? 如果你们不想我,我可是会伤心的哦~

这一次,我可带来了好消息:我们2.0正式版本要在假期发布啦!如果发不出来,我就爆金币!

看到大伙儿如此期待,我也不卖关子了,虽然不公开具体进度,但今天给大家看一小段代码,看看你们能从中分析出什么来。瞧瞧我的新作,别客气,尽情发表你们的高见哈!

  1. import pygame
  2. from pygame.locals import *
  3. from pygameGUI.error import UIError
  4. from pygameGUI.group import Group, BottomGroup

  5. class Widget:
  6.     """组件基类"""
  7.     NORMAL = 0  # 正常
  8.     HOVER = 1   # 激活
  9.     PRESSED = 2 # 按下

  10.     def __init__(self, group):
  11.         self.states = self.NORMAL
  12.         self.rect = pygame.Rect()
  13.         self.group = group

  14.         if type(group) is BottomGroup:  
  15.             self.group.add(self)
  16.         elif isinstance(self.group, Frame):
  17.             self.master = group
  18.             self.group.add(self)
  19.         else:
  20.             raise UIError("group参数应该是一个Frame类")

  21.     def update(self, *args, **kwargs):
  22.         return

  23.     def draw(self, screen):
  24.         pass

  25.     def get_rect(self):
  26.         if hasattr(self, "master"):
  27.             rect = [self.rect + self.master.get_rect()]
  28.             return pygame.Rect(rect)
  29.         else:
  30.             screen_rect = self.group.screen.get_rect()
  31.             rect = [screen_rect + self.rect]
  32.             return pygame.Rect(rect)

  33.     @staticmethod
  34.     def draw_texture(texture, size):
  35.         image = pygame.Surface(size, pygame.SRCALPHA)
  36.         if type(texture) in (tuple, list):
  37.             image.fill(texture)
  38.         elif callable(texture):
  39.             image = texture(image)
  40.         elif isinstance(texture, pygame.Surface):
  41.             image = texture
  42.         else:
  43.             raise UIError("texture的类型应该是一个元组/列表、返回image函数 或 一个Surface对象")
  44.         return image

  45.     @staticmethod
  46.     def replace_rect(rect, image):
  47.         x, y = rect.center
  48.         rect = image.get_rect()
  49.         rect.center = x, y
  50.         return rect

  51.     @staticmethod
  52.     def default_rect_detection(widget, *args, **kwargs):
  53.         if (not BottomGroup.block or widget.unblock) and widget.get_rect().collidepoint(kwargs):
  54.             if widget.block:
  55.                 BottomGroup.block = True
  56.             return widget.HOVER
  57.         else:
  58.             return widget.NORMAL
复制代码


看到了吗,这是一个基础的组件类`Widget`。它有三种状态:正常(`NORMAL`),激活(`HOVER`),和按下(`PRESSED`)。我们还定义了一些方法,比如`draw_texture`绘制纹理,`replace_rect`刷新矩形位置等。

接下来再看看我们特别设计的两个组件类,`Frame`和`Button`,它们都是从`Widget`继承而来:

  1. class Frame(Widget):
  2.     def __init__(self, group, pos=(0, 0), size=(100, 100), texture=(0, 0, 0), block=True, unblock=False):
  3.         super().__init__(group)
  4.         self.block = block
  5.         self.unblock = unblock
  6.         self.detection = super().default_rect_detection

  7.         def command(states, *args, **kwargs):
  8.             if states == self.HOVER:
  9.                 pass
  10.             self.states = states
  11.         self.command = command

  12.         self.image = self.draw_texture(texture, size)
  13.         self.rect = self.image.get_rect()
  14.         self.rect.x, self.rect.y = pos
  15.         self.widgets = Group(self)

  16.     def update(self, *args, **kwargs):
  17.         self.widgets.update(*args, **kwargs)
  18.         states = self.detection(self, *args, **kwargs)
  19.         self.command(states)

  20.     def draw(self, surface):
  21.         image = self.image.copy()
  22.         self.widgets.draw(image)
  23.         surface.blit(image, )

  24.     def set_image(self, size=(100, 100), texture=(0, 0, 0)):
  25.         self.image = self.draw_texture(texture, size)
  26.         self.rect = self.replace_rect(self.rect, self.image)

  27.     def delete(self):
  28.         self.group.widgets.remove(self)
复制代码


`Frame`类是一个框架结构组件,它有一个内部组`widgets`可以容纳其它组件,同时提供了阻断与免疫机制,以及默认控制和交互检测。

  1. class Button(Widget):
  2.     def __init__(self, group, pos=(0, 0), size=(50, 25), texture=(230, 230, 230), block=True, unblock=False):
  3.         super().__init__(group)
  4.         self.block = block
  5.         self.unblock = unblock
  6.         self.image = self.draw_texture(texture, size)
  7.         self.rect = self.image.get_rect()
  8.         self.rect.x, self.rect.y = pos

  9.         def detection(widget, *args, **kwargs):
  10.             if widget.default_rect_detection(widget, *args, **kwargs):
  11.                 if pygame.mouse.get_pressed()[0]:
  12.                     return widget.PRESSED
  13.                 else:
  14.                     return widget.HOVER
  15.             else:
  16.                 return widget.NORMAL
  17.         self.detection = detection

  18.         def command(states, *args, **kwargs):
  19.             if states == self.NORMAL:
  20.                 self.set_image()
  21.             elif states == self.HOVER:
  22.                 self.set_image(texture=(240, 240, 240))
  23.                 if self.states == self.PRESSED:
  24.                     print("按钮完成了一次点击")
  25.             elif states == self.PRESSED:
  26.                 self.set_image(texture=(220, 220, 220))
  27.             self.states = states

  28.         self.command = command

  29.     def update(self, *args, **kwargs):
  30.         states = self.detection(self, *args, **kwargs)
  31.         self.command(states)

  32.     def draw(self, surface):
  33.         surface.blit(self.image, )

  34.     def set_image(self, size=(50, 25), texture=(230, 230, 230)):
  35.         self.image = self.draw_texture(texture, size)
  36.         self.rect = self.replace_rect(self.rect, self.image)
复制代码


`Button`类是一个按钮组件,同样具有阻断与免疫机制,还新增了按钮状态的视觉反馈,比如在不同状态下改变颜色,并且已经默认实现了简单的点击逻辑。

怎么样,鱼油们,看懂了吗?这是个很灵活的模板,通过分离交互检测和行为执行部分,以减少重复代码,提高开发效率。用PyCharm编辑器码代码效率也蹭蹭往上涨~

希望这些代码能为你们提供一些启发,等我的2.0版本发布出来后,一定会更加详细地介绍每一个模块的使用方法,所以大家敬请期待吧!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-7-10 22:59:21 | 显示全部楼层
FishC 发表于 2024-7-10 22:57
哈哈,鱼油们,好久不见啊!咱们的pygameGUI开发日志又回来啦!鸽了这么久,你们有没有想我呀?  ...

不是,哥们
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-7-10 23:03:25 | 显示全部楼层
支持
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-7-11 09:13:44 | 显示全部楼层
支持,看来更新的内容不少嘛,加油呀
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-7-11 09:14:37 | 显示全部楼层
站在使用者角度考虑,精简使用者所费代码,妙啊

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-7-11 10:15:00 | 显示全部楼层
好耶
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-7-11 11:38:45 | 显示全部楼层
纯新手,这个pygame是干啥的昂
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-7-11 12:57:34 | 显示全部楼层
abiao_fishc 发表于 2024-7-11 11:38
纯新手,这个pygame是干啥的昂

写游戏用的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-7-11 13:22:08 | 显示全部楼层
本帖最后由 zhangchenyvn 于 2024-7-11 13:23 编辑

感觉这次的代码更新比上次的工程化了好多,功能也丰富了好多,上面这段代码应该是UI的框架和一个按钮的代码,写成了类似TK的模板化代码,使用起来比上一代更加高效亿些
真心表示:真的不错
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-7-11 16:30:45 | 显示全部楼层
路过
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-14 05:38

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表