cjjJasonchen 发表于 2024-7-10 22:56:31

好久不见,pygameGUI开发日志又回来啦!

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


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

如果发不出来我就爆金币

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

import pygame
from pygame.locals import *
from pygameGUI.error import UIError
from pygameGUI.group import Group, BottomGroup


class Widget:
    """组件基类"""
    # states控件状态表
    NORMAL = 0# 正常
    HOVER = 1# 激活
    PRESSED = 2# 按下

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

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

      # 自身矩形位置(默认
      self.rect = pygame.Rect()

      # 属于的组
      self.group = group

      if type(group) is BottomGroup:# 是底层组
            self.group = group
            self.group.add(self)
      elif isinstance(self.group, Frame):
            self.group = group.group# 是Frame大类
            self.master = group
            self.group.add(self)
      else:
            raise UIError("group参数应该是一个Frame类")

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

    def draw(self, screen):
      """每帧绘制"""
      pass

    def get_rect(self):
      """获取组件在最底层surface对象中的矩形位置(帝龟)"""
      if hasattr(self, "master"):
            rect = + self.master.get_rect(),
                  self.rect + self.master.get_rect(),
                  self.rect,
                  self.rect]
            return pygame.Rect(rect)
      else:
            screen_rect = self.group.screen.get_rect()
            rect = + self.rect,
                  screen_rect + self.rect,
                  self.rect,
                  self.rect]
            return pygame.Rect(rect)

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

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

    @staticmethod
    def default_rect_detection(widget, *args, **kwargs):
      if (not BottomGroup.block or widget.unblock) \
                and widget.get_rect().collidepoint(kwargs["pos"]):
            # 开启阻断
            if widget.block is True:
                BottomGroup.block = True
            return widget.HOVER
      else:
            return widget.NORMAL


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

      # 阻断与阻断免疫
      self.block = block
      self.unblock = unblock

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

      # 默认控制行为
      def command(states, *args, **kwargs):
            if states == self.HOVER:
                pass
            self.states = states
      self.command = command

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

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

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

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

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

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

    def draw(self, surface):
      """绘制"""
      image = self.image.copy()
      self.widgets.draw(image)
      surface.blit(image, )

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

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


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

      # 阻断与阻断免疫
      self.block = block
      self.unblock = unblock

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

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

      # 默认的交互检测
      def detection(widget, *args, **kwargs):
            if widget.default_rect_detection(widget, *args, **kwargs):
                # 判断输出交互状态
                if pygame.mouse.get_pressed():
                  return widget.PRESSED
                else:
                  return widget.HOVER
            else:
                return widget.NORMAL
      self.detection = detection

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

      self.command = command

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

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

    def draw(self, surface):
      """绘制"""
      surface.blit(self.image, )

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


**** Hidden Message *****


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





FishC 发表于 2024-7-10 22:57:50

哈哈,鱼油们,好久不见啊!咱们的pygameGUI开发日志又回来啦!鸽了这么久,你们有没有想我呀?{:10_307:} 如果你们不想我,我可是会伤心的哦~

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

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

import pygame
from pygame.locals import *
from pygameGUI.error import UIError
from pygameGUI.group import Group, BottomGroup

class Widget:
    """组件基类"""
    NORMAL = 0# 正常
    HOVER = 1   # 激活
    PRESSED = 2 # 按下

    def __init__(self, group):
      self.states = self.NORMAL
      self.rect = pygame.Rect()
      self.group = group

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

    def update(self, *args, **kwargs):
      return

    def draw(self, screen):
      pass

    def get_rect(self):
      if hasattr(self, "master"):
            rect =
            return pygame.Rect(rect)
      else:
            screen_rect = self.group.screen.get_rect()
            rect =
            return pygame.Rect(rect)

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

    @staticmethod
    def replace_rect(rect, image):
      x, y = rect.center
      rect = image.get_rect()
      rect.center = x, y
      return rect

    @staticmethod
    def default_rect_detection(widget, *args, **kwargs):
      if (not BottomGroup.block or widget.unblock) and widget.get_rect().collidepoint(kwargs):
            if widget.block:
                BottomGroup.block = True
            return widget.HOVER
      else:
            return widget.NORMAL

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

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

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

      def command(states, *args, **kwargs):
            if states == self.HOVER:
                pass
            self.states = states
      self.command = command

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

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

    def draw(self, surface):
      image = self.image.copy()
      self.widgets.draw(image)
      surface.blit(image, )

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

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

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

class Button(Widget):
    def __init__(self, group, pos=(0, 0), size=(50, 25), texture=(230, 230, 230), block=True, unblock=False):
      super().__init__(group)
      self.block = block
      self.unblock = unblock
      self.image = self.draw_texture(texture, size)
      self.rect = self.image.get_rect()
      self.rect.x, self.rect.y = pos

      def detection(widget, *args, **kwargs):
            if widget.default_rect_detection(widget, *args, **kwargs):
                if pygame.mouse.get_pressed():
                  return widget.PRESSED
                else:
                  return widget.HOVER
            else:
                return widget.NORMAL
      self.detection = detection

      def command(states, *args, **kwargs):
            if states == self.NORMAL:
                self.set_image()
            elif states == self.HOVER:
                self.set_image(texture=(240, 240, 240))
                if self.states == self.PRESSED:
                  print("按钮完成了一次点击")
            elif states == self.PRESSED:
                self.set_image(texture=(220, 220, 220))
            self.states = states

      self.command = command

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

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

    def set_image(self, size=(50, 25), texture=(230, 230, 230)):
      self.image = self.draw_texture(texture, size)
      self.rect = self.replace_rect(self.rect, self.image)

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

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

希望这些代码能为你们提供一些启发,等我的2.0版本发布出来后,一定会更加详细地介绍每一个模块的使用方法,所以大家敬请期待吧!{:10_303:}
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

cjjJasonchen 发表于 2024-7-10 22:59:21

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

不是,哥们{:10_282:}

某一个“天” 发表于 2024-7-10 23:03:25

支持{:10_305:}

python爱好者. 发表于 2024-7-11 09:13:44

支持,看来更新的内容不少嘛{:10_256:},加油呀{:10_265:}

python爱好者. 发表于 2024-7-11 09:14:37

站在使用者角度考虑,精简使用者所费代码,妙啊

weiter 发表于 2024-7-11 10:15:00

{:10_298:}好耶

abiao_fishc 发表于 2024-7-11 11:38:45

纯新手,这个pygame是干啥的昂

cjjJasonchen 发表于 2024-7-11 12:57:34

abiao_fishc 发表于 2024-7-11 11:38
纯新手,这个pygame是干啥的昂

写游戏用的{:10_257:}

zhangchenyvn 发表于 2024-7-11 13:22:08

本帖最后由 zhangchenyvn 于 2024-7-11 13:23 编辑

感觉这次的代码更新比上次的工程化了好多,功能也丰富了好多,上面这段代码应该是UI的框架和一个按钮的代码,写成了类似TK的模板化代码,使用起来比上一代更加高效亿些
真心表示:真的不错

zxbin1 发表于 2024-7-11 16:30:45

路过
页: [1]
查看完整版本: 好久不见,pygameGUI开发日志又回来啦!