鱼C论坛

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

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

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

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

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

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



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

如果发不出来我就爆金币

先不公布开发进度,给大伙看个代码块(不全的)看看各位鱼油可以从代码里分析出什么来
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([0, 0, 0, 0])

        # 属于的组
        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.rect[0] + self.master.get_rect()[0],
                    self.rect[1] + self.master.get_rect()[1],
                    self.rect[2],
                    self.rect[3]]
            return pygame.Rect(rect)
        else:
            screen_rect = self.group.screen.get_rect()
            rect = [screen_rect[0] + self.rect[0],
                    screen_rect[1] + self.rect[1],
                    self.rect[2],
                    self.rect[3]]
            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, [self.rect.x, self.rect.y])

    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()[0]:
                    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, [self.rect.x, self.rect.y])

    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)

游客,如果您要查看本帖隐藏内容请回复
[/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有你更精彩^_^

查看全部评分

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

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

看到大伙儿如此期待,我也不卖关子了,虽然不公开具体进度,但今天给大家看一小段代码,看看你们能从中分析出什么来。瞧瞧我的新作,别客气,尽情发表你们的高见哈!
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 = [self.rect + self.master.get_rect()]
            return pygame.Rect(rect)
        else:
            screen_rect = self.group.screen.get_rect()
            rect = [screen_rect + self.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()[0]:
                    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版本发布出来后,一定会更加详细地介绍每一个模块的使用方法,所以大家敬请期待吧!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

不是,哥们
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-7-10 23:03:25 | 显示全部楼层
支持
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-7-11 09:13:44 | 显示全部楼层
支持,看来更新的内容不少嘛,加油呀
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-7-11 10:15:00 | 显示全部楼层
好耶
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-7-11 11:38:45 | 显示全部楼层
纯新手,这个pygame是干啥的昂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

写游戏用的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

使用道具 举报

发表于 2024-7-11 16:30:45 | 显示全部楼层
路过
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-10-3 09:32

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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