Metadata-Version: 2.4
Name: qgame
Version: 1.21.0
Summary: A professional game library based on PySide6
Author: WatermelonCode
Author-email: watermeloncode@foxmail.com
License: MIT
Project-URL: Homepage, https://gitee.com/watermelon-juice-code/qgame/
Project-URL: Repository, https://gitee.com/watermelon-juice-code/qgame/
Project-URL: Bug Reports, https://gitee.com/watermelon-juice-code/qgame/issues
Keywords: game,qgame,qt,gui,pyside6,game-library,pygame
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: OS Independent
Classifier: Topic :: Games/Entertainment
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: PySide6>=6.0.0
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: keywords
Dynamic: license
Dynamic: license-file
Dynamic: project-url
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary


# QGame Engine

A lightweight, modern, and high-performance 2D game framework built on PySide6. Designed to draw like Pygame, yet harness the power of modern UI systems, absolute path scaling, high-performance memory image operations, and smooth matrix transformations.

QGame Engine 是一个基于 PySide6 构建的轻量级、现代且高性能的 2D 游戏开发框架。它在提供类似于 Pygame 的极简绘制 API 的同时，还融合了现代 UI 系统接口、无 DPI 偏差缩放、高性能内存位图离屏缓冲以及轻量平滑的矩阵变换。
---

# Changelog / 更新日志

## [2026.08.17] Version 1.21.0 （**性能优化/Performance Optimization**）
**English:**
*   **Regarding Startup Speed**
    *   Sorry, I forgot to mention this earlier 😅. The speed improvement applies when you have complex functionality or a lot of code — startup will be noticeably faster. If you're just creating a simple, empty window with nothing in it, then unfortunately, it will still be as slow as before.
    *   Otherwise, just look at Example 38 — *"Stellar Crypto Physical Vault (which uses the password input box from 1.20.0)"* — isn't its startup speed pretty fast?
*   **Performance Optimization**
    *   Refactored drawing functions such as `draw` and `particles` and `ecs` to batch render everything in a single pass, rather than drawing on every call. No code changes required on your end — all improvements are internal.
*   **Particle System Updates**
    *   In addition to performance optimizations, several presets have been added: `create_snow` (snowfall), `create_smoke` (rising smoke), `create_sparkle` (magic sparkles), and `create_sakura` (falling cherry blossoms).
*   **Resource Updates**
    *   Although this is just a storage module, it now comes with built-in caching! Existing `Image` and `SVG` assets can be reused automatically.
*   **Update Notification Updates**
    *   Now, it doesn't just show that a new version is available — it also displays the actual changelog.
    *   Of course, if you still find it annoying, the bug was already fixed in the previous version. Just set `qgame.show_update_info = False` 😅.
    *   But updates aren't really that bad, you know? When you see the prompt, just update. You get bug fixes, new features, and performance improvements. The sooner you update, the sooner you get the latest version. (Totally not trying to convince you to keep it enabled, says the melon 🍉.)
**中文:**
*   **关于开启速度**
    *   漏说了一句，抱歉😅。这是对于功能复杂或代码很多时启动速度会很快，如果你就创建个简单的吗、没有任何东西的窗口，那抱歉，久的还是久
    *   不然你看，示例38 — *"《星际密码物理金库》（使用1.20.0的密码框）"*开启的的速度是不是很快？
*   **性能优化**
    *   将`draw`、`particles`、`ecs`等这些关于绘画功能，统一绘制，而不是调用即绘制。不用修改任何代码，只在内部进行修改
*   **粒子系统更新**
    *   除了性能优化，还增加了几个预设：雪花 (create_snow)、上升烟雾 (create_smoke)、魔法闪烁 (create_sparkle) 以及 樱花飘落 (create_sakura)
*   **Resource更新**
    *   虽然这个只是个存储的模块，但带自动缓存功能的！可以复用已有的Image和SVG
*   **更新提醒更新**
    *   现在不会只显示新版本好了，而是把其更新内容也显示
    *   当然如果你觉得烦的话，那个Bug上个版本就修了，使用：`qgame.show_update_info = Falsee`即可😅
    *   但更新其实没那么不好，你看到提示你就更新，更新了修复Bug、增加功能、性能优化，你先更新，你就比别人先得到新的版本（试图劝你开启此功能的屑🍉）

## [2026.08.16] Version 1.20.0 （**❗❗❗ 版本重大更新/Major Version Update ❗❗❗**）
**English:**
*   **Major Update**
    *   Since our `qgame`'s primary dependency is `PySide6`, `qgame.init()` used to take a considerable amount of time to initialize, during which the application would appear to "freeze."
    *   We've made significant improvements! No, we didn't replace the core dependency — rest assured. But with this version, startup speed is blazing fast — comparable to `pygame`, and in my personal opinion, even faster!
*   **CLI Updates**
    *   `qgame new template` now generates an empty template by default.
    *   `qgame package` now supports multiple files and folders, and directly uses `Nuitka`.
*   **UI Updates**
    *   Added a new `SecureInput` class, designed specifically for handling sensitive data like passwords and secret keys.
    *   Input is obfuscated; access is destroyed.
    *   However, it has not been tested yet. If any issues arise, consider using `Nuitka` directly.
*   **New Popups & File Selection**
    *   Added a new `MessageBox` class. As usual, you can simply use `qgame.messagebox` (no uppercase needed).
        *   `show(...)`: Main display method.
        *   `select_file(...)`: Native non‑blocking file dialog.
        *   `info(...)`, `success(...)`, `warning(...)`, `error(...)`, `question(...)`, `confirm(...)`: Preset dialog types.
        *   `add_theme(...)`: Registers a global custom theme.
*   **Bug Fixes**
    *   **Fixed parameter bug in `Example 23`**
        *   The API parameters underwent major changes earlier, and this example was overlooked. It's now fixed.
    *   **Fixed bug where `qgame.show_update_info = False` still displayed notifications**
        *   Previously, setting `qgame.show_update_info = False` would still prompt for updates.
        *   Now, simply set `qgame.show_update_info = False` before calling `qgame.init()` and it will work as expected.
**中文:**
*   **重大更新**
    *   由于我们的`qgame`的主要依赖库是`PySide6`的，因此`qgame.init()`需要初始化较多时间，期间会出现“假死”情况
    *   因此我们做了升级！不是换主要依赖库，放心使用，但这个版本开启速度将会快的飞起！类似`pygame`的启动速度但个人觉得比`pygame`还快！
*   **CIL更新**
    *   `qgame new template`默认直接生成空模板
    *   `qgame package`支持多文件个多文件夹了。且现在直接使用`Nuitka`
    *   但目前未经测试，如果有问题，考虑直接使用`Niutka`
*   **UI更新**
    *   新增`SecureInput`类，专门为密码这类处理敏感数据（如密码、秘钥）
    *   输入即乱码，访问即销毁。
*   **更新弹窗与文件选择**
    *   新增`MessageBox`类，当然如往常，直接`qgame.messagebox`即可，不用大写。
        *   `show(...)`：主要显示方法
        *   `select_file(...)`：原生非阻塞文件对话框
        *   `info(...)`、`success(...)`、`warning(...)`、`error(...)`、`question(...)`、`confirm(...)`：弹窗预设
        *   `add_theme(...)`：注册一个全局自定义主题
*   **修复些许Bug**
    *   **修复`示例23`参数Bug**
        *   之前API参数大改，这里忘了改了。现在修复了
    *   **修复`qgame.show_update_info = False`依然显示Bug**
        *   原先使用`qgame.show_update_info = False`依然会提示升级
        *   但现在只需在使用`qgame.init()`前使用`qgame.show_update_info = False`即可

## [2026.08.15] Version 1.19.1
**English:**
    *   Added a repository! You can now submit bug reports in `Issues` (**on `Gitee`**)!
**中文:**
    *   增加仓库！可以在`Issues`中发送错误报告！（**在`Gitee`**）

## [2026.08.13] Version 1.19.0
**English:**
*   **Editor Updates**
    *   Added a new **Particle Generator Parameter Editor**!
    *   Installation methods:
        *   Via `pip`: `pip install qgame-pe-editor`
        *   Via CLI: `qgame editor pe`
    *   Run it with: `run-qgame-pe-editor`
    *   The UI Editor finally has icons!
**中文:**
*   **编辑器更新**
    *   新增`粒子生成器参数编辑器`！
    *   下载方式：
        *   用`pip`下载：`pip install qgame-pe-editor`
        *   用`CIL`下载：`qgame editor pe`
    *   运行方式：`run-qgame-pe-editor`
    *   UI编辑器终于有图标啦！

## [2026.08.12] Version 1.18.0（**❗❗❗ 版本重大更新/Major Version Update ❗❗❗**）
**English:**
*   **QGame CLI Updates & Fixes**
    *   Fixed an issue where the module would fail to start due to errors caused by missing downloads.
    *   Added a new template:
        *   `mod`: A demo/template for developers showcasing the usage of `script` (Lua modding). Command: `qgame new template mod`
*   **UI Docmentation Updates**
    *   The UI docmentation has become more detalied.
*   **Major Updates to `script` (Lua Modding System)!**
    *   **Anti-Cheat Mechanism: Read-Only Protection**
        *   `SecureProxy`: A security proxy for Python objects that prevents Lua MOD scripts from maliciously tampering with sensitive data. You can specify which attributes are read‑only and which are read‑write; this also affects the original instance.
        *   `ReadOnly`: A one‑click toggle that makes everything read‑only (inherits from `SecureProxy`).
    *   **Syntax Changes**: Lua functions can now be called and executed from anywhere, with return values.
        *   `run()`: Executes once only.
        *   `call()`: Can be invoked from anywhere to execute a function and receive its return value.
        *   `is_err`: Only effective when `call()` is used with `err=False`. Determines whether an error occurred. `echo=True` will output the error. `again=False` outputs the error repeatedly; when `True`, it only outputs non‑duplicate text (comparing only the last output with the current one).
        *   `is_cheat_err()`: Checks whether the function called via `call()` attempted to modify a read‑only variable protected by `SecureProxy`.
        *   `table()`: Converts Python tuples into Lua tables.
*   **Major UI Updates!**
    *   Three new UI components: `ListWidget`, `ComboBox`, and `CheckBox`:
        *   `ListWidget`: An in‑game drag‑and‑drop list container. Common uses: in‑game inventory, key binding remapping, MOD resource pack managers, and developer level lists. Supports: mouse‑dragging for free sorting, per‑item backgrounds/custom stickers, adaptive high‑quality SVG icons, and right‑click developer custom menus.
        *   `ComboBox`: An in‑game dropdown multi‑option configuration combo box. Common uses: graphics quality, physics engine frequency, resolution, and other settings modules.
        *   `CheckBox`: An in‑game toggle checkbox. Common uses: sound effects on/off, full‑screen switching, and collision‑box visibility toggles.
    *   `Panel` Updates:
        *   When the `hide_close` parameter is set to `True`, the close button (arrow) in the upper‑right corner disappears, preventing players from manually closing the panel.
        *   The `close()` function allows developers to manually close the panel.UI
        *   The `connect_close()` function invokes a developer‑provided `Callable` when the panel is closed.
**中文:**
    *   **QGame CIL更新与修复**
        *   修复模块未下载而报错导致启动不了
        *   其`qgame install lib`新增`lupa`库
        *   新增新的模板：
            *   mod：给开发者们演示/模板其`script`（即lua模组）的使用/代码。命令：`qgame new template mod`
    *   **UI文档更新**
        *   UI文档变得详细
    *   `script`这个用于模组编写（lua语言）迎来重大更新！
        *   **防开挂机制**：只读
            *   `SecureProxy`：Python 对象的安全防护代理，防止 Lua MOD 脚本恶意篡改敏感数据。可指定那个只读，那个可读可写，此修改对于原本的instance也生效
            *   `ReadOnly`：一键全部只读（继承自`SecureProxy`）
        *   **语法改变**：使lua中的函数可在任意地方调用执行与返回
            *   `run()`：只执行一次即可
            *   `call()`：在任意地方调用执行与返回
            *   `is_err`：只有`call()`指定`err=False`生效。判断是否报错，`echo=True`会输出其错误。`again=False`会一直输出，为`True`只会输出不重复的文字（只记录上个输出的内容是否与现在的相同）
            *   `is_cheat_err()`：判断其`call()`的函数是否执行了`SecureProxy`被指定只读的变量
            *   `table()`：将Python的元组转化为lua的表
    *   **UI大更新！**
        *   更新3个UI组件：`ListWidget`、`ComboBox`、`CheckBox`：
          *   `ListWidget`：游戏内嵌拖拽式列表容器。常用于：游戏背包、按键映射绑定、MOD 资源包管理器、开发者关卡列表。支持：鼠标拖动自由排序、子项添加背景/精细贴纸、高清 SVG 图标自适应、右键开发者自定义菜单。
          *   `ComboBox`：游戏内嵌下拉多选项配置组合框。常用于：图形材质质量、物理引擎频率、分辨率等多选设置项模块。
          *   `CheckBox`：游戏内嵌复选勾选框。常用于：音效开关、全屏状态切换、物理碰撞包框显隐控制。
        *   `Panel`更新：
            *   参数`hide_close`为`True`时，其右上角的关闭箭头消失，使玩家不能主动关掉其Panel
            *   函数`close()`可以开发者手动关掉其Panel
            *   函数`connect_close()`会在关闭的时调用开发者传入的参数Callable

## [2026.08.10] Version 1.17.0（**❗❗❗ 版本重大更新/Major Version Update ❗❗❗**）
**English:**
*   **QGame CIL Updates**
    *   Added a new subcommand `game` under `new` — finally, it's no longer just `template`!
    *   `game`, as the name suggests, creates small, ready-to-play games in the current directory. Currently includes `shoot` — a 2D shooting game. Developers can build upon this foundation to add more cool stuff!
    *   Usage: `qgame new game shoot`

*   **More Methods Updates**
    *   Added a new `rgb` module, which includes:
        *   The `RGB` class. Use `convert(...)` to convert RGB/RGBA values to 6-digit or 8-digit HEX strings.
    *   Added a new `errors` module, containing some errors developers probably won't need to touch:
        *   `QGameError`, `ArgumentNotFoundError`, `UnboundWindowError`, `ImageNotShowError`, `AliasNotFoundError`

*   **More Utility Methods for the `Entity` Class**
    *   Pygame-level multi-axis positioning and physical boundary alignment:
        *   `bottom_right`, `bottom_left`, `top_right`, `top_left`, `center`, `center_x`, `center_y`, `bottom`, `right`, `top`, `left`
    *   Direction vector derivation:
        *   `direction_to(target) -> tuple`: Returns the normalized unit direction vector `(dx, dy)` pointing to a target (entity or coordinate). Perfect for bullet firing directions and AI movement calculations.
    *   Smart chasing — perfect integration with movement vectors:
        *   `chase(target, dt: float = 1.0)`: Moves toward a target position or entity (fully supports delta‑time frame-rate independence).
    *   Built‑in AABB collision detection without external dependencies:
        *   `distance_to(target) -> float`: Quickly calculates the pixel distance from the current entity to another entity or coordinate.
        *   `is_colliding_with(other) -> bool`: Quickly checks if the current entity overlaps with another object (Entity / 4‑tuple / Rect) via AABB intersection. Designed to prevent circular references; no external modules required; instantaneous check.
        *   `angle_to(target, degrees: bool = True) -> float`: Quickly calculates the rotation angle (in degrees or radians) from the current entity toward the target.
        *   `clamp_to_screen(screen_width: int, screen_height: int)`: Prevents the player or entity from moving outside the game window (invisible wall constraint).
        *   `is_off_screen(screen_width: int, screen_height: int, margin: float = 50.0) -> bool`: Checks if the entity has completely left the screen bounds (with a configurable safety margin).

*   **More Collision Detection (Pygame‑style)**
    *   `check_sprite_collide(sprite, targets: list, dokill: bool = False) -> list`: [Batch entity collision] Detects if a single source entity collides with any entity in a target group (list).
    *   `check_group_collide(group1: list, group2: list, dokill1: bool = False, dokill2: bool = False) -> dict`: [Group‑vs‑group batch collision] Detects intersections between two entity groups (e.g., friendly bullets vs enemy monsters).

*   **Window Missed Features**
    *   I just realized the `window` module lacked width and height getters! Why didn't anyone mention this? 🤔 (On second thought...) I guess there wasn't anywhere to mention it... 😅
    *   Added methods:
        *   `get_width(window=None) -> int`
        *   `get_height(window=None) -> int`
        *   `get_size(window=None) -> int | tuple[int, int]`
    *   Note: These values update in real time as the window resizes!

*   **Mod Developers, Rejoice!**
    *   Added the `qgame.script.script` module, which includes:
        *   `run(extra_context: Dict[str, Any] = None)`: Runs the script, with optional `extra_context` to temporarily add or override context variables at runtime.
        *   `get_function(name: str)`: Extracts a global Lua function by name, returning a Python‑callable object.
        *   `call(func_name: str, *args)`: Directly calls a Lua function from the Python side with arguments.
            *   `func_name`: The name of the Lua function.
            *   `args`: The arguments to pass to the Lua function.
    *   Worried about Chinese garbled text in Windows CMD due to GBK encoding? No worries! We've replaced all Lua `print()` calls with Python's `print()` under the hood — problem solved! 😎
**中文:**
*   **QGame CIL 更新**
    *   命令新增`new`的子命令`game`，对！终于不是`template`单独一个啦！
    *   `game`，顾名思义，就是在当前目录下创建一些点开即玩的小游戏。目前有`shoot`2D建议枪战，开发者们可以在此基础上新增更多好玩的东西！
    *   运行命令：`qgame new game shoot`
*   **依旧methods更新**
    *   新增`rgb`文件！里面有：
        *   `RGB`类。用`convert(...)`函数来将RGB/RGBA转化为6位HEX值或8位HEX值
    *   新增`errors`文件！里面有一些开发者可能不会用到的错误：
        *   `QGameError`、`ArgumentNotFoundError`、`UnboundWindowError`、`ImageNotShowError`、`AliasNotFoundError`
*   **`Entity`类的更多实用方法**
    *   Pygame 级别的“几”轴定位与物理边界对齐系统：
        *   `bottom_right`、`bottom_left`、`top_right`、`top_left`、`center`、`center_x`、`center_y`、`bottom`、`right`、`top`、`left`
    *   极致方向推导器（方向向量获取）
        *   `direction_to(target) -> tuple`：获取指向目标（实体或坐标）的归一化单位方向向量 (dx, dy)。极度适合子弹发射方向、AI 行进方向计算
    *   智能追击 (chase) —— 完美接通底盘向量
        *   `chase(target, dt: float = 1.0)`：向目标位置或目标实体移动（完美支持 dt 帧率独立化）
    *   无需外部引用的内置 AABB 单体强力相撞校验
        *   `distance_to(target) -> float`：快速计算当前实体到另一个实体或坐标的像素距离
        *   `is_colliding_with(other) -> bool`：快速判定当前实体是否与另一个对象（Entity / 4元组 / Rect）发生了 AABB 相交重叠。防循环引用设计，不依赖外部模块，瞬间判定
        *   `angle_to(target, degrees: bool = True) -> float`：快速计算当前实体指向目标的旋转方向（弧度或角度）
        *   `clamp_to_screen(screen_width: int, screen_height: int)`：强制玩家或实体不能移出游戏窗口（空气墙约束）
        *   `is_off_screen(screen_width: int, screen_height: int, margin: float = 50.0) -> bool`：判定是否完全脱离游戏屏幕范围（带安全缓冲边界）
*   **更多碰撞检测（类pygame）**
    *   `check_sprite_collide(sprite, targets: list, dokill: bool = False) -> list`：[批实体碰撞] 检测单个源实体是否与目标群组 (list) 中的任意实体相撞。
    *   `check_group_collide(group1: list, group2: list, dokill1: bool = False, dokill2: bool = False) -> dict`：[组与组批量碰撞] 检测两个实体阵营 (例如：己方子弹阵营 vs 敌方怪物阵营) 的相交情况。
*   **window补漏**
    *   我现在才发现window缺了获取高度宽度！怎么没人说一下啊？🤔（仔细一想）好像也没有能说的地方啊……😅
    *   新增方法：
        *   `get_width(window=None) -> int`
        *   `get_height(window=None) -> int`
        *   `get_size(window=None) -> int | tuple[int, int]`
        *   注：都是随窗口高度实时变化的哦
*   **Mod开发者狂喜！**
    *   新增`qgame.script.script`方法，其中有：
        *   `run(extra_context: Dict[str, Any] = None)`：顾名思义，就是运行，但可以用`extra_context`来运行时临时追加或覆盖的上下文变量
        *   `get_function(name: str)`：从 Lua 脚本中提取指定的全局 Lua 函数，使其变为 Python 可调用对象
        *   `call(func_name: str, *args)`：直接从 Python 侧调用 Lua 内部定义的某个函数并传参。
            * func_name: Lua 函数名
            * args: 传给 Lua 函数的参数
    *   担心Window命令行因采用GBK格式而导致中文乱码？放心！我们直接把Lua里的所有`print()`代码都替换成了Python的`print()`！😎直接解决！

## [2026.08.09] Version 1.16.0
**English:**
*   **❗ Major Breakthrough: .qres Asset Suite is Here ❗**
    *   Added the brand-new `resource` module (`resource.py`)! You can now declare structure categories in static plaintext files, eliminating hardcoded asset dictionaries.
    *   Download:
        * Download via **Gitee**: https://gitee.com/watermelon-juice-code/qgame-resource-support/blob/master/qgame-resource-support-1.0.0.vsix
        * Download via **Baidu Netdisk**: https://pan.baidu.com/disk/main?from=homeFlow#/index?category=all&path=%2F%E5%85%AC%E5%BC%80%E6%96%87%E4%BB%B6%E5%A4%B9  Extraction code: `code`
    * Select `qgame-resource-support-1.0.0.vsix` and download it.
* Download via **Quark Cloud Drive**: https://pan.quark.cn/s/eeb366929d4b  Extraction code: `TTt3`
    *   **Class GroupRes**: Supports dual-access modes via Python characteristics: Dot property lookup (e.g., `res.player.hp`) or dictionary string keys (e.g., `res["player"]["hp"]`).
    *   **Class Resource**: Includes the powerful parsing syntax `load()` / `loads()`. It features smart reference mapping (e.g., `<hp> hp_max` automatically copies the parsed value of `<hp_max>`), automatic zero-value generation for empty parameters, and rigid type evaluation.
    *   Also supports `convert(py_class)` to instantly extract structured schemas from native Python classes, and `to_qres()` to write modifications back safely.
*   **Official Tooling: VSCode companion is live!**
    *   Introducing the official developer extension **`qgame-resource-support`** to safeguard your `.qres` scripts.
    *   Supports dynamic type highlighting and smart token snippets.
    *   Built-in compiler-grade Linter: Warns on cross-group variable duplicates, conflicts on redefined variables, and strictly flags variables starting with digits (e.g., `<1player>` -> Red compilation error) to prevent Python crashes.
    *   Silenced VSCode's generic `"abc"` suggestion noise for a pure, distraction-free `<...>` coding experience.

**中文:**
*   **❗ 核心突破：.qres 专属资产配置套件登场 ❗**
    *   新增全新 `resource` 模块（物理文件 `resource.py`），支持以纯文本 `.qres` 格式统筹管理游戏全量静态、动态配置数据，彻底告别在代码中硬编码字典的时代！
    *   下载：
        * 使用`Gitee`下载：https://gitee.com/watermelon-juice-code/qgame-resource-support/blob/master/qgame-resource-support-1.0.0.vsix
        * 使用`百度网盘`下载：https://pan.baidu.com/disk/main?from=homeFlow#/index?category=all&path=%2F%E5%85%AC%E5%BC%80%E6%96%87%E4%BB%B6%E5%A4%B9 提取码：code
            *   选择`qgame-resource-support-1.0.0.vsix`并下载
        * 使用`夸克网盘`下载：https://pan.quark.cn/s/eeb366929d4b 提取码：TTt3
    *   **GroupRes 容器**：为游戏存取量身打造。支持双向数据穿透，你既可以用点号（`res.player.hp`）像访问属性一样读取，也可以用字典键（`res["player"]["hp"]`）进行下标存取！
    *   **Resource 算子**：通过核心 `load` / `loads` 管道无损读盘。支持**变量间交叉引用**（如：`<hp> hp_max` 会自动把之前算好的 hp_max 值分派给 hp）、类型零值空填充（例如写 `list <bag>` 自动补全空列表 `[]`），以及严格的硬件类型转换约束。
    *   支持 `convert(py_class)` 一键将 Python 类嵌套结构抽象为 Resource 数据树；并提供 `to_qres()` / `save()` 实现改写后数据的无损回写导出。
*   **官方配套：VSCode 专属插件同步上架！**
    *   QGame 专属语言套件 **`qgame-resource-support`** 正式发布。
    *   深度配置了静态高亮体系与快捷模板 Snippets。
    *   内置“真·编译器级静态诊断”：对多重重名进行强碰撞拦截，并且**严格校验 Python 命名标识符**（如果写了数字开头的 `<1player>`，编辑器会直接画红线阻断），确保在写配置时完美拦截运行期崩溃。
    *   强制清干净了 VSCode 恶心人的 `'abc'` 历史单词联想，输入 `<` 时只弹出干净的专属类型和变量组。

## [2026.08.08] Version 1.15.0
**English:**
*   **Methods Fixes & Updates**
    *   Fixed the `core import error` in `1.14.1`. The cause? 🍉 mistyped the module name 🤣 ~~（🍉：🤬）~~（🍉：😅）
    *   Added a new `hash` module, which includes:
        *   `textToHash`: A lightweight function that converts text into a numeric hash. Not recommended for critical use cases like user passwords. For those, see below.
        *   If `bcrypt` is installed:
            *   `hash_password`: Encrypts a password using `bcrypt`. Generates a different hash each time.
            *   `verify_password`: Verifies a password against its `bcrypt` hash. Returns `True` if the password matches, otherwise `False`.
        *   If `bcrypt` is **not** installed:
            *   `hash_password`: Salts the password, then hashes it 100,000 times to resist brute-force attacks. (Don't worry — 100,000 iterations may sound slow, but it's actually done in the blink of an eye.)
            *   `verify_password`: Same parameters as above. Verifies the password against the stored hash and returns `True` if they match, otherwise `False`.
        *   If `bcrypt` is not installed, you'll see a reminder. If you find it annoying, just set `qgame.show_hash_info = False` to disable it.
**中文:**
*   **methods修复与更新**
    *   `1.14.1`将`core导入错误`给修复。原因是🍉把模块名给写错了🤣 ~~（🍉：🤬）~~（🍉：😅）
    *   新增`hash`文件！里面有：
        *   `textToHash`：轻量函数，将文本转化为一串数字。不建议在非常重要如用户密码这样的场景中使用。如果想，参考下面
        *   如果安装了`bcrypt`：
            *   `hash_password`：使用`bcrypt`加密密码。每次都不一样
            *   `verify_password`：使用`bcrypt`解密密码并判断参数1`password`是否一样。如果一样，返回`True`，反之返回`False`
        *   如果没安装`bcrypt`：
            *   `hash_password`：首先将会进行加盐，其次爹10万次，防止破解（别听到10万就以为很慢，其实也就一眨眼的功夫），最后返回结果
            *   `verify_password`：参数同上。破解一样，最后判断参数1`password`是否一样，如果一样，返回`True`，反之返回`False`
        *   如果没安装`bcrypt`，那么会提醒你，一样，觉得烦的直接：`qgame.show_hash_info = False`就行力

## [2026.08.07] Version 1.14.0
**English:**
*   **❗ Major Update ❗**
    *   If you find QGame's update notifications too annoying, just set `qgame.show_update_info = False`!
    *   Is that major enough for you? 😜
*   **Methods Update**
    *   Continued enhancements to the `Tuple` class, making it behave more like `list`/`dict` — though it still returns `tuple` types! 🤣
    *   Added a `modify` module, which includes:
        *   `timer`: Measures function execution time and assigns the result to `result_time`. (Note: `result_time` defaults to `None` 😉)
        *   `deprecated`: Marks a function as deprecated.
        *   `deprecated_class`: Same as above, but for classes.
*   **Animation Update**
    *   Added the `AnimatedSprite` class, eliminating the pain of manually managing frame switching with timers! 😎
*   **Audio Update**
    *   Added the `SpatialSound` 2D spatial audio generator class.
*   **Particle System Update**
    *   Added the `add_collision_rule` method, allowing particles to trigger specified actions when colliding with something.
**中文:**
*   **❗ 重磅更新 ❗**
    *   如果你觉得`QGame`的更新提示太烦了，直接：`qgame.show_update_info = False`就行！
    *   就问你重不重磅吗？😜
*   **methods更新**
    *   继续加强了`Tuple`类，使他更像`list`/`dict`那样！只不过都是返回`tuple`类型的🤣
    *   新增`modify`文件！里面有：
        *   `timer`：函数运行时间并将`result_time`赋为此值。主：`result_time`默认是`None`哦😉
        *   `deprecated`：用于给函数标记已弃用
        *   `deprecated_class`：同上，只不过是对于类使用的
*   **动画更新**
    *   新增`AnimatedSprite`类，彻底解决手动在外面用计时器切图纸贴图的痛点！😎
*   **音频更新**
    *   新增`SpatialSound`2D 空间声学发生器类，
*   **粒子系统更新**
    *   新增`add_collision_rule`方法，实现粒子的碰撞到某个东西时做出参数二指定的动作

## [2026.08.06] Version 1.13.0
**English:**
*   **❗Breaking Change**
    *   All UI positions are now represented using `tuple`.
*   **New Methods Added**
    *   The author casually added a couple of methods for fun 😜
    *   `Person` and `Tuple`
    *   `Person`: Currently stores birthday and age, along with conversion between them.
    *   `Tuple`: For now, it just adds a `dict`-like `get()` method. More practical or abstract methods may be added in the future 😜
*   **UI Editor Update**: Refer to the [UI Editor Official Documentation](https://pypi.org/project/qgame-ui-editor)
**中文:**
*   **❗破坏性变更**
    *   所有UI位置使用元组`tuple`表示。
*   **新增methods**
    *   作者无聊随便搞了个methods，
    *   `Person`和`Tuple`
    *   `Person`目前就纯存生日和年龄，与之间的换算
    *   `Tuple`，说白了，目前就是加了个类`dict`的`get()`方法，以后可能会加更多使用或抽象的方法😜
*   **UI编辑器更新**，参考[UI编辑器官方文档](https://pypi.org/project/qgame-ui-editor)

### [2026.08.05] Version 1.12.0
**English:**
*   **UI Updates**
    *   Most UI components now support images, including SVG format.
    *   Added a new `CodeText` class that functions like the code editors in Visual Studio Code or Visual Studio, featuring regex-based syntax highlighting, IDE-style tooltips, adaptive tooltip height, and Ctrl + mouse wheel zoom in/out.
**中文:**
*   **UI更新**
    *   UI大部分都已支持图像，包括svg格式
    *   新增`CodeText`类，可以像`Visual Studio Code`或`Visual Studio`代码编辑器那样，正则表达式指定规则高亮、IDE提示、提示框（自适应文本高度）、Ctrl+鼠标滚轮放大缩小等

### [2026.08.03] Version 1.11.0
**English:**
*   **UI Visual Editor**
    *   Say goodbye to writing UI code line by line. Use the drag-and-drop visual UI editor: QGame Visual UI Editor.
    *   However, this package is not included by default. Please use:
        *   `pip install qgame-ui-editor`
        *   Or use the CLI command:
        *   `qgame editor ui`
    *   Then run `run-qgame-ui-editor` to launch it.
*   **Creative Image & SVG Glyph Engine (`qgame.CustomFont`)**
    *   Say goodbye to massive .ttf font assets! We introduced the highly anticipated `CustomFont` sprite/vector font compartment.
    *   Supports loading single character graphics directly (e.g. `a.png` maps to 'a', `zhong.svg` maps to '中'), instantly constructing high-fidelity custom stylized typography.
    *   Built-in bulk-loading pipeline: Call `font.load_dir('fonts/')` to scan an entire character asset folder automatically.

**中文:**
*   **UI可视化编辑器**
    *   告别手写一个一个的UI代码，使用拖拽填写的可视化UI：QGame 可视化UI编辑器
    *   但该包不包含，请使用：
        *   `pip install qgame-ui-editor`
        *   或使用CLI命令行工具
        *   `qgame editor ui`
    *   然后使用`run-qgame-ui-editor`
*   **手绘图片与 SVG 矢量字符引擎 (`qgame.CustomFont`)**
    *   彻底告别动辄十几兆、跨平台易缺失的 `.ttf` 字体文件！新增手绘创意字/像素字/矢量字装载器 `CustomFont`。
    *   支持将单独的图片字符和 SVG 绑定为文字切片（例如 `a.png` 代表 'a'，`中.svg` 代表 '中'，一个汉字算一个字符）。
    *   支持一键批量扫盘：调用 `font.load_dir('images/my_pixel_font/')` 自动提取无缝装载整个字符字库。

### [2026.08.01] Version 1.10.0
**English:**
*   **Infinite SVG Vector Graphics Engine**
    *   No more pixelation under 4K/8K resolution! Built-in native support for SVG vector files through `qgame.SVG` and `draw.svg()`.
    *   Calculates vector bézier paths directly at draw-time (real-time rasterization) instead of stretching basic bitmap pixels.
*   **AAA G-Force Motion Blur Core**
    *   Added `draw.motion_blur_image()`, enabling high-fidelity linear multi-sample motion blur and G-force camera-lag vibrations.
    *   Perfect for racing velocity stretches, high-frequency camera-shaking, and sword-swing sweeps.
*   **Fully-Managed Diagnostic & CLI Setup Manager**
    *   Revamped `cli.py` to completely eliminate CMD/PowerShell GBK Chinese code page encoding crashes by silently hooking Windows kernel `chcp 65001` and piping standard out streams as UTF-8.
    *   Multi-tier environment and library health checks:
        *   `qgame doctor package`: Diagnosis compiler chains (Nuitka, GCC, PySide6-deploy).
        *   `qgame doctor lib`: Scans optional active runtime libraries.
    *   Replaced the old single-purpose cmd `qgame icon install` with `qgame install lib` — an interactive, smart library installer showing dependency package sizes and descriptive usages.
*   **Real-time Voice Chat Network Kit**
    *   Provides high-frequency UDP low-latency LAN voice broadcasting server & client pipelines. Included in library metadata as an optional extension.

**中文:**
*   **无限分辨率 SVG 矢量图形引擎**
    *   彻底无视 4K / 8K 全屏缩放！新增矢量图形原生读取类 `qgame.SVG` 与专属矢量渲染管道 `draw.svg()`。
    *   直接在画布的浮点精度上进行实时几何栅格化，而非生粗暴缩放位图像素，保证图标与 UI 永远锐利。
*   **AAA 级推背感动态模糊核心**
    *   新增 `draw.motion_blur_image()`，支持多样本（Samples）线性采样以及局部引擎颤抖。
    *   专为赛车高速飙车残影、格斗刀偏残光轨迹、以及高频暴击震颤提供电影级动态模糊。
*   **全自适应 CLI 诊断与一键包管理系统**
    *   彻底修复了 CMD 在 GBK(936) 编码下运行乱码的顽疾！`cli.py` 初始化优先注入 Windows 底层 `chcp 65001` 指令并强制重组标准流为 UTF-8。
    *   分层式环境和类包体检：
        *   `qgame doctor package`：诊断物理编译与打包环境（Nuitka、GCC 编译器、部署管线是否健在）。
        *   `qgame doctor lib`：扫描第三方游戏多媒体扩展库安装情况。
    *   去除了原鸡肋的 `qgame icon install`，升级为 `qgame install lib` 极客级交互式安装面板：实时显示大小、说明，支持 A 键一键修复以及数字特定安装。
*   **网络音频连麦与环境音交互**
    *   网络库新增网络低时延 UDP 音频通信套件。作为可选多媒体功能包无缝对接 QGame 一键安装流程。


### [2026.07.31] Version 1.9.0
**English:**
*   **Grouping (`qgame.Group`)**
    *   Groups `qgame.Entity` objects together. Entities added to the group will share coordinates, as `qgame.Group` provides a coordinate attribute.
    *   Therefore, you can change the coordinates of a `qgame.Group` to update the coordinates of all `qgame.Entity` objects within it.
*   **New Version Check**
    *   Version `1.9.0` and above include a new version check. Every time `qgame` is imported, it fetches the latest version from PyPI and compares it with the local version. If the local version is older, a prominent color warning will be displayed.
    *   Worried about garbled text in the command prompt? Don't be – we use `ctypes` to enable ANSI rendering support in the terminal. For older computers, it will display plain text without `\033[93m` escape codes.
    *   Worried about network latency causing lag? We've implemented asynchronous checks to avoid blocking.
*   **`qgame.load()` Bug**
    *   In versions prior to `1.9.0`, the `load()` function read from `.qgame/settings.json` in the current directory. However, since the generated template resides in the `src/` directory, the file could not be found, and no error message was displayed.
    *   This has been fixed in version `1.9.0` and above.
*   **New Command Argument**
    *   **`platformer`**: Run the command `qgame new template --platformer` to generate a platformer game template.

**中文:**
*   **分组 (`qgame.Group`)**
    *   将`qgame.Entity`进行分组，加入组内的将共享坐标，`qgame.Group`提供了坐标这一属性
    *   因此你可以改变`qgame.Group`的坐标来改变加入其中所有的`qgame.Entity`的坐标
*   **新版本检测**
    *   在`1.9.0`版本及以上提供了新版本检测，每次导入qgame时都会从`PyPI`上获取最新版本与本地版本比较，如果小于则会用醒目的颜色提醒你。
    *   如果担心`cmd`显示的是想那种乱码？那就别担心了，我们使用`ctypes`打开了cmd的`ANSI`的渲染支持。如果是老电脑？那就直接显示原本字样，而不会带有`\033[93m`
    *   如果担心网速不好会卡顿？放心，我们特意为此做了异步
*   **`qgame.load()` Bug**
    *   在`1.9.0`之前的版本，load函数读取的是当前路径的`.qgame/settings/json`，但因生成的模板是在`src/`目录下的，因此找不到，且没找到不会输出任何文字
    *   在`1.9.0`版本及以上得到了修复
*   **新增命令参数**
    *   **`platformer`**，执行命令：`qgame new template --platformer`就会生成一个平台跳跃游戏的模板

### [2026.07.30] Version 1.8.0
**English:**
*   **New Commands**
    *   **`package`**: Packages `./src/main.py` into an executable `.exe` file. If an error occurs during the packaging process, please check whether PySide6 is installed (or download the latest version) or verify that GCC is installed.
    *   **`doctor`**: If you are unsure whether Nuitka or GCC is installed, use **`qgame doctor`**.
    *   **`icon convert`**: Converts a PNG image at the specified path into an ICO file. Usage: `qgame icon convert player.png --output app.ico`
    *   **`icon install`**: If an icon-related error occurs, please use `qgame icon install` to download the required dependencies.

**中文:**
*   **新增命令**
    *   **`package`**，将`./src/main.py`打包成exe可执行文件。如果生成exe过程中，如果报错，请检查是否安装PySide6（或下载新版）或检查是否下载gcc
    *   **`doctor`**，如果不知道有没有Nuitka或gcc，使用**`qgame doctor`**
    *   **`icon convert`**，将指定路径下的png图片转化成ico文件，使用`qgame icon convert player.png --output app.ico`
    *   **`icon install`**，如果icon报错，请使用`qgame icon install`下载依赖


### [2026.07.30] Version 1.7.0

**English:**
*   **Command-Line Scaffolding (`qgame new template`)**
    *   Introduces the engine CLI code generator. Developers can spawn standard directory directories and settings configs instantly via shell prompts.
*   **Numerical Range Adjuster (`Slider`)**
    *   Added a modern sliding track widget to `qgame.ui` allowing mouse drag interactions to map bounded float or integer values. 
*   **Typewriter Dialogue System (`DialogBox`)**
    *   A DPI-responsive dialogue canvas view, featuring character text typewriter animation, custom emotion icons, and routing choices. 
*   **Visual Logic Tree Builder (`qgame_dialog_editor`)**
    *   A standalone visual graph editor with built-in dark theme CSS, dynamic node reference locking, and JSON export pipelines.
*   **Debugger Window Update (`qgame.debugger`)**
    *   Values in the debugger window can now be modified and take effect immediately.
*   **Interactive Modifications in Debugger (DebugInspector)**
    *   Monitored items in the debugger can now be clicked to open popup text input prompts. Values are parsed with automated type restoration (AST evaluation) and updated instantly back into the running game loop.

**中文:**
*   **脚手架生成器 (`qgame new template`)**：
    *   引入引擎 CLI 工具，开发者能够在终端一键初始化游戏开发目录及全套配置文件。
*   **数值范围调节器 (`Slider`)**：
    *   在 `qgame.ui` 下新增了拖拽条组件，支持玩家通过拖动滑块直观地调节指定极值区间内的参数。
*   **多路由分支对话框 (`DialogBox`)**：
    *   支持视口 DPI 自适应缩放的会话显示面板，内置打字机逐字出屏动画、Emoji/本地贴图头像解析和分支选择器。
*   **可视化对话编辑器 (`qgame_dialog_editor`)**：
    *   内置的自举可视化设计工具。支持无缝逻辑链校验、节点属性配置，并能一键导出为游戏读取的标准 JSON 树。
*   **调试窗口变量反射修改 (`DebugInspector`)**：
    *   调试面板监控项目现已支持鼠标点击修改。自动逆向还原基础类型（布尔值、浮点数、数组等），即改即用，免去重开游戏的时间开销。

### [2026.07.29] Version 1.6.0
**English:**
*   **Debug-window**
    *   **Cross-Window Monitor Panel (`DebugInspector`)**
      - Eliminates messy console terminal `print()` spam and game loop freezing caused by code breakpoints.
      - Launches a secondary debug window. It does not require any drawing logic in the main loop; rendering is automatically piped through `qgame.window.update()`.
    *   ***Lifecycle Segregation (`is_debug` Flag)**
      - Introduces a dedicated debug window identifier. Evaluated windows are excluded from `get_all_windows()` by default.
      - The application exits cleanly when the main game window is closed. Closing the debugger independently will not affect the main game execution.
    *   ***Lambda Dynamic Binding & Defensive Sandboxing**
      - Variables are registered using `lambda` functions. The inspector queries objects at render time, remaining resilient even if variables are re-instantiated.
      - Built-in exception handling captures runtime issues (e.g., `AttributeError` or `ZeroDivisionError`) and renders them in highlighted red instead of crashing the window.
    *   **Viewport Clipping & Smooth Scroll Engine**
      - Tracks wheel events combined with viewport clipping (`QPainter.setClipRect`) to make data rows slide smoothly within a restricted region without overlaying the header.
      - Slim VS Code-style vertical scrollbar on the right. Height dynamically scales based on the quantity of monitored items.
    *   ***Adaptive Layout & Scalable Typography**
      - Supports customization via a `font_size` argument in `debugger.init`. Proportionally converts line height, padding gaps, char-cut limits, and scroll steps on-the-fly.

*   **Multi-window update**: QGame now supports multiple windows 😄!
    *   Use the `qgame.window.get_all_windows()` function to retrieve all windows; returns a `list`.
*   **Full-screen update**: Added a new parameter `scaling_mode` in the initialization function `set_settings` to specify the full-screen scaling behavior:
    *   `letterbox`: (Classic default mode) Maintains the design aspect ratio; fills the remaining areas with black bars.
    *   `crop`: (Aspect fill masking mode) The view fills the entire screen without stretching, but automatically and symmetrically crops any overflowing content (e.g., left/right or top/bottom edges).
    *   `stretch`: (Forced stretch mode) The view is forcibly stretched to match the full-screen aspect ratio, ignoring visual quality loss.
    *   `adaptive`: (Viewport-responsive mode, similar to a browser) The canvas resolution dynamically adjusts with window resizing (including full-screen). For example, when the physical resolution becomes 2560×1440, the canvas also becomes 2560×1440 with a 1:1 responsive coordinate mapping.


**中文:**
*   **调试窗口**：
    *   **跨窗口监视面板 (`DebugInspector`)**
      - 彻底告别繁琐的控制台 `print()` 刷屏以及断点调试对游戏帧率的打断。
      - 独立多开一个调试窗口，无需在游戏循环中写任何绘制语句，全程由底层 `qgame.window.update()` 自动驱动渲染。
    *   **生命周期隔离机制 (`is_debug` Flag)**
      - 引入调试窗口标识，并在物理窗口管理器 `get_all_windows()` 中默认隐式滤除。
      - 当玩家关闭游戏主窗口时，程序会立即干净地终止；而单独关闭调试窗口不会对主游戏运行产生干扰。
    *   ***Lambda 动态绑定与安全沙盒**
      - 推荐使用 `lambda` 匿名函数注册观察变量。调试器在渲染时会动态拉取最新内存指向。
      - 内部集成异常捕获，即使监控的目标变量在游戏中因销毁而引发 `AttributeError` 或 `ZeroDivisionError`，调试器窗口也不会崩溃，而是高亮爆红显示异常类型。
    *   ***视口裁剪与平滑滚动系统**
      - 捕获鼠标滚轮事件，配合视口剪裁技术（`QPainter.setClipRect`），确保数据行在中间活动区平滑平移，不会溢出盖住顶部的标题栏。
      - VS Code 风格的右侧指示滑动游块，高度随挂载变量的数量自动缩放。
    *   ***动态排版与自适应字号**
      - `debugger.init` 支持传入自定义字号 `font_size`，内部会对页眉高度、行高、文字截断字符数和滚动步距进行比例换算，解决大字号重叠溢出的问题。
*   **多窗口更新**，QGame支持多窗口啦😄！
    *   使用`qgame.window.get_all_windows()`函数获取所有窗口，返回一个`list`
*   **全屏更新**，在初始化函数`set_settings`中新增参数`scaling_mode`，用于指定全屏的模式:
    *   `letterbox`: （经典默认模式）：保持设计比例，不足区域补充黑色填充条。
    *   `crop`: (画幅剪裁遮罩模式，即 Aspect Fill)：画面铺满整个屏幕不被拉伸，但自动对称裁切掉超出屏幕的多余部分（如左右或上下）。
    *   `stretch`: (强行拉伸模式)：画面无视画质损失，强行贴合全屏比例。
    *   `adaptive`: (视口自适应响应模式，类似浏览器)：画布分辨率随窗口改变（包括全屏）而动态扩增/缩小（例如：物理分辨率变成 2560x1440 时，画布变成 2560x1440，坐标系统为 1:1 响应）。

### [2026.07.28] Version 1.5.1
**English**
*   **Fixed the level editor**, now you can use: `run-qgame-editor`

**中文:**
*   **修复关卡编辑器**，现在使用：`run-qgame-editor`即可

### [2026.07.28] Version 1.5.0

**English:**
*   **Refactored Collision Module (`qgame.collision`)**: Integrated multi-track collider registers: `add_active_collider` (collidable & block pathfinding nodes), and `add_collider` (bounds only, ignored by search algorithm).
*   **Added Game AI & Automation Module (`qgame.ai`)**:
    *   `PathFinder`: Self-adapting pixel-to-grid grid coordinates search utilizing A* logic.
    *   `TrajectoryPredictor`: Solves future positions based on user velocity & quadratic acceleration estimation logs.
    *   `InputPredictor`: Probability forecasting next action keys based on Markov n-gram transition matrix.

**中文:**
*   **经典碰撞模块重构重设计 (`qgame.collision`)**：细化加入了多轨碰撞容器结构。其中 `add_active_collider` 增加参与碰撞箱（强制避障），`add_collider` 增加普通碰撞箱（事件与限位，不扰乱 AI 路线）。
*   **新增人工智能控制套件 (`qgame.ai`)**：
    *   `PathFinder` (寻路机)：集成 A* 格栅搜寻，支持 8 方向平滑移动及高画质像素与网格自适应算法。
    *   `TrajectoryPredictor` (运动预判器)：通过二阶物理差分方程，基于历史坐标实时外推未来位置以作包夹拦截。
    *   `InputPredictor` (键鼠预判器)：自带有状态转移矩阵，能对连续的操作连招逻辑做出提前防空与预警判定。

[2026.07.28] Version 1.4.0
**English:**
*   **Added Anti-Freeze Task Loader (`ProgressBar.load_tasks`):**
    *   Designed for complex task loading processes (e.g. slicing asset decryption or network sync).
    *   Accepts a batch array of functions, automatically processing and ticking Qt event queues after executing each task block, ensuring game windows will never throw windows freeze / OS "Not Responding" alerts.
*   **Added Engine Splash Screen Controller (`qgame.show_splash`)**: Easily show high-fidelity fade transitions for studio logos before loading.
    *   Parameters: `show_splash(image_path=None, duration=2.0, echo_error=True)`.
    *   No-Image-Safety: If the specified image path does not exist, QGame will dynamically draw a technology-blue fallback studio logo and save it to `qgame/images/QGameOnStartingImage.png` to avoid crashes.
    *   Embedded QEventLoop: Fades transparent masks dynamically without halting win desktop resizing.
*   **Added Game Video Playback Component (`VideoPlayer`):**
    *   Designed for processing full-screen opening CG movies, dynamic cutscenes, or loopable video-driven UI backgrounds.
    *   Features: `play()`, `pause()`, `stop()`, `set_volume(volume: float)`, `set_loop(loop: bool)`, and finished scene transitions `connect_finished(callback)`.
    *   Failsafe Mode: If the host lacks media source decoding packages, it falls back smoothly to avoid fatal engine crashes.
*   **Added Non-Blocking Network Component Framework (`qgame.network`):**
    *   Designed for processing multiplayer synchronization without spawning tricky system Python loops.
    *   Provides event-driven callback hooks for easy packet parsing.
    *   Submodules:
        *   `network.UDPNetworkServer` & `network.UDPNetworkClient` for real-time game positioning.
        *   `network.WSNetworkServer` & `network.WSNetworkClient` for lobby chatting and state alignment.
  
**中文:**
*   **新增防死挂起加载器 (`ProgressBar.load_tasks`)**：
    *   针对复杂资产读取、切图或数据解密等高开销初始化关卡。
    *   接收无参函数组成的加载列表，核心在执行单个任务间隙全自动重刷系统事件、刷新进度，彻底排除客户端“未响应”沙漏警报。
*   **新增游戏引擎启动闪屏控制 (`qgame.show_splash`)**：在游戏启动前展示带动态淡入淡出滤镜的工作室大片 Logo。
    *   参数支持形式：`show_splash(image_path=None, duration=2.0, echo_error=True)`。
    *   文件缺失卫士：若无指定路径，将自动读取内置闪屏图；当内置资源也不存在时，会自动在画布上矢手高密绘制一张 QGame 蓝色圆形极简 Logo 存至磁盘（`qgame/images` 下），保护引擎逻辑稳定不倒。
    *   无锁心跳：在不中断事件队列获取的条件下，流畅地处理淡入淡出遮罩。
*   **新增剧情与转场视频播放器芯片 (`VideoPlayer`)**：
    *   针对开场大片 CG、关卡剧情重塑、动态背景视频 UI 的专业原生多媒体封装。
    *   核心指令：`play()` (播放)、`pause()` (暂停)、`stop()` (停止归零)、`set_volume(float)` (音量，0.0~1.0)、`set_loop(bool)` (配置循环状态)、`connect_finished(callback)` (完结跳过事件槽)。
    *   智能减震：运行环境或缺失 ffmpeg/多媒体驱动时自动做平滑捕获不闪退，避免影响主游戏编译。
*   **新增低耦合事件网络骨架库 (`qgame.network`)**：
    *   基于 Qt 事件系统封装的无锁非阻塞局域网及公网联机方案。
    *   剥离了繁琐的多线程和同步死锁，将复杂的网络连接重塑为极简回调式交互。
    *   核心大类：
        *   `network.UDPNetworkServer` / `network.UDPNetworkClient`：对应高速帧同步、大弹幕交互场景。
        *   `network.WSNetworkServer` / `network.WSNetworkClient`：对应回合制决策、聊天大厅与云备份接入场景。

### [2026.07.27] Version 1.3.0

**English:**
*   **Added Declarative Tween Animation Controller (`qgame.tween`)**: Introducing fluid physical polish ("Juice") to games and UI systems without manual timer calculations.
    *   Supports 17 standard easing equations (e.g., `elastic_out`, `bounce_out`, `sine_in_out`, etc.).
    *   Allows chaining parameters like `delay`, `duration`, and `on_complete` callbacks.
    *   Dynamically recalculates screen geometries during UI tweens to prevent clipping.
*   **Added Application Custom Font Registry (`qgame.Font`)**: Load local `.ttf` or `.otf` font file resources on the fly, allowing consistent typography across different OS platforms without system font pre-installation.
*   **Upgraded 2D Layout Engine (`qgame.Align`)**: Enhanced geometric space partitions.
    *   Added grid positioning calculators (`.grid()`, `.row()`, `.column()`) for inventory slots and menu arrangements.
    *   Added Flexbox divisions (`.fit_row()`, `.fit_column()`) to adaptively stretch and partition canvas space.
*   **Added 9-Slice (Nine-Slice) UI Image Skinning**: `Panel` and `Button` now support `set_image_bg(path, top, right, bottom, left)`. Under window resizing, the margins and 4 corners remain crisp and distortion-free.
*   **Robust `set_theme()` Parameter Fallback**: Fixed a `TypeError` crash when passing partial elements as `None`. Configured robust keyword-argument protection across `Button`, `Panel`, `ProgressBar` and `TextBox`. Developers can now customize styles on-demand (e.g. `button.set_theme(text_color=...)`) without typing redundant `None` parameters.
*   **Rect Iterator Unpacking**: Overloaded python's unpacking mechanism (via `__iter__`) on `graphics.Rect`. Rect containers can now be destructured directly as coordinate tuples (e.g., `x, y, w, h = rect`) for drawings.

**中文:**
*   **新增声明式缓动动画控制器 (`qgame.tween`)**：无需在主循环中累加时延计时，实现高水准的游戏与 UI 弹性过渡拟真物理效果。
    *   支持 `elastic_out`（果冻弹性）、`bounce_out`（重力降落反弹）、`back_out` 等 17 种经典插值坐标算法。
    *   支持延迟等待（`delay`）、运行周期时长和缓动终点的完成回调（`on_complete`）。
    *   缓动更新会自动触发视口尺寸计算，保证运行平滑顺畅。
*   **新增自定义字体动态加载器 (`qgame.Font`)**：提供运行时 `Font.load()` 机制，支持把包内本地的 `.ttf` 或 `.otf` 字体加载注入到游戏引擎，解决跨平台打包字体不一致的宿疾。
*   **升级 2D 矢量画盘布局引擎 (`qgame.Align`)**：大幅扩充自适应排版定位计算：
    *   提供批量网格生成器（`.grid()`、`.row()`、`.column()`），轻而易举排列背包位和按键行。
    *   引入 CSS Flex 均分思想工具（`.fit_row()`、`.fit_column()`），输入指定范围即可完美均分、拉伸切割矩形空间。
*   **新增点九图（9-Slice、九宫格）UI 贴图背景**：`Panel` 与 `Button` 增加 `set_image_bg` 支持，保证全屏或拖拽自适应形变时，贴图四角不变形、不模糊。
*   **防御性非空 `set_theme()` 属性更新**：消除了由于部分传入 `None` 导致获取下标崩溃的缺陷。对 `Button`、`Panel`、`ProgressBar`、`TextBox` 的样式更新重构，支持关键字按需更新（例如：`button.set_theme(text_color=(0, 255, 0))`），免去了传递一长串无用 `None` 的麻烦。
*   **支持原生迭代解包的 `Rect`**：为矩形容器重载了迭代解构魔法函数（`__iter__`），允许开发者直接将 `Rect` 实例当做解包坐标传参（`x, y, w, h = rect`）给 Draw 绘图函数，开发体验大大精简。

### [2026.07.26] Version 1.2.0

**English:**
*   **Added ECS (Entity Component System)**: Unifies game entities (monsters, bullets, players) under the `Entity` base class for convenient batch lifecycle management.
    *   **Y-Sorting**: Resolves depth-occlusion relation (e.g., player walking behind a tree trunk).
    *   **Size-Sorting**: Automatically rendering entities sorted by their scaling factor to simulate perfect depth perception in side-scrolling pseudo-3D games.
*   **Extreme Performance Optimization for Particle System**: Refactored unoptimized OOP allocations with Flat List batch management.
*   **Tilemap Engine & Built-in Editor**: Hand-crafting tilemaps is tedious. We bootstrapped a "QGame Tilemap Editor" using the QGame library! No extra downloads needed—simply run `python -m editor`! (Note: The exported `.qmap` map packet is heavily encrypted/obfuscated—don't even think about manually reversing it! 😉)

**中文:**
*   **添加 ECS 实体组件系统**：游戏中的怪物、子弹、玩家统一继承于 `Entity`，更方便进行批量的生命周期与碰撞关系更新。
    *   **Y-Sorting（Y轴深度排序）**：解决了前后景深遮蔽关系，例如玩家走向树木后方时能被树冠完美遮挡。
    *   **Size-Sorting（缩放深度排序）**：在伪 3D 横版街机游戏场景中，根据物体大小进行智能分层，带来绝佳的立体感。
*   **粒子系统性能飞跃优化**：重构了落后的 OOP 渲染管线，采用扁平化内存批处理（Flat List Batching）大幅提升同屏计算上限。
*   **Tilemap 瓦片层架与自举编辑器**：为了消除手写大地图矩阵的痛苦，我们用 QGame 框架自研了一个“QGame 瓦片地图编辑器”！无需配置额外编译器，下载本库后在终端键入指令： `python -m editor` 即可一键启动。（注意，编辑器保存导出的 `.qmap` 文件为强混淆高压加密文件，以防美术资源被逆向提取哦~）

#### 粒子同屏性能对比表格 / Performance Comparison (60Hz Target)

| 粒子同屏数量 (Particles count) | 未优化的 OOP 方案 (Unoptimized OOP) | 优化后的 Flat List 批处理方案 (Optimized Batching) |
| :----------------------------- | :---------------------------------- | :------------------------------------------------- |
| **200 个**                      | 60 FPS (CPU 占用 ~25%)              | 60 FPS (CPU 占用 ~2%)                              |
| **500 个**                      | 35-45 FPS 出现卡顿 (CPU ~80%)       | 60 FPS (CPU 占用 ~5%)                              |
| **1500 个**                     | 12 FPS 严重幻灯片 (CPU 100%)        | 60 FPS稳定运行 (CPU ~18%)                          |
| **3000 个**                     | 驱动写死无响应 (Crash/Freeze)       | 45-55 FPS 依然丝滑可玩                             |

### [2026.07.25] Version 1.1.2
**English:**
*   **Patch**: Document changes

**中文:**
*   **补丁**: 文档更改

### [2026.07.25] Version 1.1.1
**English:**
*   **Patch**: the sample command program had a problem, which has now been resolved

**中文:**
*   **补丁**: 示例命令程序有问题，目前已解决

### [2026.07.25] Version 1.1.0
**English:**
*   **Major Second Generation Update**: Added core modules and presets for commercial-grade 2D games.
*   **Color Presets (`qgame.color` / `Color` class)**: Predefined colors including standard, dark/light variants, game-specific ambient masks (e.g. night filters), and alpha-blending shadows.
*   **Layout Alignment Helpers (`qgame.align`)**: Standardized debug print lines and dynamic screen centering helpers.
*   **Enhanced Camera**: Smooth linear interpolation (`lerp_speed` dampening), shake FX, and bounding lock logic suited for large-world coordinate projection.
*   **Real 2D Rigid Body Physics Engine**: Added collision solver using Impulse-Clamping, material elasticity, and friction coefficients.
*   **Interactive Demos**: Run the updated desktop examples directly using the command `run-qgame-examples`.

**中文:**
*   **第二代版本大更新**：补充了商业级 2D 游戏最常用的一系列预设与核心模块。
*   **游戏色彩预设，Color类 (`qgame.color`)**：内置了标准基础色、暗色调、游戏特制滤镜（如夜幕遮罩）以及各类半透明 shadow 混合色，消除魔鬼数字。
*   **全局排版 & 定位预设，Align类 (`qgame.align`)**：提供标准行渲染基准行高，并增加动态边缘偏移与画布中心定位函数。
*   **更好的 Camera**：实现了带阻尼的平滑镜头跟随、多维震屏，支持无限大世界坐标系向主显示视口的偏移映射。
*   **真实的 2D 物理引擎**：引入了带摩擦力、弹力、重力加速度的刚体求解器与窄相 OBB 碰撞分离机制。
*   **示例程序更新**：使用终端命令 `run-qgame-examples` 即可启动全新的大世界物理与光影效果综合演示。

### [2026.07.24] Version 1.0.0
**English:**
*   **First Generation Release (Initial Version)**.
*   **Core Game Pipeline (`qgame`)**: Window lifecycle and OpenGL hardware acceleration.
*   **Input Processing (`qgame.keyboard` & `qgame.mouse`)**: Real-time keystroke and pointer tracking.
*   **2D Graphics (`qgame.graphics`)**: Antialiased geometric drawings and offscreen image buffers.
*   **AABB Collision System (`qgame.collision`)**: Low-overhead shape overlaps check.
*   **Audio Engine (`qgame.audio`)**: Sound effects player and streaming background music playback.
*   **UI Input Box (`qgame.ui`)**: Adaptive `TextBox` supporting system IME and resizing.
*   **Scene Architecture (`qgame.scene`)**: Unified stage lifecycle management.
*   **Advanced Tools**: `Camera` tracking and `Spritesheet` grid/atlas packers parser.

**中文:**
*   **初代版本正式发布**。
*   **核心模块 (`qgame`)**：Qt/OpenGL 底层混合生命周期管理。
*   **输入处理 (`qgame.keyboard` & `qgame.mouse`)**：高反应灵敏的键鼠捕获。
*   **2D 绘图与渲染 (`qgame.graphics`)**：抗锯齿几何画板与离屏图像矩阵翻转。
*   **碰撞检测系统 (`qgame.collision`)**：基础 AABB 数学相交判定。
*   **音频控制系统 (`qgame.audio`)**：音效快速触发与多媒体背景音乐循环。
*   **UI 输入控件 (`qgame.ui`)**：完美兼容输入法与全屏缩放的文本输入框。
*   **游戏场景结构 (`qgame.scene`)**：生命周期托管的场景切替管理器。
*   **工具支持**：带死区限制的 `Camera` 及 `Spritesheet` 雪碧图/合图解析器。

---

# Usage Notes & Precautions / 使用注意事项 ⚠️

To ensure the best development experience and performance, please read the following guidelines:

为了保证最佳的开发体验与稳定性，请在开发时注意以下策略：

### 1. High-DPI Scaling & Device Pixel Ratio (高分屏与设备像素比)
On Windows or macOS with screen scaling (e.g., 125%, 150%, 200%), Qt automatically resizes canvas dimensions, which might distort pixel-art textures. 
*   `qgame.Spritesheet` and `qgame.Tilemap` have built-in `setDevicePixelRatio(1.0)` logic to ensure pixel-perfect crops.
*   When performing manual drawing coordinates, be aware that canvas sizes will automatically fit the actual hardware coordinate points.

在 Windows 10/11 或 macOS 的高分辨率缩放屏幕下，Qt 会默认开启虚拟像素缩放，这会导致裁剪像素图时计算错误。
*   `qgame` 的 `Spritesheet` 与 `Tilemap` 内部已强制指定 `DevicePixelRatio` 为 `1.0`（物理点对点图层）。
*   若你打算自己派生底层的 `QImage` 并直接传递给绘图，请确保使用 `setDevicePixelRatio(1.0)`，防止贴图发生二倍变小。

### 2. Time-Step Tunneling (物理隧穿与 Delta Time 截断限幅)
If you drag, resize, or suspend the OS window, Qt's main thread pauses. Upon release, the accumulative delta time ($dt$) could be abnormally high (e.g., $dt > 1.0$), making the player move hundreds of pixels in a single frame. This will cause the player to pass through thin obstacle walls (tunneling).
*   **Solution**: Always clamp your delta time in the game loop before updating positions or ticking physics worlds:
    ```python
    dt = clock.tick(60)
    dt = min(dt, 0.03)  # Clamp delta time to maximum 30ms step!
    ```

在玩家拖拽窗口标题栏、缩放或者桌面弹出系统对话框时，Qt 主线程会被挂起。松开鼠标后瞬时传回的 Delta Time ($dt$) 会发生累积暴涨。一旦 $dt$ 激增，角色单帧的位移增量就会超出普通阻挡物强度的厚度，直接发生穿模隧穿。
*   **规避手段**：请在更新角色的物理判定前强行写入单帧变化量限幅限制，截住时延信号：
    ```python
    dt = clock.tick(60)
    dt = min(dt, 0.03)  # 强制截断单步上限为 30 毫秒，大步长将拆分为小分段执行
    ```

### 3. File System Lock Releases (文件锁的释放处理)
When parsing JSON or crop sheets dynamically (`run_spritesheet_demo`), if you try to clean up paths/files on Windows immediately after rendering, OS permissions might throw an `Access Denied` error because the GC hasn't collected the cache yet.
*   **Best Practice**: Explicitly delete references using `del sheet, tiles` before calling `os.remove()`.

在 Windows 系统下进行解析大图切片时，若紧接着想要擦除磁盘生成的临时图片缓存，往往由于 Python GC 垃圾回收延时，底层文件权标仍驻留在进程句柄中，抛出拒绝删除异常。
*   **最佳实践**：在用 `os.remove` 销毁数据前，先通过句柄 `del` 指令明确断开引用指针：
    ```python
    del sheet, tiles, atlas
    os.remove("temp.png")
    ```

### 4. Tilemap Grid Renderer Optimization (瓦片辅助网格优化)
Looping through matrix lists and starting a dedicated paint device for each tile individually (like multiple local `qgame.draw.rect` calls) is highly unoptimized.
*   **Best Practice**: For drawing wireframes or customized debugging visuals, instantiate a single backend `QPainter` block to do batch renders. See `run_tilemap_demo` implementation details.

遍历瓦片矩阵并在底层开启成百上千次 `QPainter` 画笔绘制调试线会造成严重的 CPU 瓶颈。
*   **最佳实践**：如需显示自定义的大图或者碰撞线描，应当像 `run_tilemap_demo` 那样使用单局部的 Painters 批量打包刷图，以此节省创建/消解状态机的上下文消耗。

---

## Installation & Running Demo
If installed via setuptools, run the demo directly in the terminal:
```bash
run-qgame-examples
```
Or run as a module:
```bash
python -m qgame
```

---

## Editor Mode
Launch the built-in tilemap maker:
```bash
python -m editor
```
Design your level layers, brush block collisions, and hit "Save Map" to export the secure binary `.qmap` mapping config directly.

---

## Node Dialogue Editor
* **Three-pane Partition Layout**: Built on top of a dark CSS interface. Provides Node ID tracking lists on the left, attribute entries (speaker, emotion icon, text editor) in the middle, and choice cells on the right.
* **Deadlink Prevention**: Both the default single-direction step `next` router and the rows in the multi-branch choice tables index the registry database. They display current active Nodes in drop-down combo boxes to prevent broken routes.
* **JSON Exporter & Importer**: Saves logic configurations into `.json` files, which can be directly referenced by `DialogBox.load_dialog_json` without coding.
Operating mode:
```bash
run-qgame-dialog-editor
```

---

## Core Module (`qgame`)

### Functions
* **`init()`**
  Initializes the PySide6 Application context. Must be called before any graphics operations.
* **`set_settings(*, width: int, height: int, title: str = "QGame", icon_path: str = None, scaling_mode: Literal["letterbox", "crop", "stretch", "adaptive"] = "letterbox") -> QImage`**
  Sets the game window resolution and title. Returns the primary QImage canvas for rendering.
* **`show_splash(image_path: str = None, duration: float = 2.0, *, echo_error: bool = True)`**
  Display the game launch splash screen with smooth semi-transparent transitions of fade in and fade out. If no parameter is passed, use the QGame logo. If the path does not exist and echo_error is True, raise FileNotFoundError; otherwise, print the error.

### `window` (Window Instance)
* **`update()`**
  Redraws the window and processes window events. Call once per frame inside the game loop.
* **`set_title(title: str)`**
  Dynamically changes the window title.
* **`set_icon(icon_path: str)`**
  Loads and sets the window icon.
* **`set_size(width: int, height: int) -> QImage`**
  Changes the canvas dimensions dynamically.
* **`toggle_fullscreen()`**
  Toggles between fullscreen and windowed modes.
* **`show_cursor(visible: bool)`**
  Shows or hides the OS cursor.
* **`get_all_windows() -> list`**
  Return all window instances
* **`get_width(window=None) -> int`**
  Returns the window width.
* **`get_height(window=None) -> int`**
  Returns the window height.
* **`get_size(window=None) -> int | tuple[int, int]`**
  Returns a tuple containing the window width and height.

### `events` (Events Instance)
* **`get(window=None) -> List[Event]`**
  Pulls and returns all pending events in the queue.
* **`get_mouse_pos() -> tuple`**
  Get the mouse position in the window.
* **`wait_for_event(event_type: int, timeout: float = None) -> Event | None`**
  Blocks execution to wait for a specific event type.
* **`get_key_state(key_code: int) -> bool`**
  Smooth keyboard query that bypasses system repeats.

### `Clock` (Class)
* **`tick(fps: int) -> float`**
  Controls the game frame rate and returns `dt` (Delta Time in seconds).

---

## Tween System (`qgame.tween`)

### `tween` (TweenManager Instance)
Used to construct smooth declarative animations.
* **`to(target, duration: float, ease: str = "linear", delay: float = 0.0, on_complete: Callable = None, **properties)`**
  Creates an active tween.
  * `target`: Target object or dictionary.
  * `duration`: Animation duration in seconds.
  * `ease`: Math interpolation key word (e.g. `"elastic_out"`, `"bounce_out"`, `"quad_in_out"`, `"sine_out"`).
  * `properties`: Parameters to modify, like `x=500` or `alpha=1.0`.
* **`update(dt: float)`**
  Ticks all running tween calculations. Call once per frame in your main loop.
* **`clear()`**
  Flushes all animations.

---

## ECS & Entity System (`qgame.ecs`)

### `Entity` (Class)
Inherit `Entity` to build custom game actors. Under rendering structures, it supports layered sorting indices and please refer to the changelog for version 1.7.0 for more details.
* **Properties**: `x`, `y`, `size` (for Size-Sorting).
* **Methods**: `update(dt)`, `draw(canvas)`.

### `EntityManager` (Class)
Managers your main world lists.
* **`add(entity: Entity)`**
* **`remove(entity: Entity)`**
* **`clear()`**
* **`update(dt)`**: Updates all components.
* **`draw(canvas)`**: Evaluates camera coordinates and renders with automatic layer sorting.
* **`auto_layer_y = True`**: Resolves classic Y-Sorting relationships.
* **`auto_layer_s = True`**: Sorts by structural scale sizes (size depth).

---

## Particle System (`qgame.particles`)

### `ParticleEmitter` (Class)
Uses flat arrays in memory to optimize particles computation and drawings.
* **`create_rain(width)`**: Spawns rainfall particles.
* **`create_fire(x, y)`**: Spawns campfire floating embers.
* **`create_explosion(x, y)`**: Spawns one-shot cluster particles that auto-dispose.
* **`condition: tuple | list | object | Callable[[float, float], bool], action: Literal["die", "bounce_y", "bounce_x", "freeze"] | Callable[[list], None]`**: Define rules and perform corresponding actions.

---
## Resources and `.qres` VSCode Extension (`qgame.resource`)

### Resources
`resource.py` is the underlying operator for loading and managing `.qres` asset configurations in the QGame engine, ensuring the robustness of game data through three core mechanisms:

1. **Minimalist Bidirectional Data Traversal (`GroupRes`)**
   To keep game business-layer code extremely concise, Python magic methods are overridden:
   - **Dot notation for direct access**: `res.armor.defence`
   - **Bracket notation for indirect access**: `res["armor"]["defence"]`
   - **Nested subgroup support**: Child groups are automatically converted into independent `GroupRes` container classes, enabling infinite nesting depth.

2. **Powerful Symbol Table Mechanism**
   - **Cross-variable assignment**: When loading a `.qres` file, a `symbol_table` scope dictionary is maintained in the main process. When encountering `int <mp> mp_max`, if `mp_max` has been previously declared, the Python driver directly reads its value via pointer reference, enabling linked variable configurations.
   - **Null-value fallback**: If only a type and variable name are provided (e.g., `dict <buffs>` with no RHS value), the engine automatically injects the corresponding Python zero-value based on the type prefix (`{}`, `[]`, `set()`, `0`, `0.0`, `False`, `None`), making it highly fault-tolerant.
   - **TypeError with precise line numbers**: When a type conversion exception occurs, the engine throws a highly readable crash log containing the specific `.qres` line number, the original value, and the expected strong type.

3. **Bidirectional Conversion**
   - `convert(py_class)`: Directly reads any Python class type tree (including nested structures) and reconstructs them into a `Resource` object tree.
   - `to_qres()`: Reverse output algorithm. Re-formats and exports various in-memory variables and deeply nested groups into clean, standard `.qres` plain text, which can be safely `save()` back to disk.

---

## 🛠️ QGame Lua Scripting System (`qgame.script`)

`qgame.script` is QGame's built-in **scripting language cross-bridge system**. It is built on the high-performance `lupa` library (a JIT‑level Lua binding), allowing developers to write high‑frequency game logic in the minimal, lightweight Lua language while maintaining blazing‑fast Python game rendering.

---

### 🎯 Why Use Lua Scripting in QGame?

1. **Complete Logic‑Engine Separation**: Python handles physics, rendering, and foundational mechanics; Lua is dedicated to “NPC dialogue,” “level triggers,” and “weapon damage values.”
2. **Blazing Speed**: Lua is one of the fastest interpreted scripting languages in the world.
3. **Mod Developers Rejoice**: Lua is the most commonly used scripting language in the gaming industry (World of Warcraft, Angry Birds, and Roblox all use it), so mod developers can get started quickly—and even those new to it can pick it up fast!
4. **Safe & Painless Console Output**: Completely solves the **GBK garbled text** issue when printing Chinese strings from Lua in Windows CMD/PowerShell. QGame intercepts and overrides Lua's `print` at the lower level, making it fully compatible with the Python terminal!
5. **Seamless Bidirectional Interaction**:
   * Inside Lua scripts, you can directly call Python entity methods like `.chase()` and `.destroy()`
   * On the Python side, you can directly execute advanced AI functions defined in Lua using `.call()`

---

### 🔑 1. Core Interface API Overview

### 🛑 Prerequisite Environment Check
```python
import qgame

# Check if lupa is installed. If not, QGame will prompt: pip install lupa
print(qgame.script.is_supported())  # Returns True / False
```

### 📄 Loading Scripts: `qgame.script.load(source, context=None)`
* **Purpose**: Compiles a Lua script or loads a local `.lua` file.
* **Parameters**:
  * `source` (str / Path): Can be a local script path (e.g., `"scripts/boss_ai.lua"`) or a Lua code string directly.
  * `context` (dict): **Extremely powerful!** Can pack Python objects (such as `player` instances, `window`, etc.) directly into Lua at load time. Lua scripts can then use them as global variables directly!

### Type Conversion: `qgame.script.table(...)`
* **Purpose**: Converts Python tuples into Lua tables.
* **Example**: `qgame.script.table(10, 20)`

### 🚀 Running the Script Body: `LuaScript.run(extra_context=None)`
* **Purpose**: Executes the main Lua code block. Only needs to be executed once.
* **Parameters**:
  * `extra_context` (dict): Temporarily appends or overrides Python variable mappings at runtime.

### 📞 Precise Cross‑Boundary Call: `LuaScript.call(func_name, *args, optional=False, default=None, err=True)`
* **Purpose**: Instead of running the entire script, directly grab a specific `function` defined in Lua, pass arguments, and get the return value!

### Lua Functions: `LuaScript.has_function(name)` / `LuaScript.get_function(name, optional=False)`
* **Purpose**: No need to read the Lua mod file to look up functions; directly use `globals` to get/check them instantly!

### Error Handling: `LuaScript.is_err(called_val, *, echo=False, again=False)` / `is_cheat_err(called_val, *, echo=False, again=False)`
* **Purpose**: Checks whether the called function has performed any illegal operations (e.g., modifying read‑only variables).

---

## 🎮 2. Practical Walkthrough: Manipulating QGame Entities with Lua!

Let's experience the magical "soul‑level bidirectional communication" between Python and Lua through this minimal example:

### Step 1: Writing the Lua Behavior Script `monster_behavior.lua`
Create a new file named `monster_behavior.lua`:

```lua
-- monster_behavior.lua
print("[Lua] 🎯 Monster AI script loaded and activated successfully!")

-- 1. Lua can directly access the "player" and "monster" instance objects passed from Python!
function on_monster_update(dt)
    -- Calculate the distance between the monster and the player
    local dist = monster:distance_to(player)
    
    if dist > 80 then
        -- 💡 Far away: Lua directly calls the Python .chase() method to command the monster to pursue!
        monster:chase(player, dt)
        print("[Lua] Status: Distance from player " .. string.format("%.1f", dist) .. "px, chasing at full speed!")
    else
        -- 💡 Close range: Lua triggers the monster to bite the player directly
        player.hp = player.hp - 10 * dt
        print("[Lua] Status: Melee combat! Player HP remaining: " .. string.format("%.1f", player.hp))
    end
end

-- 2. A demo function that computes a value inside Lua and returns data to Python
function calculate_exp(base_exp, multiplier)
    return base_exp * multiplier + 100
end
```

### Step 2: Writing the Python Main Driver
On the Python side, use `qgame.script` to bind, run, and pass entities:

```python
import qgame
from qgame.ecs import Entity  # Yes, the Entity you use is in ecs
from qgame.script import script

# 1. Initialize QGame
qgame.init()

# 2. Create player and monster entities (with x, y, hp attributes)
class Role(Entity):
    def __init__(self, x, y, name):
        super().__init__(x, y)
        self.name = name
        self.hp = 100.0
        self.speed = 150.0  # Movement speed

player = Role(100, 100, "Xiao Ming")
zombie = Role(300, 300, "Zombie")

# 3. 🚨 Key: Load the Lua script and inject the entities!
# Register player and monster as global context for Lua, making them directly usable in the script!
ai_script = script.load(
    "monster_behavior.lua", 
    context={"player": player, "monster": zombie}
)

# Run the script body once (to execute the print on load)
ai_script.run()

# 4. Game main loop
clock = qgame.Clock()
for _ in range(3):  # Simulate 3 frames
    dt = clock.tick(60)
    
    # 🚨 Key: In the Python main loop, directly cross‑call the Lua update behavior function!
    ai_script.call("on_monster_update", dt)

# 5. 🚨 Key: Read the computed result from Lua!
final_exp = ai_script.call("calculate_exp", 50, 1.5)
print(f"[Python] Received data from Lua: The kill reward experience is {final_exp} points!")
```

## 💻 Perfect Console Output:
After running the Python script:
```bash
[Lua] 🎯 Monster AI script loaded and activated successfully!
[Lua] Status: Distance from player 282.8px, chasing at full speed!
[Lua] Status: Distance from player 280.1px, chasing at full speed!
[Lua] Status: Distance from player 277.4px, chasing at full speed!
[Python] Received data from Lua: The kill reward experience is 175.0 points!
```

---

### `qres` VSCode Extension
#### Download:
* Download via **Gitee**: https://gitee.com/watermelon-juice-code/qgame-resource-support/blob/master/qgame-resource-support-1.0.0.vsix
* Download via **Baidu Netdisk**: https://pan.baidu.com/disk/main?from=homeFlow#/index?category=all&path=%2F%E5%85%AC%E5%BC%80%E6%96%87%E4%BB%B6%E5%A4%B9  Extraction code: `code`
    * Select `qgame-resource-support-1.0.0.vsix` and download it.
* Download via **Quark Cloud Drive**: https://pan.quark.cn/s/eeb366929d4b  Extraction code: `TTt3`

`qgame-resource-support` — VSCode editor synergy for `.qres` files.

This VSCode extension is more than just syntax highlighting; it's a lightweight static syntax analyzer (Linter) tightly coupled with Python rules:

1. **Strong Blocking: Python Variable Naming Identifier Constraints**
   - **Rule blocking**: In Python, variable names cannot start with a digit (e.g., `1player` is illegal and causes a `SyntaxError`).
   - **Plugin enforcement**: When the plugin detects a digit immediately after `<` (e.g., `int <2d_pos> [0,0]`), it draws a red squiggly line directly in VSCode, preventing this malformed configuration from reaching the QGame engine and causing compilation errors.

2. **Scope Redefinition Real-Time Correction**
   - **Same-group duplicate detection**: If two variables with the same name are declared within the same `[Resource.xxx]` block, the plugin highlights them in red.
   - **Block overlap detection**: If duplicate group declarations are found, the plugin marks them as errors in real time.
   - **Cross-group shadowing warning (yellow alert)**: When variables with the same name appear in different group hierarchies, a yellow bidirectional squiggly line warning is shown (can be disabled in editor settings). This prevents confusion when performing cross-variable assignments via the symbol table later on.

3. **Syntax Beautification & Clean Intellisense Experience**
   - **Color optimization**: Independently highlights `.qres` keywords (e.g., `str`, `list`), group categories, variable angle brackets, and numeric literals.
   - **Noise reduction**: Completely suppresses VSCode's default "abc" free-text word suggestions. Typing `<` only brings up pre-configured available types and configuration symbols.
   - **Automatic file template injection**: When a blank `.qres` file is created, the plugin automatically inserts the `[Resource]` header marker, providing a seamless and polished configuration experience.
---

## Input Module (`qgame.keyboard`, `qgame.mouse`)

### `keys` (Key Mapping Constants)
Contains PySide6 key code constants, e.g., `keys.W`, `keys.ESCAPE`, `keys.UP`, `keys.SPACE`, `keys.SHIFT`, etc.

### `keyboard` (Keyboard Detection)
* **`is_pressed(key_code: int) -> bool`**
  Returns `True` if the specified key is currently down.

### `mouse` (Mouse Detection)
* **`get_pos() -> tuple[int, int]`**
  Returns virtual canvas coordinates `(x, y)` of the mouse.
* **`is_pressed(button: int) -> bool`**
  Returns `True` if the specified mouse button is down (`mouseButtons.LEFT`, `mouseButtons.RIGHT`, `mouseButtons.MIDDLE`).

---

## Graphics Module (`qgame.graphics`)

### `Color` (Class Constant - `qgame.color`)
A collection of preset color tuples for rendering:
* **Standard**: `WHITE`, `BLACK`, `RED`, `GREEN`, `BLUE`, `YELLOW`, `ORANGE`, `PURPLE`, `PINK`, `CYAN`, `BROWN`, `GRAY`.
* **Dark Variants**: `DARK_RED`, `DARK_GREEN`, `DARK_BLUE`, `DARK_GRAY` (Iron/Stone block).
* **Vibrant & Special**: `LIGHT_GREEN` (Healing), `LIGHT_BLUE` (Frost), `LIGHT_YELLOW`, `GOLD`.
* **FX & Environment**: `WOOD_BG` (Wood tiles), `NIGHT_MASK` (Darkness layer, RGBA: `10, 10, 25, 248`), `PLAYER_GLOW` (Warm lamp), `TARGET_GREEN` (Crosshair).
* **Translucent (RGBA)**: `TRANSPARENT`, `SHADOW_50`, `SHADOW_80` (Pause mask), `WHITE_GLOW`.

### `Align` (Use - `qgame.layout`)
UI position calculation presets and automatic 2D grid partitions:
* **Debug Line Y-coordinators**: `LINE_1` (Y=20), `LINE_2` (Y=50), `LINE_3` (Y=80).
* **`top_left(offset_x, offset_y) -> tuple[int, int]`**
* **`top_right(canvas, offset_x, offset_y, width) -> tuple[int, int]`**
* **`bottom_left(canvas, offset_x, offset_y, height) -> tuple[int, int]`**
* **`bottom_right(canvas, offset_x, offset_y, width, height) -> tuple[int, int]`**
* **`center(canvas, width, height) -> tuple[int, int]`**
* **`grid(x, y, rows, cols, cell_width, cell_height, spacing_x=0, spacing_y=0) -> list[Rect]`**
  Returns an array of Rect structures representing grid slots.
* **`row(x, y, count, cell_width, cell_height, spacing=0) -> list[Rect]`**
  Horizontal一维 row partitioning.
* **`column(x, y, count, cell_width, cell_height, spacing=0) -> list[Rect]`**
  Vertical一维 column partitioning.
* **`fit_row(parent_rect: Rect, count, spacing=0) -> list[Rect]`**
  Divides a parent Rect horizontally into `count` sections.
* **`fit_column(parent_rect: Rect, count, spacing=0) -> list[Rect]`**
  Divides a parent Rect vertically into `count` sections.

### `Font` (Class)
* **`load(font_path: str) -> str`**
  Loads local `.ttf` or `.otf` file and registers it. Returns the registered font family name.

### `CustomFont` (Hand-drawn / Bitmap / Vector Font Loader) (New)
A character mapping partition designed for fontless, geek-style hand-drawn fonts, pixel fonts (Bitmap Font), and custom glyph sets.

*   **`__init__(default_width=None, default_height=None)`**
    Initializes a custom font partition. You can pass `default_width` and `default_height` to lock the physical base size for each character displayed.
*   **`register(char: str, file_path: str) -> bool`**
    Manually maps a single character to an image (or SVG vector) file path:
    *   `char`: Must be a single character of length 1 (supports letters, symbols, individual Chinese characters, etc.).
    *   `file_path`: Supports `.png`, `.jpg`, and `.svg` (vector characters).
*   **`load_dir(dir_path: str) -> int`**
    **(Core Recommendation: Batch Scan & Load)** Scans all image assets in the specified folder. **The base filename (without extension) is used as the mapped character.**
    *   *Example folder structure*:
        ```text
        assets/retro_font/
          ├── a.png      (Automatically mapped to character 'a')
          ├── b.png      (Automatically mapped to character 'b')
          ├── 1.png      (Automatically mapped to character '1')
          └── 赞.svg     (Supports SVG natively; mapped to Chinese character '赞')
        ```
    *   Simply call `font.load_dir("assets/retro_font/")` to load the entire folder in one go! Returns the number of characters successfully loaded.
*   **`get_char(char: str) -> Image | SVG | None`**
    Internal asset relocation method; retrieves the underlying renderable object for the given character.

#### In Static Drawing Methods:
*   **`draw.custom_text(canvas, custom_font, text, coords, spacing=2, scale=1.0, opacity=1.0)`**
    Renders a string horizontally on the canvas using the specified hand-drawn/vector font partition.
    *   `custom_font`: A `CustomFont` instance that has been initialized and populated with characters.
    *   `text`: The string to render, e.g., `"hello 赞"`. (If the string contains unregistered whitespace like `" "`, the system will automatically reserve a placeholder space.)
    *   `coords`: The starting drawing position `(x, y)`.
    *   `spacing`: Horizontal pixel spacing between characters.
    *   `scale`: Overall scaling factor (float). For example, `2.0` doubles the glyph size without quality loss.
    *   `opacity`: Overall drawing transparency, ranging from `0.0` to `1.0`.

### `Image` (Class)
Represents a source image cached in memory.
* **`__init__(source: str | Image | QImage)`**
  Wraps a path, another image instance, or QImage. Performs zero-IO memory copy when using an existing image.
* **`resize(width: int, height: int, keep_aspect: bool = False)`**
  Rescales the active image.
* **`scale(factor_x: float, factor_y: float = None, keep_aspect: bool = True)`**
  Scales by percentage multipliers.
* **`rotate(angle: float)`**
  Rotates the image (degrees, clockwise).
* **`flip(horizontal: bool = True, vertical: bool = False)`**
  Flips the image.
* **`reset()`**
  Reverts the image to its original clean state.
* **`width` / `height`**
  Properties returning active resolution.

### `SVG` (Geek-level Vector Asset Class)
*   **`__init__(source_path: str)`**
    Parses a local standard SVG vector data file and builds a high-fidelity rendering data source.
*   **`resize(width: float, height: float)`**
    Sets the target rendering bounds for the current vector boundary (supports precise floating-point coordinate scaling).
*   **`scale(factor_x: float, factor_y: float = None)`**
    Scales the vector dimensions proportionally or non-proportionally by the given factors.
*   **Properties**: `width` and `height`, returning the absolute bounds of the scaled vector.

#### In Static Drawing Methods:
*   **`draw.svg(canvas, svg_obj, coords, center=False, opacity=1.0)`**
    Rasterizes vector graphics in real-time on the canvas using the Qt vector geometry renderer.
    *   `svg_obj`: An instantiated `qgame.SVG` object.
    *   `coords`: The drawing start position (x, y).
    *   `center`: When set to `True`, aligns the drawing to the exact center of the vector graphic.
    *   `opacity`: Adaptive transparency blending, ranging from `0.0` (fully transparent) to `1.0` (fully opaque).

### `Rect` (Class)
* **`__init__(x, y, width, height)`**
  A float-precision 2D rectangle container. Supports packing unpack iterates (e.g. `x,y,w,h = rect`).
* **`center` / `centerx` / `centery`**
  Properties to read/write center coordinates.
* **`collidepoint(pos: tuple) -> bool`**
  Returns `True` if a coordinate is inside the boundary.

### `draw` (Draw Utility)
* **`fill(canvas, color)`**
  Clears the canvas with a solid color `(r, g, b)`.
* **`rect(canvas, color, rect, width=0)`**
  Draws a rectangle. `width=0` fills it.
* **`rounded_rect(canvas, color, rect, radius, width=0)`**
  Draws an antialiased rounded rectangle.
* **`circle(canvas, color, center, radius, width=0)`**
  Draws an antialiased circle.
* **`ellipse(canvas, color, rect, width=0)`**
  Draws an ellipse inside a bounding box.
* **`line(canvas, color, start, end, width=1)`**
  Draws an antialiased segment line.
* **`text(canvas, text, coords, size=16, color=(255,255,255), font_name="")`**
  Draws a high-fidelity antialiased text.
* **`image(canvas, img, coords, center=False, src_rect=None, opacity=1.0)`**
  Draws a fast-blended image, supports center tracking, sub-rect cropping, and transparency.
* **`draw.motion_blur_image(canvas, img, x, y, vx, vy, samples=5, max_blur_length=100.0, center=False)`**
    **(Core Recommendation)** Uses 1D multi-sampling interpolation to render real-time motion blur trails for images moving at high speed.
    *   `img`: An instantiated `qgame.Image` object.
    *   `x`, `y`: The target drawing position.
    *   `vx`, `vy`: The relative motion velocity vector for the current frame (higher speed results in longer trails; if 0, the image remains sharp).
    *   `samples`: The number of sample overlays for rendering. Recommended range: `3` to `6`. Higher sample counts yield smoother quality.
    *   `max_blur_length`: Limits the maximum physical pixel length of the trail, preventing excessively high motion from causing the particles to fade into nothingness.
    *   `center`: When set to `True`, enables a highly physics-adaptive center-origin tracking mechanism.

---

## Collision Module (`qgame.collision`)

### Methods
* **`check_rect(rect1: tuple, rect2: tuple) -> bool`**
  Rect-to-Rect AABB intersection.
* **`check_circle(pos1, r1, pos2, r2) -> bool`**
  Circle-to-Circle intersection.
* **`check_rect_circle(rect, center, radius) -> bool`**
  Rect-to-Circle intersection.
* **`check_point_rect(point, rect) -> bool`**
  Point-in-Rect containment.
* **`check_point_circle(point, center, radius) -> bool`**
  Point-in-Circle containment.

---

## Physics Module (`qgame.physics`)

### `PhysicsWorld` (Class)
Manages the simulation of dynamic rigid bodies and gravity.
* **`__init__(gravity_x: float = 0.0, gravity_y: float = 9.8)`**
  Creates a simulation world. Default gravity is `600.0` pixels/s² down.
* **`add_body(body: RigidBody)`**
  Registers a rigid body to the simulation solver.
* **`remove_body(body: RigidBody)`**
  Removes a body from the simulation.
* **`step(dt: float)`**
  Iterates the physics clock. Automatically runs multiple sub-steps to resolve constraints and avoid clipping.

### `RigidBody` (Class)
A material dynamic entity in the physics solver.
* **`__init__(shape_type: str, x: float, y: float, width_or_radius: float, height: float = 0, is_static: bool = False, mass: float = 1.0, friction: float = 0.5, restitution: float = 0.0)`**
  `shape_type` can be `"circle"` or `"rect"`. Set `is_static=True` for ground/walls. `restitution` controls bounciness.
* **`apply_impulse(impulse_x: float, impulse_y: float, offset: tuple[float, float] = (0, 0))`**
  Applies an instantaneous force vector to push the object (e.g. jumping).

---

## Audio Module (`qgame.audio`)

### `Sound` (Class)
For rapid playback of short sound effects (`.wav`).
* **`play()`, `stop()`**
* **`set_volume(volume: float)`** (0.0 to 1.0)
* **`set_loop(loop: bool)`**

### `Music` (Class)
For streaming long background music tracks (`.mp3`).
* **`play(loop: bool = True)`, `pause()`, `unpause()`, `stop()`**
* **`set_volume(volume: float)`** (0.0 to 1.0)

### `SpatialSound` (2D Spatial Audio Generator Class)
Adds audio to 2D physical space calculations. Automatically performs stereo channel panning and volume attenuation (loud when near, quiet when far) based on the camera position.
* **`__init__(self, file_path, coords, max_distance = 600.0, loop = False)`**
    Initializes the spatial sound instance.
    * `file_path`: Path to the audio file.
    * `coords`: Initial 2D position `(x, y)` of the sound source.
    * `max_distance`: Maximum audible distance. Beyond this, the volume will be effectively silent.
    * `loop`: Whether the audio should loop continuously.
* **`play()`**
    Starts playing the audio.
* **`stop()`**
    Stops the audio playback.
* **`set_position(coords)`**
    Updates the position of the sound source in the 2D world.
* **`update_spatial_properties()`**
    Call this in the main loop alongside camera and sound source movement to apply real-time spatial effects (panning and distance attenuation).

---

## Animation (`qgame.animation`)

# 📖 QGame Animation System API Reference (`qgame.animation`)

---

## 1. Exception Classes (Custom Exceptions)

Used for precise capture and localization of underlying errors during animation loading, control, extraction, or alias lookup.

### `NotFoundFileError`
* **Description**: Raised when attempting to add (`add_file_path`) an animation configuration file, `.animdata` archive, or image resource that does not physically exist on disk.

### `UnboundWindowError`
* **Description**: Raised when attempting certain viewport drawing operations before the game's main window has been properly initialized.

### `ImageNotShowError`
* **Description**: Triggered when attempting to drive an animation (`animation_start`) on an image/animation that has not yet been displayed (`image_show`).

### `NotFoundAliasError`
* **Description**: Triggered when looking up an alias that has never been registered in the system.

---

## 2. Global Animation Control Functions

These functions primarily handle asset-level scheduling and frame advancement for **classic sprite sheets (e.g., `hero_1.png`, `hero_2.png`)** and **advanced composite animation configuration files (`.json` / `.animdata`)**.

---

### `add_file_path`
```python
def add_file_path(file_path: str, alias: str, wait: int = 10) -> None:
```
* **Description**: Registers a multimedia animation or single-frame image asset.
* **Parameters**:
  * `file_path` (`str`): The file path. Can be:
    * `.json`: Custom 2D bone or multi-layer composite animation configuration file.
    * `.animdata`: Packed and compressed proprietary encrypted animation asset package.
    * `.*` (e.g., `.png`, `.jpg`): Single-frame regular pixel image asset.
  * `alias` (`str`): The permanent lookup alias for this asset in memory.
  * `wait` (`int`, default `10`): Frame delay in ticks. Smaller values result in faster frame switching.
* **Raises**:
  * `NotFoundFileError`: The file path does not exist.
  * `ValueError`: The `wait` parameter is negative.

---

### `image_show`
```python
def image_show(alias: str, x: int, y: int, window: QImage) -> None:
```
* **Description**: Activates and renders the specified alias asset at physical coordinates `(x, y)` on the main canvas `window`.
* **Parameters**:
  * `alias` (`str`): The asset alias to display.
  * `x`, `y` (`int`): The drawing position (center or top-left corner).
  * `window` (`QImage`): The target game viewport canvas that receives the rendering.
* **Raises**:
  * `NotFoundAliasError`: The alias cannot be found.

---

### `animation_start`
```python
def animation_start(
    alias: str, 
    total_frames: int = 1, 
    callback: Optional[Callable[[], None]] = None,  
    underline: bool = True, 
    file_type: str = "png"
) -> None:
```
* **Description**: Advances the multi-frame animation associated with the alias by one frame. Must be called continuously in the main game loop. For JSON/animdata animations, it automatically drives all sub-skeleton components according to the configuration. For sprite sheets, it automatically looks up the next numbered frame image.
* **Parameters**:
  * `alias` (`str`): The asset alias.
  * `total_frames` (`int`, default `1`): Total number of frames. For complex composite animations, this field is automatically overridden by the configuration.
  * `callback` (`Callable`, optional): Callback triggered when the animation completes a full cycle (returns to the first/last frame).
  * `underline` (`bool`, default `True`): Whether the number in the sequence filename has an underscore (e.g., `hero_1.png` → `True`; `hero1.png` → `False`).
  * `file_type` (`str`, default `"png"`): The image format extension.
* **Raises**:
  * `ImageNotShowError`: The asset has never been rendered (`image_show` was not called).
  * `NotFoundFileError`: The next sequence image file cannot be found in the corresponding folder.

---

### `animation_stop`
```python
def animation_stop(alias: str) -> None:
```
* **Description**: Stops the currently playing animation for the given alias and resets its frame wait counter.
* **Parameters**:
  * `alias` (`str`): The asset alias to stop.

---

### `is_image_showing`
```python
def is_image_showing(alias: str) -> bool:
```
* **Description**: Checks whether the image/animation under the given alias is currently being rendered on the canvas.
* **Returns**: `bool`.
* **Raises**: `NotFoundAliasError`.

---

### `is_animation_started`
```python
def is_animation_started(alias: str) -> bool:
```
* **Description**: Checks whether the specified animation is currently in the playing (frame-advancing) state.
* **Returns**: `bool`.
* **Raises**: `NotFoundAliasError`.

---

### `get_animation_frame`
```python
def get_animation_frame(alias: str) -> int:
```
* **Description**: Returns the current real frame index of the animation for the given alias.
* **Returns**: `int` (0-based frame index).
* **Raises**: `NotFoundAliasError`.

---

### `set_animation_frame`
```python
def set_animation_frame(alias: str, frame: int = 1) -> None:
```
* **Description**: Forces the specified animation to rewind or jump to the target frame.
* **Parameters**:
  * `alias` (`str`): The asset alias.
  * `frame` (`int`, default `1`): The target frame number.

---

### `set_animation_speed`
```python
def set_animation_speed(alias: str, speed: int = 2) -> None:
```
* **Description**: Multiplicatively shortens the frame wait delay, increasing or decreasing playback speed.
* **Parameters**:
  * `alias` (`str`): The target alias.
  * `speed` (`int`, default `2`): The speed multiplier (must be a positive integer).

---

### `animation_reverse`
```python
def animation_reverse(alias: str) -> None:
```
* **Description**: Sets the target animation to **reverse playback mode**.
* **Parameters**:
  * `alias` (`str`): The target alias.

---

### `animation_reverse_back`
```python
def animation_reverse_back(alias: str) -> None:
```
* **Description**: Restores the target animation to normal **forward playback mode**.
* **Parameters**:
  * `alias` (`str`): The target alias.

---

## 3. State Monitoring Class: `AnimationStatus`

---

### `AnimationStatus`
```python
class AnimationStatus:
```
* **Description**: A read-only inspection capsule class. When passed an asset alias, it can instantly capture a snapshot of all its current physical playback states.

### **Constructor**
```python
def __init__(self, alias: str):
```
* Initializes and immediately captures the state of the alias animation. Contains the following member attributes:
  * `alias` (`str`): The lookup identifier.
  * `is_showing` (`bool`): Whether it is currently being displayed.
  * `is_started` (`bool`): Whether frame advancement is active.
  * `frame` (`int`): The current physical frame index.
  * `speed` (`int`): The playback speed.
  * `is_reverse` (`bool`): Whether reverse looping is enabled.
  * `file_path` (`str`): The original registered file path.
  * `file_name` (`str`): The base filename stripped of numeric suffixes.
  * `total_frames` (`int`): The evaluated total number of animation frames.
  * `current_frame` (`int`): The normalized frame offset.
  * `image_type` (`str`): The type, either `"Image"` (single frame) or `"Animation"` (composite animation).

### **Public Methods**

#### 1. `get_settings`
```python
def get_settings(self) -> str:
```
* **Description**: Packages all states, configurations, and metadata of the asset into a well-structured JSON string suitable for network transmission or persistent storage.
* **Returns**: `str` (JSON string).

#### 2. `get_status`
```python
def get_status(
    self, 
    status: Literal["animation_started", "image_showing", "animation_start", "animation_end", "animation_reverse"]
) -> bool:
```
* **Description**: Extracts a specific logical boolean state by key.
* **Parameters**:
  * `status` (`Literal`): The state property to query.
    * `"animation_started"`: Whether the animation is currently running.
    * `"image_showing"`: Whether the image is visible in the viewport.
    * `"animation_start"`: Whether the animation pointer is currently at the first frame.
    * `"animation_end"`: Whether the animation has reached the last frame (useful for triggering end-of-cycle business logic).
    * `"animation_reverse"`: Whether reverse playback mode is active.
* **Returns**: `bool`.

---

## 4. Frame Animation Machine Class: `AnimatedSprite`

---

### `AnimatedSprite`
```python
class AnimatedSprite:
```
* **Description**: The mainstay of modern object-oriented game development. It organizes a complete set of pose states (e.g., `idle`, `run`, `attack`, `jump`) for an entity in memory, switches between them via a simple `play("run")` call, and supports delta-time (DT) adaptation and keyframe event callbacks (e.g., triggering a hit on frame 3).

### **Constructor**
```python
def __init__(self, x: float = 0.0, y: float = 0.0):
```
* **Parameters**:
  * `x`, `y` (`float`, default `0.0`): The initial physical origin coordinates of the sprite in world space.

### **Public Methods**

#### 1. `add_state`
```python
def add_state(self, state_name: str, images: list, fps: float = 10.0, loop: bool = True) -> None:
```
* **Description**: Adds or overwrites a state suite to the sprite's action library.
* **Parameters**:
  * `state_name` (`str`): The name of the action (e.g., `"idle"`, `"shoot"`).
  * `images` (`list[Image]`): A list of QGame `Image` pointers for the sequence.
  * `fps` (`float`, default `10.0`): The desired playback frame rate for this action.
  * `loop` (`bool`, default `True`): Whether the animation loops or freezes on the last frame when it reaches the end.

#### 2. `play`
```python
def play(self, state_name: str) -> None:
```
* **Description**: Immediately transitions to the specified animation state. If the state does not exist or is already playing, the call is automatically intercepted to prevent unwanted restarts from high-frequency invocations.
* **Parameters**:
  * `state_name` (`str`): The name of the action to transition to.

#### 3. `bind_frame_event`
```python
def bind_frame_event(self, state_name: str, frame_index: int, callback: Callable[[], None]) -> None:
```
* **Description**: **Frame event trigger mechanism**. Triggers a specific handler function when the specified action reaches the designated frame. For example, triggering hit detection on frame `3` of the `"attack"` action, or footstep sound effects on frame `4` of the `"run"` action.
* **Parameters**:
  * `state_name` (`str`): The target action name.
  * `frame_index` (`int`): The target frame index (0-based).
  * `callback` (`Callable`): A no-argument callback function to execute when the condition is met.

#### 4. `update`
```python
def update(self, dt: float) -> None:
```
* **Description**: Must be called on every clock tick in the game loop. Pass in `delta_time` to adjust the timestep, ensuring that animation timing remains smooth and consistent despite network latency or frame rate fluctuations.
* **Parameters**:
  * `dt` (`float`): The delta time interval.

#### 5. `get_current_image`
```python
def get_current_image(self) -> Optional[Image]:
```
* **Description**: Retrieves the actual physical image handle corresponding to the current pose of the animation machine, for use with `qgame.draw.image`.
* **Returns**: An `Image` instance, or `None` if no state is active.

---

## Popup & File Dialog System (`qgame.messagebox`)

`MessageBox` is an **advanced popup interaction system** in the `qgame` engine. To maintain immersion and visual consistency in the game, it is built on PySide6 with a custom frameless, draggable, and freely skinnable modern popup, along with a file picker interface — eliminating the need for developers to directly import PySide6 complexity into their main program.

Below is a detailed technical overview of `MessageBox`, including component structure, function names, and parameter explanations.

---

### I. Helper Class: `DraggableMessageBox`

Inherits from the native `QMessageBox`. When the popup is set to frameless (`frameless=True`), the default system title bar disappears. This class overrides mouse events to enable **dragging by clicking and holding anywhere on the background area**.

*   **`__init__(self, parent=None, draggable=True)`**
    *   `parent`: The parent window.
    *   `draggable`: Whether mouse dragging is enabled.

---

### II. Core Class: `MessageBox` Interface & Parameter Details

#### 1. Core Display Method: `show()`

This is the most general popup method, supporting fully customizable buttons, icons, themes, and coordinates.

*   **`show(title="System Prompt", message="", buttons=["OK"], icon="info", canvas=None, draggable=True, frameless=True, coords=None, theme="nord") -> str`**
    *   **Parameter Descriptions**:
        *   `title (str)`: The popup title (displayed in the taskbar or when frameless mode is off).
        *   `message (str)`: The popup's main text content.
        *   `buttons (list[str])`: An array of button options, e.g., `["Agree & Continue", "Decline & Exit"]`.
        *   `icon (str)`: Preset icon type. Options: `"info"`, `"success"`, `"warning"`, `"error"`, `"question"`.
        *   `canvas`: The bound canvas object. If provided, the popup will be **absolutely centered** in the game viewport and use modal blocking (the player cannot interact with the main game window until the popup is closed).
        *   `draggable (bool)`: Whether dragging by the background is allowed. Defaults to `True`.
        *   `frameless (bool)`: Whether to hide the native system title bar. Defaults to `True`, giving the popup a more modern appearance.
        *   `coords (tuple[int, int])`: The initial pixel coordinates `(x, y)` for the popup.
        *   `theme (str | dict)`: The theme. Accepts preset theme names (e.g., `"nord"`, `"dark"`, `"light"`), or a custom CSS style `dict` passed directly.
    *   **Return Value**: Returns the text of the button clicked by the user (as a `str`). For example, if "Agree & Continue" is clicked, returns `"Agree & Continue"`.

---

#### 2. Convenience Popup Wrappers

The system provides 6 simplified wrapper functions for different use cases. All of these ultimately call `show()` under the hood:

*   **`info(message, title="Info", canvas=None, lang="cn", **kwargs) -> str`**
    *   Information prompt popup. Default button is `["OK"]` when `lang="cn"`, or `["Yes"]` when `lang="en"`.

*   **`success(message, title="Success", canvas=None, lang="cn", **kwargs) -> str`**
    *   Success notification popup. Default button is `["OK!"]` or `["OK!"]`.

*   **`warning(message, title="Warning", canvas=None, lang="cn", **kwargs) -> str`**
    *   Warning popup. Default button is `["I understand"]` or `["I know"]`.

*   **`error(message, title="Error", canvas=None, lang="cn", **kwargs) -> str`**
    *   Error report popup. Default button is `["OK"]` or `["Yes"]`.

*   **`question(message, title="Question", canvas=None, lang="cn", **kwargs) -> str`**
    *   Question popup. Default has two buttons: `["OK", "Cancel"]` or `["Yes", "Cancel"]`.

*   **`confirm(message, title="Confirm Action", canvas=None, lang="cn", **kwargs)`**
    *   Confirmation popup. Similarly defaults to two buttons.

---

#### 3. File Resource Picker: `select_file()`

A utility function that opens the system file browser without polluting your main program's dependencies.

*   **`select_file(title="Select Local File", file_filter="All Files (*.*)", canvas=None) -> str`**
    *   `title (str)`: The file explorer window title.
    *   `file_filter (str)`: A filter string, e.g., `"Image Files (*.png *.jpg);;All Files (*.*)"`.
    *   `canvas`: The bound parent viewport.
    *   **Return Value**: Returns the absolute file path (as a `str`) selected by the user, or an empty string `""` if cancelled.

---

#### 4. Advanced Theme Mapping: `add_theme()`

Supports dynamically registering custom UI themes, defined via RGB tuples or hex color codes.

*   **`add_theme(name, bg, border, text, btn_bg, btn_hover, btn_text)`**
    *   `name`: The identifier for your custom theme.
    *   `bg` / `border` / `text` / `btn_bg` / `btn_hover` / `btn_text`: Accepts RGB tuples `(R, G, B)` or hex strings `"#HEX"`. Once registered, you can use the theme via `show(theme="ThemeName")` in subsequent calls.

For example, the default `"nord"` theme is configured as:

```python
"nord": {
    "bg": "#2e3440", "border": "#4c566a", "text": "#eceff4",
    "btn_bg": "#434c5e", "btn_hover": "#88c0d0", "btn_text": "#eceff4"
}
```

---

### 💡 Brief Summary

`MessageBox` is a **highly customizable modern game popup system**. By wrapping `QMessageBox` and overriding mouse events, it enables **frameless dragging** and **one‑click theme switching** between dark/aurora styles. Developers can dispatch blocking or non‑blocking notifications in the main loop with minimal code (e.g., `MessageBox.success("Loaded successfully!", canvas=self)`) — without having to deal with the complexity of PySide6's low‑level layout code.

---

## UI Input & Container Controls (`qgame.ui`)

QGame UI controls fully support an **adaptive proportional high‑DPI scaling mechanism**. The proportions, font sizes, corner radii, 9‑slice texture stretch margins, and even the physical thickness of circular progress bars of all UI controls will automatically scale with the viewport resolution, maintaining perfect pixel clarity on high‑DPI displays or when toggling full‑screen via F11.

*   **Minimalist On‑Demand Configuration**: All `set_theme()` methods on controls support **optional keyword arguments** (e.g., you can quickly change colors by simply writing `set_theme(text_color=(0, 255, 0))`). Any unspecified style attributes safely inherit from the default advanced dark‑tech theme, so you don't need to pass redundant `None` values.
*   **Image & Universal SVG Support**: All controls support not only standard `.png` and `.jpg` foreground/background images, but also high‑quality `.svg` vector rendering via `QSvgRenderer`, which rasterizes vector graphics in real time based on physical pixels during viewport refreshes—ensuring razor‑sharp visuals even on 4K or 8K screens.

---

### 1. `Button` (Button Control)

Presents a native interactive button on the game canvas that supports hover color changes, click‑down states, local icons, and global shortcut key triggering.

*   **`__init__(coords: tuple[float, float], width: int, height: int, text: str = "")`**
    *   `coords`: Virtual coordinates; supports passing a tuple `(x, y)` or dynamic lambda coordinate generation.
*   **`set_theme(normal_bg=None, hover_bg=None, pressed_bg=None, border_color=None, text_color=None, border_radius=None, font_size=None, font_family=None, font_weight=None)`**
    *   Configures background colors, borders, font sizes, weights, and corner radii for the three button states (normal, hover, pressed).
*   **`set_image(image_path: str)`**
    *   Sets a high‑fidelity foreground icon for the button. The icon automatically clears the button's existing text and scales proportionally with the button size.
*   **`set_image_bg(image_path: str, top=12, right=12, bottom=12, left=12)`**
    *   Uses the 9‑slice stretching algorithm to fill the button with a background texture, ensuring borders and corners never distort when stretched.
*   **`connect(callback: Callable[[], None])`**
    *   Binds a callback function to be triggered when the button is clicked (on mouse release).
*   **`set_shortcut(shortcut_str: str)`**
    *   Binds a physical keyboard shortcut (e.g., `"Return"`, `"Space"`, `"Ctrl+S"`) to the button; pressing it is equivalent to clicking the button.
*   **`set_enabled(enabled: bool)`**
    *   Pass `False` to immediately disable the button, applying the gray disabled state and blocking user clicks.
*   **`set_text(text: str)` / `get_text()`**
    *   Modifies or retrieves the button's text.
*   **`set_visible(visible: bool)`**
    *   Shows or hides the button.
*   **`destroy()`**
    *   Safely unloads and physically destroys the button.

---

### 2. `Panel` (Draggable Floating Window Container)

An advanced panel container often used for large equipment panels, settings windows, or network chat lobbies. It supports recursive nesting of buttons, radio buttons, text boxes, and cascading size calculations.

*   **`__init__(coords: tuple[float, float], width: int, height: int, title: str = "Window", hide_close: bool = False)`**
    *   `title`: Title bar text.
    *   `hide_close`: **【Core Update】** If set to `True`, the ✕ close button in the top‑right corner is completely removed, hiding the physical exit button. Developers can then let users accept agreements or control the close flow via internal buttons.
*   **`set_theme(header_bg=None, content_bg=None, border_color=None, border_radius=None, font_size=None, text_color=None, font_family=None, font_weight=None)`**
    *   Configures the title bar background, content area background, border color, corner radius, and title text size/weight.
*   **`set_image_bg(image_path: str, top=24, right=24, bottom=24, left=24)`**
    *   Sets a 9‑slice stretched background image (e.g., parchment paper or dark metal frame texture).
*   **`add_widget(obj)`**
    *   Inserts a UI control. The inserted object is detached from the main game window, controlled, and mounted under the Panel's local layout system, cascading its position and scaling with the Panel's drag and resize events.
*   **`connect_close(callback: Callable[[], None])`**
    *   **【Core Update】** Close signal slot. Whether triggered by the user clicking the ✕ button or by calling `.close()` in script, this callback is invoked immediately, allowing developers to catch the event (e.g., to auto‑pause the game or save cloud data).
*   **`close()`**
    *   Closes the panel and synchronously fires the close signal to registered callbacks.
*   **`set_visible(visible: bool)`**
    *   Shows or hides the entire panel and all its child widgets.

---

### 3. `Label` (Label & High‑Definition Foreground Drawing Control)

A pure text or high‑definition image display layer. When no text is set and an image is loaded, it can serve as a high‑performance adaptive flat illustration or UI background layer.

*   **`__init__(coords: tuple[float, float], width: int, height: int, text: str = "")`**
*   **`set_text(text: str)` / `get_text()`**
*   **`set_theme(text_color=None, bg_color=None, font_size=None, font_family=None, font_weight=None)`**
*   **`set_image(image_path: str)`**
    *   Sets the foreground image. During stretching and resolution scaling, the system internally applies lossless rasterization to prevent blurring.
*   **`set_image_bg(image_path: str, top: int = 0, right: int = 0, bottom: int = 0, left: int = 0)`**
    *   Sets a 9‑slice background texture.
*   **`set_position(x, y)` / `set_size(width, height)` / `destroy()`**

---

### 4. `ProgressBar` (Anti‑Aliased Progress & Health Bar Control)

A multi‑posture numerical visualization tool with anti‑aliased rounded borders, featuring a **high‑fidelity blocking loader**. Works for horizontal, vertical, and circular progress bars.

*   **`__init__(coords: tuple[float, float], width: int, height: int, direction: str = "horizontal")`**
    *   `direction`: Options are `"horizontal"`, `"vertical"`, or `"circular"`.
*   **`set_value(val: float)`**
*   **`set_range(min_val: float, max_val: float)`**
*   **`set_show_text(show: bool)`**
    *   Whether to elegantly display percentage text at the center.
*   **`set_circular_thickness(thickness: int)`**
    *   When direction is `"circular"`, changes the physical pixel thickness of the rotating energy ring.
*   **`set_theme(bg_color=None, fill_color=None, border_color=None, text_color=None, border_radius=None, border_width=None, font_size=None, font_family=None, font_weight=None)`**
*   **`load_tasks(tasks: list[Callable], on_progress: Callable = None, on_complete: Callable = None)`**
    *   **【Thread‑Level Anti‑Freeze Task Loader】** Sequentially executes time‑consuming no‑argument loading functions (e.g., loading textures, connecting to networks, parsing audio tracks). During loading, it periodically pumps the underlying event queue to refresh the viewport, ensuring that **no "window not responding" or gray‑screen freezes occur**—even if the player drags or interacts heavily.

---

### 5. `Slider` (High‑Sensitivity Interactive Slider)

*   **`__init__(coords, width, height, direction = "horizontal")`**
    *   `direction` can be `"horizontal"` or `"vertical"`.
*   **`set_value(val: int)` / `get_value() -> int`**
*   **`set_range(min_val: int, max_val: int)`**
*   **`connect(callback: Callable[[int], None])`**
    *   Attaches a value listener; when the user drags the slider, the latest value (as an integer) is passed to the callback in real time.
*   **`set_theme(track_bg_color=None, track_fill_color=None, handle_color=None, handle_hover_color=None, track_height=None, handle_width=None, handle_height=None)`**
    *   Allows fine‑grained customization of the slider handle, filled track, and unfilled track colors and corner radii.

---

### 6. `TextBox` (Native Text Input Box)

A component that players can click to invoke the IME and directly type Chinese, English, or complex game console commands.

*   **`__init__(coords, width, height, placeholder="", multi_line=True)`**
    *   `multi_line`: Pass `False` to switch to a single‑line (QLineEdit) mode; multi‑line uses QTextEdit with smooth scrolling.
*   **`set_theme(bg_color=None, text_color=None, border_color=None, border_radius=None, font_size=None, font_family=None, font_weight=None)`**
*   **`set_image_bg(image_path: str, top=6, right=6, bottom=6, left=6)`**
    *   Fills the background with a 9‑slice texture for a stylish retro input look.
*   **`get_text() -> str` / `set_text(text: str)` / `clear()`**
*   **`set_focus()`**
    *   Automatically highlights and captures keyboard focus without clicking, making it easy to enter typing mode quickly.

---

### `SecureInput`

`SecureInput` is a **high‑security physically isolated input field** in the `qgame` engine, specifically designed for handling sensitive data such as passwords and secret keys. Unlike a regular `TextBox`, its goal is to minimize the time that plaintext data resides in memory — approaching zero.

Below is the detailed technical manual for `SecureInput`:

---

### 1. Class Definition & Initialization

**Class Name:** `qgame.ui.SecureInput`

*   **`__init__(self, coords, width, height, placeholder)`**
    *   `coords`: `tuple[float, float]` – The `(x, y)` coordinates of the widget on the virtual canvas.
    *   `width`: `int` – The width of the widget.
    *   `height`: `int` – The height of the widget.
    *   `placeholder`: `str` – The placeholder hint text when nothing is entered. Defaults to `"WAITING FOR ENCRYPTED FREQUENCY..."`.

---

### 2. Core Functional Methods

#### 🚀 `access_data(self, consumer_func)` 【Most Critical API】

Due to the security design, this control **does not** provide a `get_text()` method. If you need to read the content (e.g., for hash verification or sending to a server), you must use this gatekeeper function.

*   **Parameter `consumer_func`**: A callback function (typically a `lambda` or `def`) of the form `func(plaintext: str)`.
*   **Workflow**:
    1.  Decrypts the plaintext from the protected memory buffer (XOR‑obfuscated) momentarily.
    2.  Immediately passes the plaintext to your `consumer_func`.
    3.  **Physical Erasure**: Once your function finishes executing, the control immediately overwrites that memory block with zeros and triggers garbage collection.
*   **Usage Example**:
    ```python
    # Verify a password
    success = txt_pass.access_data(lambda p: qgame.hash.verify_password(p, stored_hash))
    ```

#### 🧹 `clear(self)`
*   **Action**: Immediately clears the input content and manually resets all bytes in the memory buffer to `0`. Recommended for manual invocation when switching scenes or resetting a login form.

#### 🎯 `set_focus(self)`
*   **Action**: Gives keyboard focus to the input field (cursor is placed directly inside).

#### 💥 `destroy(self)`
*   **Action**: Thoroughly destroys the widget, removes it from the UI management queue, and performs memory erasure.

---

### 3. Three Core Security Barriers

1.  **Memory Layer (XOR Obfuscation)**
    *   Internally uses `bytearray` instead of `string` for storage.
    *   **Random Salt Encryption**: A random 64‑bit `_xor_key` is generated upon initialization.
    *   **Instant Obfuscation**: Each keystroke is immediately XOR‑encoded against this key before being stored in memory. The memory always contains meaningless binary garbage, so plaintext cannot be found via cheat tools like Cheat Engine.

2.  **Physical Layer (Interaction Blocking)**
    *   **Disables Right‑Click Menu**: Prevents "Show Plaintext" or copy via context menu.
    *   **Disables Clipboard**: Blocks system‑level **Copy (Ctrl+C)**, **Paste (Ctrl+V)**, and **Cut (Ctrl+X)** operations to prevent passwords from leaking to an insecure clipboard.
    *   **Disables Drag‑and‑Drop**: Prevents dragging password content to other application windows.

3.  **Lifecycle Layer (Self‑Destruction)**
    *   Plaintext exists only for the few microseconds during the `access_data` call.
    *   **Manual Overwrite**: Leverages Python's mutable `bytearray` to fill the memory block with zeros immediately after processing.

---

### 💡 Concise Summary

**`SecureInput` = Obfuscated Memory Storage + Physical Action Lockdown + Instant Self‑Destruction After Access.**

It solves the problem of "attackers scanning memory and reading plaintext passwords directly" by altering the data's form and strictly controlling the lifetime of plaintext.

---

### 7. 🚀 `ListWidget` (Multi‑Functional Draggable List) — **NEW!**

A versatile container designed for in‑game item grids, configuration folders, and custom level editors.

*   **`__init__(coords: tuple[float, float], width: int, height: int)`**
*   **`add_item(text: str, icon_path: str = None) -> int`**
    *   Appends a row of text to the end of the list, optionally with a left‑aligned icon (fully supports `.svg` / `.png`).
*   **`clear()`** / **`remove_item(index: int)`**
    *   Clears the list or removes the row at the specified index.
*   **`get_selected_index() -> int`**
    *   Returns the currently highlighted row index (returns `-1` if none selected).
*   **`get_selected_text() -> str`**
*   **`set_draggable(enabled: bool)`**
    *   **【Mouse Drag Sorting】** Pass `True` to allow players to **drag items up and down** to reorder the list seamlessly, with smooth insertion guides and index auto‑correction.
*   **`set_context_menu(menu_items: list[str], callback: Callable[[int, str, str], None])`**
    *   **【Right‑Click Bubble Menu】** Injects a semi‑transparent floating option group. For example, `["🪓 Equip", "🧪 Recycle", "🗑️ Discard"]`. Clicking any item triggers `callback(selected_row_index, original_text, clicked_action_text)`, making inventory/backpack interaction development instant and effortless.
*   **`connect_clicked(callback: Callable[[int, str], None])`**
    *   Attaches a left‑click listener.
*   **`connect_double_clicked(callback)`**
    *   Connects a double‑click listener for quick item usage/equipping.
*   **`set_theme(bg_color=None, text_color=None, border_color=None, border_radius=None, item_hover_bg=None, item_selected_bg=None, font_size=None, font_family=None, font_weight=None)`**
    *   Supports detailed theming for list item normal, hover, and selected states.

---

### 8. 🚀 `ComboBox` (High‑Quality Flat Dropdown Selection) — **NEW!**

The perfect companion for multiple‑choice game settings like resolution selection, anti‑aliasing modes, and physics frequency options.

*   **`__init__(coords: tuple[float, float], width: int, height: int)`**
*   **`add_items(items: list[str])`**
    *   Batch‑adds a list of dropdown options.
*   **`clear()`**
*   **`get_selected_index() -> int`** / **`get_selected_text() -> str`**
*   **`set_selected_index(index: int)`**
*   **`connect_changed(callback: Callable[[int, str], None])`**
    *   When the selected item changes, immediately passes `(new_index, new_selected_text)` to the callback.
*   **`set_theme(bg_color=None, text_color=None, border_color=None, border_radius=None, font_size=None, font_family=None, font_weight=None)`**
    *   Allows beautiful theming of the dropdown bubble, hover, and selection effects.

---

### 9. 🚀 `CheckBox` (Futuristic Glowing Checkbox) — **NEW!**

The most intuitive control for boolean toggles such as sound effects, collision box visibility, and more.

*   **`__init__(coords: tuple[float, float], width: int, height: int, text: str = "")`**
*   **`set_checked(checked: bool)`**
*   **`is_checked() -> bool`**
    *   Quickly checks whether the checkbox is currently checked.
*   **`connect(callback: Callable[[bool], None])`**
    *   Attaches a sensitive callback that fires whenever the state changes, returning a boolean value.
*   **`set_text(text: str)`**
*   **`set_theme(bg_color=None, text_color=None, active_color=None, font_size=None, font_family=None, font_weight=None)`**
    *   `active_color`: Configures the glowing accent color when checked.

---

## 💻 `CodeText` Code / Rich Text Editor

`CodeText` is a highly advanced multi‑line rich text and code editor. It fully integrates a custom highlighter pipeline based on QRegularExpression, with high‑frequency suggestion popups, squiggly underline warnings, tooltips anchored to the cursor, and gesture‑level viewport font scaling.

```
     ┌────────────────────────────────────────────────────────┐
     │  # 1. Automatic Highlighting (Regular Expressions)     │
     │  def init_system():                                    │
     │      qgame.init()                                      │
     │                                                        │
     │  # 2. Error Squiggly Markers (add_marker)              │
     │      eror_code = 404                                   │
     │      ~~~~~~~~~  <--- [Error Wave Marker]               │
     │                                                        │
     │  # 3. Cursor‑Anchored Tooltip (show_tooltip)           │
     │      ┌───────────────────────┐                         │
     │      │ 💡 [qgame.init Tooltip]│                         │
     │      │ Initialize viewport    │                         │
     │      └───────────────────────┘                         │
     └────────────────────────────────────────────────────────┘
```

### 1. Core Properties & Methods

*   **`CodeText(coords: tuple, width: int, height: int, placeholder: str = "")`**
    *   Constructs a high‑precision editor viewport.
*   **`add_highlight_rule(pattern: str, color: tuple, bold: bool = False, italic: bool = False)`**
    *   Binds custom syntax‑highlighting rules via regular expressions.
    *   `pattern`: The highlight regex, e.g., `r'\b(def|class|import|from|return)\b'` for Python keywords.
    *   `color`: An RGB triplet `(R, G, B)`.
*   **`add_marker(start_pos: int, length: int, line_type: str, color: tuple)`**
    *   Marks a specific text segment with a visual warning line.
    *   `line_type`: Options: `"wave"` (squiggly underline), `"straight"` (solid underline), `"dash"` (dashed), or `"dot"` (dotted).
*   **`clear_markers()`**
    *   Clears all warning markers in the text area.
*   **`set_suggestions(words: list[str])`**
    *   Provides an auto‑completion word list. Type a few characters and press **`[Ctrl + Space]`** to bring up a floating suggestion list.
    *   **Overlap‑Prevention**: The completer replaces the original word safely (e.g., `"qga"` → `"qgame"`), avoiding duplicates like `"qgaqgame"`.
    *   **Smart Auto‑Dismiss**: The suggestion list automatically hides when you type a space, newline, or when the current input exactly matches a candidate word.
*   **`set_tab_spaces(count: int)`**
    *   Sets the number of spaces for Tab indentation; defaults to `4`.
*   **`show_tooltip(text: str, x: int = -1, y: int = -1)`**
    *   Displays a fully developer‑controlled adaptive tooltip popup.
    *   **Cursor‑Following**: When `x` and `y` are omitted (or set to `-1`), the tooltip automatically positions itself below the current text cursor, with built‑in edge‑detection to prevent overflow.
    *   **Scrollable Long Content**: If the tooltip content exceeds `130px` in height, a custom narrow scrollbar automatically appears on the right.
*   **`hide_tooltip()`**
    *   Hides the displayed tooltip.

---

### 2. ⚡ Gesture‑Level Font Scaling (Ctrl + Mouse Wheel)

To ensure visual accessibility across all resolutions, `CodeText` includes IDE‑grade gesture scaling. **Hold the `[Ctrl]` key and scroll the mouse wheel** to smoothly scale the text size from `6px` to `72px` with seamless redrawing.

---

### 3. Advanced API Development Example

```python
import qgame

qgame.init()
canvas = qgame.set_settings(width=800, height=600, title="Advanced Code Editor Demo")

# 1. Create a high‑performance CodeText sandbox with detailed indentation settings
editor = qgame.CodeText((100, 100), 600, 380, placeholder="Start typing here...")
editor.set_theme(bg_color=(20, 24, 30), text_color=(230, 240, 255), font_size=14, font_weight="normal")
editor.set_tab_spaces(2)  # Tab → 2 spaces, great for front‑end developers

# 2. Inject rich syntax‑highlighting rules
editor.add_highlight_rule(r'\b(def|class|import|from|return|if|elif|else)\b', (94, 129, 172), bold=True)
editor.add_highlight_rule(r'("[^"\\]*(?:\\.[^"\\]*)*"|\'[^\'\\]*(?:\\.[^\'\\]*)*\')', (163, 190, 140))  # Strings
editor.add_highlight_rule(r'#.*', (101, 115, 126), italic=True)  # Gray italic comments

# 3. Set up the suggestion dictionary
editor.set_suggestions(["qgame", "set_settings", "set_theme", "CodeText", "draw", "update", "quit"])

# 4. Draw a red warning squiggly at character 15, length 8
editor.add_marker(15, 8, "wave", (235, 94, 94))

# 5. Fully controlled tooltip near the bottom‑right of the code area
guide_docs = (
    "⚠ ERROR DETECTED\n"
    "---------------------------------\n"
    "Typo! 'draw_txt' not found.\n"
    "Did you mean one of these?\n"
    "1. qgame.Draw.text\n"
    "2. qgame.draw.rect"
)
editor.show_tooltip(guide_docs, x=150, y=280)

# 6. Start the game loop
clock = qgame.Clock()
running = True
while running:
    clock.tick(60)
    for event in qgame.events.get():
        if event.type == qgame.eventType.QUIT:
            running = False

    qgame.draw.fill(canvas, (24, 26, 32))
    qgame.window.update()

qgame.quit()
```

## Scene Management (`qgame.scene`)

### `Scene` (Base Class)
Extend this to organize game states.
* **`on_enter(*args, **kwargs)`**
  Triggered when switching *into* this scene.
* **`on_exit()`**
  Triggered when switching *out of* this scene. UI children registered via `add_ui()` are automatically destroyed.
* **`handle_event(event)`, `update(dt)`, `draw(canvas)`**
* **`add_ui(widget)`**
  Registers and auto-binds UI components to the lifecycle of this scene.

### `scene_manager`
* **`switch(new_scene_instance, *args, **kwargs)`**
* **`handle_event(event)`, `update(dt)`, `draw(canvas)`**

---

## Plot Dialogue Box (`qgame.dialog`)

### `DialogBox` (Branching dialogue canvas)
* **DPI responsive scaling**: Automatically binds to parent window geometries, dynamically resizing line heights, padding gaps, avatar grids, and option boundaries during full-screen stretch modes.
* **Typewriter Pipeline**: Renders characters progressively using an internal timer. Clicking the box wrapper stops the typewriter process and instantly fills the text area.
* **Dual Avatar Schemes**: Supports rendering oversized Emojis directly from strings, or parses files by validating absolute paths (`.png`, `.jpg` layouts).
* **Dynamic Decision Router**: Generates clean choice buttons at the bottom of the box. Clicking buttons routes variables and directs logic to subnodes. Users can register callbacks for complete dialogue chain exits.
---

### `Project Template Generator`
## 💻 Fully Adaptive QGame Terminal Environment Manager & Diagnostic Chip (CLI)
Fixed text overlap and Chinese garbled character issues on Windows platforms (CMD, GBK consoles) with automatic backward compatibility for legacy DOS frameworks.

### 1. ⚙️ Holographic Environment Diagnostic Tool (`doctor`)
We have set up dedicated physical inspection channels for multi-level packaging, compilation, and runtime dependencies:
*   **`qgame doctor package`**
    Inspects the local packaging and compilation toolchain. Checks the Nuitka accelerator compiler, MinGW (GCC compiler and environment variables), and PySide6-deploy tool status.
    *   *Fix command*: Append the `--fix` flag to let the engine attempt a one-click resolution of packaging/installation issues caused by missing components:
        ```bash
        qgame doctor package --fix
        ```
*   **`qgame doctor lib`**
    Quickly scans for optional runtime extension packages such as multimedia codecs, voice chat backends, and image slicing utilities. If any are missing, the console will display what each module is useful for in project development and automatically align dependencies.

### 2. 📦 Automated Visual Dependency Installation Panel (`install`)
Replaces the old, rigid `qgame icon install` with an upgraded smart one-click express installation box:
*   **`qgame install lib`**
    Launches an interactive fully automated installation manager
    Usage Example:
    ```text
    qgame install lib
[QGame 报错] 未检测到 sounddevice 库，请先运行: pip install sounddevice numpy
[QGame 报错] 未检测到 numpy 库，请先运行: pip install numpy 或 qgame install lib
============================================================
🚀 Welcome to QGame 自动化生态依赖库安装管家
============================================================

👉 正在智能为您寻找，发现您还有 4 个强大的插件尚未安装：
------------------------------------------------------------
  (1) Pillow
      大小概估: ~15.4 MB
      功用解释: Required for png to .ico icon conversion, automatic square cropping and basic image processing tasks

  (2) sounddevice
      大小概估: ~3.8 KB
      功用解释: Required for low-latency audio stream, LAN voice chat, and vocal input triggers

  (3) numpy
      大小概估: ~30 MB
      功用解释: Required for real-time audio matrix processing, vector calculations, and fast coordinates computations

  (4) lupa
      大小概估: ~3.8 MB
      功用解释: Required for executing high-performance Lua MOD scripts, secure sandbox proxies, and custom entity behaviors

------------------------------------------------------------
请输入以下对应指令：
  [ A ] 📦 一键打包，下载安装【全部】缺失的优秀资源 (推荐)
  [ N ] 🛑 狠心拒绝并直接退出
  [ 1 ] ⭐ 仅单独针对性下载安装 Pillow
  [ 2 ] ⭐ 仅单独针对性下载安装 sounddevice
  [ 3 ] ⭐ 仅单独针对性下载安装 numpy
  [ 4 ] ⭐ 仅单独针对性下载安装 lupa

👉 请输入您的抉择与编号指令 (A/N/数字): A

👷 正在全力为您下载安装所挑选的 4 个扩展依赖...
------------------------------------------------------------
⏳ 正在通过 pip 通道为您拉取 Pillow ...
Collecting sounddevice
  Using cached sounddevice-0.5.5-py3-none-win_amd64.whl.metadata (1.4 kB)
Requirement already satisfied: cffi in C:\Users\Administrator\AppData\Local\Python\pythoncore-3.14-64\Lib\site-packages (from sounddevice) (2.1.0)
Requirement already satisfied: pycparser in C:\Users\Administrator\AppData\Local\Python\pythoncore-3.14-64\Lib\site-packages (from cffi->sounddevice) (3.0)
Using cached sounddevice-0.5.5-py3-none-win_amd64.whl (365 kB)
Installing collected packages: sounddevice
Successfully installed sounddevice-0.5.5
✅ 安装成功: sounddevice 已成功注册至本机！
⏳ 正在通过 pip 通道为您拉取 numpy ...
Collecting numpy
  Downloading numpy-2.5.2-cp314-cp314-win_amd64.whl.metadata (6.6 kB)
Downloading numpy-2.5.2-cp314-cp314-win_amd64.whl (12.6 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 12.6/12.6 MB 5.9 MB/s  0:00:02
Installing collected packages: numpy
Successfully installed numpy-2.5.2
✅ 安装成功: numpy 已成功注册至本机！
⏳ 正在通过 pip 通道为您拉取 lupa ...
Collecting lupa
  Using cached lupa-2.8-cp314-cp314-win_amd64.whl.metadata (62 kB)
Using cached lupa-2.8-cp314-cp314-win_amd64.whl (2.0 MB)
Installing collected packages: lupa
Successfully installed lupa-2.8
✅ 安装成功: lupa 已成功注册至本机！
------------------------------------------------------------
📊 操作完毕！本次已自动帮您一键修复了 4/4 个游戏引擎扩展！
============================================================
    ```
    Simply enter `a` at the prompt to pull in all dependencies at once!

---

### 3. 🏹 Game Generation (`game`)
Use `qgame new game --help` to view all available games that can be generated (most names are self-explanatory).

---

## Group (`qgame.group`)

`Group` is a lightweight container for game objects. It is ideal for **batch management**, **parent-child coordinate coupling** (e.g., UI panels with buttons, vehicles with riders, spaceships with turrets, enemy swarms), and **unified lifecycle delegation**.

### `Group` (Hierarchical Container Group)
##### 1. Key Features
* **Parent-Child Coordinate Coupling**:
  Modifying the `Group`'s `x`, `y` properties or calling `move()` automatically shifts all child objects by the exact same offset (delta).
* **Smart Coordinate Remapping**:
  * When calling `add()`, children instantly offset their positions relative to the group's current anchor point.
  * When calling `remove()` or `clear()`, children deduct the parent offset, **seamlessly restoring their absolute world coordinates**.
* **Unified Lifecycle Propagation**:
  Calling `group.update(dt)` and `group.draw(canvas)` in your main game loop executes the corresponding lifecycles for all qualified children, eliminating manual loop boilerplate.
* **Native Python Container Protocols**:
  Supports full iteration (`for child in group:`), length checking (`len(group)`), and membership querying (`if sprite in group:`).

##### 2. Key Methods & Properties
* `Group(x=0, y=0)`: Constructor. Sets the initial parent anchor point.
* `group.x` / `group.y`: Getter/Setter. Adjusting these values shifts all children.
* `group.move(dx, dy)`: Translates the group and all its children incrementally.
* `group.add(*entities)`: Appends one or multiple entities (adds coordinate offset).
* `group.remove(*entities)`: Removes entities (deducts coordinate offset, restores absolute coordinates).
* `group.clear()`: Empties the container and restores native coordinates of all children.
* `group.update(dt, *args, **kwargs)`: Sequentially calls `update()` on all children that support it.
* `group.draw(canvas, *args, **kwargs)`: Sequentially calls `draw()` on all children that support it.

---
###### 3
###### _QGame_: こんにちは 😏
###### _Group_: What? What did you say? 😲
###### _QGame_: あ、僕が言ってるのは日本語だよ 😎
###### _Group_: Let`s speak English. OK? 😡
###### _QGame_: OK. I speak English. 😜
###### _Group_: OK. Hello, QGame, I am 'Group' 😃
###### _QGame_: Oh! \*Handshake\* Hello 'Group'! Welcome to QGame family! 😁
###### _Group_: Family? 🤔
###### _QGame_: Yes! 😎
---

## Advanced Render Accessories

### `Camera` (`qgame.Camera`)
* **`follow(target, lerp_speed)`, `update(dt)`**
  Smoothly interpolates camera positioning. Default recommended `lerp_speed` is `5.0` to `8.0`.
* **`set_deadzone(w, h)`**
  Enforces a static delay window.
* **`set_bounds(min_x, min_y, max_x, max_y)`**
  Locks camera bounding boxes to prevent displaying black edges.
* **`shake(intensity, duration)`**
  Creates screen shake impulses.
* **`apply(coord_or_rect) -> tuple`**
  Transforms world coordinates to screen coordinate outputs.

### `Spritesheet` (`qgame.Spritesheet`)
* **`get_image(x, y, w, h) -> Image`**
  Crops segment coordinate.
* **`parse_grid(tile_width, tile_height, margin=0, spacing=0) -> list[Image]`**
  Slices uniform sheets.
* **`parse_atlas(json_path) -> dict[str, Image]`**
  Loads TexturePacker configuration sheets.

## 🌐 Network Skeleton Interface Reference (`qgame.network`)

Network communication is based on QtNetwork's non-blocking mechanism. You may directly override the logic or bind to the `connect` data slots.

### 📡 1. UDP Packet Network Component
#### `UDPNetworkServer` (UDP Server Listener)
* **`__init__(port: int)`** - Sets the target port for network listening on the local machine.
* **`start() -> bool`** - Starts listening; returns whether the binding was successful.
* **`send_to(data: bytes, host: str, port: int)`** - Broadcasts the byte packet to the specified network address.
* **`connect_receive(callback: Callable)`** - Connects to the receive signal slot. Callback signature: `callback(data: bytes, ip: str, port: int)`.
* **`close()`** - Unregisters the socket.

#### `UDPNetworkClient` (UDP Client)
* **`start(local_port: int = 0) -> bool`** - Opens a local socket for communication.
* **`send(data: bytes, host: str, port: int)`** - Sends a network packet.
* **`connect_receive(callback: Callable)`** - Connects to the response receive signal.

---

### 🕸️ 2. WebSocket Lobby Component
It has already been placed in `qgame/examples/Web/UPD`
#### `WSNetworkServer` (WebSocket Server)
* **`__init__(port: int, server_name: str = "QGame")`** - Initializes the server.
* **`start() -> bool`** - Starts WebSocket listening.
* **`broadcast(message: str)`** - Broadcasts a message to all connected clients.
* **`send_to(client_socket, message: str)`** - Sends a text message to a specific client channel.
* **`connect_client(callback)`** / **`connect_disconnect(callback)`** - Callback slots for client connection and disconnection events.
* **`connect_message(callback)`** - Parses messages from a client. Callback signature: `callback(client_socket, message: str)`.

#### `WSNetworkClient` (WebSocket Client)
* **`connect_to(url: str)`** - Connects to the target endpoint, e.g., `ws://127.0.0.1:80`.
* **`send(message: str)`** - Sends a text command packet.
* **`connect_open(callback)`** / **`connect_close(callback)`** - Callbacks for successful connection and disconnection.
* **`connect_message(callback)`** - Listens for messages from the server. Callback signature: `callback(message: str)`.

### 🎙️ 3. LAN Real-Time Bidirectional Voice Chat Component (`QGameVoiceChat`)
Requires optional dependency support. If the package is missing, run the terminal command `qgame install lib` to invoke the installation manager for one-click repair.

#### `QGameVoiceChat` (UDP Audio Peer Connector)
*   **`__init__(target_ip: str, bind_port: int = 19999, target_port: int = 19999)`**
    Initializes an independent bidirectional audio communication line.
    *   `target_ip`: The LAN/public IP address of the call peer (teammate).
    *   `bind_port`: The local port for listening to incoming voice signals from the peer. Default: `19999`.
    *   `target_port`: The receiving port on the peer's machine for the voice data you send. Default: `19999`.
*   **`start()`**
    Officially starts the voice call. Simultaneously creates a background audio thread on the local machine for bidirectional operations: microphone capture + high-ratio zlib network compression + UDP low-latency real-time transmission; asynchronous reception of remote audio data + PCM restoration + ultra-fast output to speakers.
*   **`stop()`**
    Hangs up and fully terminates the current call, completely releasing the sound card channels and socket resources.
*   **`mute(is_muted: bool)`**
    Unmute/Mute the microphone (a practical interactive property that can be bound to hotkeys in the game loop). When muted, it not only stops sending audio packets but also generates no unnecessary network traffic.

---

## 🤖 3. Game AI Reference (`qgame.ai`)

### 🧭 1. A* Smart Pathfinding Component (`PathFinder`)
* **`find_path_on_screen(start_pos: tuple, end_pos: tuple, screen_w: int, screen_h: int, grid_size: int = 32) -> list`**
  **(Core Recommendation)** Input the start screen coordinates and the target pixel coordinates. The algorithm will automatically pull the currently active physics collision boxes stored in `collision.active_colliders` as grid obstacles and perform 8-direction A* pathfinding. Returns a smoothed array of screen pixel target waypoints.

---

### 🔮 2. Behavior Predictor Class (`TrajectoryPredictor`)
* **`__init__(history_len: int = 15)`** - Initializes the prediction queue depth.
* **`update(pos: tuple)`** - Inputs the current position coordinates (x, y) of the target character being followed.
* **`predict_future(steps_ahead: int = 10) -> tuple`** - Based on velocity and first-order/second-order inertial acceleration trends, predicts the target's screen pixel position several frames ahead.

---

### ⌨️ 3. Input Predictor Class (`InputPredictor`)
* **`__init__(n_gram: int = 3)`** - Defines the minimum record length for prediction.
* **`record_action(action)`** - Inputs the player's pressed command.
* **`predict_next() -> Any`** - Based on the player's continuous input patterns, intelligently predicts which key is most likely to be pressed next, returning the key object.

#### `Debug window`
* **`qgame.debugger.init(width=360, height=600, title="Debugger", font_size=11)`**
  Builds and renders the floating debugger window.
  - `width` / `height`: Geometry constraints of the workspace.
  - `title`: Branding string printed centered on the top bar.
  - `font_size`: Nominal size of Console font. Heights and text boundaries automatically align accordingly.
* **`qgame.debugger.watch(name: str, value_func)`**
  Establishes or updates a monitored item record.
  - `name`: Text label drawn on the left column in baby blue.
  - `value_func`: Given as a **lambda expression (like `lambda: obj.health`)** or a plain value. Pass callables as much as possible for dynamic values.
* **`qgame.debugger.unwatch(name: str)`**
  Instructs the panel to stop querying and printing the specified item.
* **Scroll Navigation**
  Hover your mouse pointer on top of the debug pane and use your **mouse wheel** to navigate down if there are more parameters registered than the screen height can fit.
* **Visual Interaction Hints**: Hovering over editable rows changes the mouse cursor to a pointing hand, and the row background highlights dynamically. Editable variable names are distinguished with a pencil icon (`✎`).
  - **Type Reconstruction Mechanics**: Uses Python's Abstract Syntax Trees (AST) internally. If the value being modified is a Boolean, Float, or even a List (`[1, 2, 3]`), the engine will convert the inputted user string back into its correct Python type instead of writing it back as a raw string.
  - **Usage / API Examples**:
    To allow write-back capability, you pass the parent object and the attribute name string as a `tuple`, or specify a custom `setter` callback:

    ```python
    # 1. Attribute Reflection Mode (Reads & Writes (player.speed) directly)
    qgame.debugger.watch("Player Speed", (player, "speed"))

    # 2. Custom Setter Mode (Uses a lambda to read, and a callback function to write)
    qgame.debugger.watch("Game Difficulty", lambda: world.difficulty, setter=world.set_difficulty)

    # 3. Read-Only Mode (If only a value or single lambda is passed, it remains read-only)
    qgame.debugger.watch("FPS Counter", lambda: clock.get_fps())
    ```

---
**QGame: So good, even the British won‘t go back home.**
**Because they are learning Chinese — and coding with QGame.**
*😉*
---
---

## 安装与运行演示
如果通过 setuptools 安装了库，可以在终端直接运行演示：
```bash
run-qgame-examples
```
或作为模块运行：
```bash
python -m qgame
```

---

## 地图编辑器启动指令
内置的关卡拼装器，快速在电脑端直观拼装地图：
```bash
python -m editor
```
创建多瓦片图层、配置每一格的红色碰撞信息，点击“保存”即可生成加密格式的 `.qmap` 数据文件。

---

## 可视化对话框编辑器
* **三段式直观排版**：采用精美暗黑主题。左侧列表统筹节点归纳（增删改）；中部编辑单个节点所涉及的内容（如发言人、Emoji 表情名称、文本）；右侧管理分支按键。
* **断链防御逻辑**：单向连续下一步选择栏与分支表格的选择列均具备数据库联动保护，**自动读取并生成目前已存在的节点供下拉框选取**，避免拼写错误导致死链。
* **文件无阻读盘**：能够随时导入既有配置文件二次修改，一键输出整洁缩进的 JSON 会话文件，游戏端可实现零代码加载。
运行方式：
```bash
run-qgame-dialog-editor
```

---

## 核心模块 (`qgame`)

### 全局函数
* **`init()`**
  初始化 PySide6 的 Application 上下文。在一切绘制开始前必须最先调用。
* **`set_settings(*, width: int, height: int, title: str = "QGame", icon_path: str = None, scaling_mode: Literal["letterbox", "crop", "stretch", "adaptive"] = "letterbox") -> QImage`**
  设定游戏的分辨率和主窗口标题。返回渲染使用的主画布（`QImage` 实例）。
* **`show_splash(image_path: str = None, duration: float = 2.0, *, echo_error: bool = True)`**
  展示游戏启动闪屏，附带淡入与淡出的平滑半透明过度。如果未传参数，则使用QGame的logo。如果路径不存在且echo_error为True，报FileNotFoundError，反之打印错误

### `window` (窗口实例)
* **`update()`**
  刷新渲染画面并接收系统事件，在游戏主循环中每帧调用一次。
* **`set_title(title: str)`**
  动态更改窗口标题。
* **`set_icon(icon_path: str)`**
  加载并应用窗口图标。
* **`set_size(width: int, height: int) -> QImage`**
  动态调整画面虚拟画布尺寸。
* **`toggle_fullscreen()`**
  在全屏模式与窗口模式之间无缝切换。
* **`show_cursor(visible: bool)`**
  显示或隐藏系统鼠标光标。
* **`get_all_windows() -> list`**
  返回所有窗口实例
* **`get_width(window=None) -> int`**
  返回窗口宽度
* **`get_height(window=None) -> int`**
  返回窗口高度
* **`get_size(window=None) -> int | tuple[int, int]`**
  返回窗口高度和宽度的元组

### `events` (事件获取)
* **`get(window=None) -> List[Event]`**
  取出事件队列中所有的挂起事件。
* **`get_mouse_pos() -> tuple`**
  获取鼠标位置。
* **`wait_for_event(event_type: int, timeout: float = None) -> Event | None`**
  局部阻塞当前线程，直到指定的系统事件发生或达到超时秒数。
* **`get_key_state(key_code: int) -> bool`**
  键盘状态侦测。绕过系统按键重频延迟。

### `Clock` (时钟类)
* **`tick(fps: int) -> float`**
  锁定帧率并返回两帧之间的间隔时长 `dt`（单位：秒）。

---

## Tween 缓动插值系统 (`qgame.tween`)

### `tween` (它的全局单例实例)
通过声明式编程快速构建平滑渐变动效。
* **`to(target, duration: float, ease: str = "linear", delay: float = 0.0, on_complete: Callable = None, **properties)`**
  分派注册一个缓动效果。
  * `target`: 渐变的目标 Python 对象或字典容器。
  * `duration`: 缓动执行总时长（秒）。
  * `ease`: 缓动插值计算的数学函数关键字（如 `"elastic_out"`、`"bounce_out"`、`"sine_out"` 等）。
  * `properties`: 要变换的目标值健值对，例如 `x=300`, `alpha=1.0`。
* **`update(dt: float)`**
  微步驱动正在进行的全部缓动插值。每帧在主循环中tick调用更新。
* **`clear()`**
  清除销毁所有的缓动记录。

---

## ECS 实体框架 (`qgame.ecs`)

### `Entity` (实体类)
游戏角色的底层父类，支持结构分层坐标渲染和许多实用的功能，详情请看更新日志1.7.0版本。
* **物理属性**：`x`, `y`, `size`（大小系数，影响 Size 深度层次）。
* **生命周期**：`update(dt)`, `draw(canvas)`.

### `EntityManager` (实体管理类)
管理大世界场景中的所有可见对象。
* **`add(entity: Entity)`**
* **`remove(entity: Entity)`**
* **`clear()`**
* **`update(dt)`**：更新包内注册的每一个动作帧。
* **`draw(canvas)`**：智能过滤并裁剪视框，最后根据层级绘制。
* **`auto_layer_y = True`**：启动 Y 轴前后景遮挡策略。
* **`auto_layer_s = True`**：启动物象大小缩放层次。

---

## 粒子系统 (`qgame.particles`)

### `ParticleEmitter` (粒子类)
基于底层一维线性内存渲染的轻量粒子发生器。
* **`create_rain(width)`**：雨夜倾盆下坠效果。
* **`create_fire(x, y)`**：火把升空呼吸微粒。
* **`create_explosion(x, y)`**：产生一个定点向外爆开并自动消除的集群离子。
* **`add_collision_rule(condition: tuple | list | object | Callable[[float, float], bool], action: Literal["die", "bounce_y", "bounce_x", "freeze"] | Callable[[list], None])`**：设定规则，做出相应的动作

---
这是一个**超级重量级、能让游戏瞬间晋升成“商业级工业引擎”的隐藏神仙模块！**

在游戏开发界（不论是《魔兽世界》、《愤怒的小鸟》还是《饥荒》），**Python（负责底层引擎） + Lua（负责游戏业务逻辑/MOD脚本）** 都是极其经典且强悍的黄金搭档。

通过 `qgame.script`，游戏开发者可以**把所有的角色属性、关卡剧情、怪物 AI 逻辑写在单独的 `.lua` 文件中**。这不仅能实现**极其优雅的逻辑与引擎解耦**，还能极其轻松地为你的游戏提供**玩家 MOD 开发支持**！

下面是为 QGame 开发者精心撰写的 **`qgame.script`（脚本系统）官方精彩引路指南**！

---

## 🛠️ QGame Lua 脚本系统 (`qgame.script`)

`qgame.script` 是 QGame 的内置**脚本语言跨界桥接系统**。它基于高性能的 `lupa`（JIT 级 Lua 绑定库），允许开发者在保证 Python 游戏窗口飞速渲染的同时，使用极简、轻量的 Lua 语言编写高频的游戏业务代码。

---

### 🎯 为什么要在 QGame 里用 Lua 脚本？

1. **逻辑与引擎彻底分离**：Python 专门做物理碰撞、图像渲染和基础卡位；Lua 专门用来写“NPC 对话”、“关卡触发器”、“武器伤害数值”。
2. **极速运行**：Lua 是世界上最快的脚本解释语言之一。
3. **Mod开发者狂喜**：Lua是游戏界最常用的脚本语言（魔兽世界、愤怒的小鸟、Roblox 都用它），因此Mod开发者能很快上手，就算没做过的，想做的上手也很快！
4. **安全无痛控制台**：彻底解决了 Windows CMD/PowerShell 终端下原生 Lua 打印中文字符串爆出的 **GBK 乱码** 痛点。QGame 在底层劫持并接管了 Lua 的 `print`，让其完美兼容 Python 终端！
5. **无缝的双向交互**：
   * 在 Lua 脚本里，可以直接呼叫 Python 实体的 `.chase()`、`.destroy()`
   * 在 Python 侧，可以直接用 `.call()` 执行 Lua 里的高级 AI 函数。

---

### 🔑 1. 核心接口 API 全览

### 🛑 前置前瞻环境检查
```python
import qgame

# 检查当前系统是否安装了 lupa。若未安装，QGame 会贴心地提示: pip install lupa
print(qgame.script.is_supported())  # 返回 True / False
```

### 📄 加载脚本：`qgame.script.load(source, context=None)`
* **作用**：编译一段 Lua 脚本或直接加载本地 `.lua` 文件。
* **参数**：
  * `source` (str / Path): 可以是本地脚本路径（如 `"scripts/boss_ai.lua"`），或者是直接写的 Lua 代码字符串。
  * `context` (dict): **极其强大！** 可以在装载时将 Python 对象（如 `player` 实例、`window` 等）直接打包灌入 Lua。Lua 脚本中可以直接把它当全局变量来用！

### 转化类型：`qgame.script.table(...)`
* **作用**：将Python的tuple类型转化为lua的表
* **示例**：`qgame.script.table(10, 20)`

### 🚀 运行脚本主体：`LuaScript.run(extra_context=None)`
* **作用**：运行 Lua 的主代码段。只需执行一次
* **参数**：
  * `extra_context` (dict): 运行时临时追加覆盖的 Python 变量映射。

### 📞 跨界精准调用：`LuaScript.call(func_name, *args, optional=False, default=None, err=True)`
* **作用**：不需要运行整段代码，而是直接抓取 Lua 里定义的某个 `function` 并传参运行，直接拿到返回值！

### lua中的函数：`LuaScript.has_function(name)`/`LuaScript.get_function(name, optional=False)`
* **作用**：不需要读取其lua模组文件取查找里面的函数，直接使用`globals`获取/判断，瞬间得到结果！

### 错误：`LuaScript.is_err(called_val, *, echo=False, again = False)`/`is_cheat_err(called_val, *, echo=False, again=False)`
* **作用**：判断是否call的函数是否存在违法行为

---

## 🎮 2. 实战大演练：用 Lua 脚本操纵 QGame 实体！

通过这个极简的小例子，感受一下 Python 和 Lua 之间神奇的“灵魂双向互通”：

### Step 1: 编写 Lua 方的行为脚本 `monster_behavior.lua`
我们在同级目录下新建一个 `monster_behavior.lua`：

```lua
-- monster_behavior.lua
print("[Lua] 🎯 怪物 AI 脚本成功加载并激活！")

-- 1. Lua 可以直接访问 Python 传进来的 "player" 和 "monster" 实例对象！
function on_monster_update(dt)
    -- 计算怪物跟玩家的距离
    local dist = monster:distance_to(player)
    
    if dist > 80 then
        -- 💡 离得远：Lua 直接调用 Python 端的 .chase() 方法命令怪物追击！
        monster:chase(player, dt)
        print("[Lua] 状态：距离玩家 " .. string.format("%.1f", dist) .. "px，正在全速追赶！")
    else
        -- 💡 离得近：Lua 主动触发，让怪物直接啃咬玩家
        player.hp = player.hp - 10 * dt
        print("[Lua] 状态：贴身肉搏中！玩家血量剩余：" .. string.format("%.1f", player.hp))
    end
end

-- 2. 一个在 Lua 内部计算、并返回数据给 Python 的演示函数
function calculate_exp(base_exp, multiplier)
    return base_exp * multiplier + 100
end
```

### Step 2: 编写 Python 主程序驱动
在 Python 侧，利用 `qgame.script` 来绑定运行并传递实体：

```python
import qgame
from qgame.ecs import Entity # 没错，你只用的Entity是在ecs里的
from qgame.script import script

# 1. 初始化 QGame
qgame.init()

# 2. 创建玩家和怪物的实体（拥有 x, y, hp 属性）
class Role(Entity):
    def __init__(self, x, y, name):
        super().__init__(x, y)
        self.name = name
        self.hp = 100.0
        self.speed = 150.0  # 移动速度

player = Role(100, 100, "小明")
zombie = Role(300, 300, "僵尸")

# 3. 🚨 重点：加载 Lua 脚本，并把实体注入进去！
# 将 player、monster 作为全局上下文注册给 Lua，Lua 脚本里拿起来就能用！
ai_script = script.load(
    "monster_behavior.lua", 
    context={"player": player, "monster": zombie}
)

# 运行一次脚本主体代码（完成加载时的 print）
ai_script.run()

# 4. 游戏主循环
clock = qgame.Clock()
for _ in range(3): # 模拟 3 帧
    dt = clock.tick(60)
    
    # 🚨 重点：在 Python 主循环里，直接跨界呼叫 Lua 里的 update 行为函数！
    ai_script.call("on_monster_update", dt)

# 5. 🚨 重点：从 Python 读取 Lua 里的计算结果！
final_exp = ai_script.call("calculate_exp", 50, 1.5)
print(f"[Python] 收到 Lua 的计算数据：本次击杀奖励经验值为 {final_exp} 点！")
```

## 💻 完美的控制台终端输出：
运行 Python 后的终端输出：
```bash
[Lua] 🎯 怪物 AI 脚本成功加载并激活！
[Lua] 状态：距离玩家 282.8px，正在全速追赶！
[Lua] 状态：距离玩家 280.1px，正在全速追赶！
[Lua] 状态：距离玩家 277.4px，正在全速追赶！
[Python] 收到 Lua 的计算数据：本次击杀奖励经验值为 175.0 点！
```

---

### 💡 终极极客开发技巧

1. **热重载（Hot reload）**：
   在做大地图或大型 RPG 关卡时，如果你修改了 `.lua` 脚本里的对话和逻辑，**游戏甚至不需要关闭重启**。直接在键盘侦听里判断有没有按下`F5`或什么键，然后调用`qgame.script.load(...)`，即可在不中断游戏进程的情况下，瞬间更新游戏内所有策划数据！
2. **多层安全沙箱**：
   如果玩家在开发 MOD 时误写了死循环或者拼写错误，`LuaScript` 会用 `RuntimeError` 精准拦截这些崩溃堆栈并打印在 Python 终端里，**绝对不会导致你的游戏主窗口直接闪退**！

---

## 资源和`.qres`VSCode扩展 (`qgame.resource`)

### 资源
resource.py 是 QGame 引擎加载和管理 .qres 资产配置的底层算子，通过三大硬核机制保障游戏数据的健壮性：

1. 极简的双向数据穿透 (GroupRes)
为了让游戏业务层代码极简，重载了 Python 魔法函数：
属性点号直接读取：res.armor.defence
字典中括号间接读取：res["armor"]["defence"]
支持嵌套子组：子代组别自动转化为一个独立的 GroupRes 容器类，向下无限延伸。
2. 强力变量符号表机制 (Symbol Table)
跨变量互赋值：在加载 .qres 文本时会在主进程中维护一个 symbol_table 作用域字典。当检测到 int <mp> mp_max 时，若 mp_max 在之前已被声明过，Python 驱动器会直接用指针读取它的值，实现变量联动配置。
空值占位推导：如果仅写了类型和变量（例如 dict <buffs>，没有写右值值），引擎会根据类型前缀自动灌注 Python 对应的零值（{}、[]、set()、0、0.0、False、None），极具容错性。
带精准行号的 TypeError 异常抛出：一旦出现类型转换异常，会把 .qres 具体哪一行的出错数据、原本的值、期望转换的强类型抛出为可读性极强的 Crash 文本。
3. 双向双规转换
convert(py_class)：能直接读取任意 Python 的 Class 类型树（包含内嵌阶层），将它们扫盘重构成 Resource 对象树。
to_qres()：反向输出算法。将内存中修改好的各种变量、高度嵌套组重新格式化排版，输出为最干净标准的 .qres 纯文本，并能安全地 save() 回磁盘。

### `qres`VSCode扩展
#### 下载：
* 使用`Gitee`下载：https://gitee.com/watermelon-juice-code/qgame-resource-support/blob/master/qgame-resource-support-1.0.0.vsix
* 使用`百度网盘`下载：https://pan.baidu.com/disk/main?from=homeFlow#/index?category=all&path=%2F%E5%85%AC%E5%BC%80%E6%96%87%E4%BB%B6%E5%A4%B9 提取码：code
    *   选择`qgame-resource-support-1.0.0.vsix`并下载
* 使用`夸克网盘`下载：https://pan.quark.cn/s/eeb366929d4b 提取码：TTt3


qgame-resource-support VSCode 编辑器协同功能
该 VSCode 插件并不仅仅是简单的高亮，而是一个与 Python 规则强绑定的轻量级静态语法分析器（Linter）：

1. 强力拦截：Python 变量命名标识符约束
规则阻断：在 Python 中，变量名绝不能以数字开头（如 1player 是非法命名，会引起 SyntaxError）。
插件配合：当插件检测到 < 后面紧跟的是数字时（如 int <2d_pos> [0,0]），会在 VSCode 中直接画红波浪线阻挠，防止此配置文件流入 QGame 游戏主循环造成引擎编译报错。
2. 作用域碰撞（Scope Redefinition）实时纠偏
同组同名检测：在同一个 [Resource.xxx] 分组下如果写了两个同名变量，插件会报红报错。
区块重叠检测：如果写了两个重复的分组声明，插件也会实时标记错误。
跨组影子同名警示（黄色警告）：当不同分层组中使用了相同名字的变量时，会给出黄色双向波浪线警告（可在编辑器 settings 中一键屏蔽），防止策划或开发者在后续通过 symbol_table 进行变量交叉赋权时，产生调用混淆。
3. 语法美化与纯净的 Intellisense 体验
配色优化：为 qres 关键字（str、list 等）、分类组、变量尖括号及数值字面量进行独立高亮。
噪音消除：完全屏蔽了 VSCode 的默认 “abc” 自由词表推荐，输入 < 只会精准推送你提前写好的可用类型以及配置符号。
文件模板自动灌注：当检测到开发者创建了空白 .qres，会自动插入 [Resource] 头部标记，提供最舒适的配置仪式感。
---

## 输入处理 (`qgame.keyboard`, `qgame.mouse`)

### `keys` (按键常量映射)
封装了 PySide6 常用的按键码，如 `keys.W`、`keys.ESCAPE`、`keys.UP`、`keys.SPACE`、`keys.SHIFT` 等。

### `keyboard` (键盘状态侦测)
* **`is_pressed(key_code: int) -> bool`**
  检测某按键当前是否正被按住。

### `mouse` (鼠标状态侦测)
* **`get_pos() -> tuple[int, int]`**
  获取鼠标在虚拟画布分辨率上的相对坐标点 `(x, y)`。
* **`is_pressed(button: int) -> bool`**
  检测某鼠标键当前是否被按住（传参例如 `mouseButtons.LEFT`、`mouseButtons.RIGHT` 等）。

---

## 2D 绘图与渲染 (`qgame.graphics`)

### `Color` (预设色彩类 - `qgame.color`)
集成了渲染常用的色彩定义：
* **标准基础色**：`WHITE`, `BLACK`, `RED`, `GREEN`, `BLUE`, `YELLOW`, `ORANGE`, `PURPLE`, `PINK`, `CYAN`, `BROWN`, `GRAY`。
* **暗度变体**：`DARK_RED`, `DARK_GREEN`, `DARK_BLUE`, `DARK_GRAY` (铁板/基础砖墙)。
* **亮度与发光**：`LIGHT_GREEN` (治愈光环), `LIGHT_BLUE` (冰霜), `LIGHT_YELLOW`, `GOLD` (金币)。
* **特效预设色**：`WOOD_BG` (木地底色), `NIGHT_MASK` (极限黑夜滤镜, RGBA: `10, 10, 25, 248`), `PLAYER_GLOW` (玩家灯具微光), `TARGET_GREEN` (鼠标准星)。
* **Alpha半透明**：`TRANSPARENT`, `SHADOW_50`, `SHADOW_80` (暂停弹窗底幕), `WHITE_GLOW` (微白高亮)。

### `Align` (自适应位置与矢量网格生成类 - `qgame.layout`)
UI 快速换算与自适应网格均分布局器：
* **文字 debug 默认行高**：`LINE_1` (Y=20), `LINE_2` (Y=50), `LINE_3` (Y=80)。
* **`top_left(offset_x, offset_y) -> tuple[int, int]`**
* **`top_right(canvas, offset_x, offset_y, width) -> tuple[int, int]`**
* **`bottom_left(canvas, offset_x, offset_y, height) -> tuple[int, int]`**
* **`bottom_right(canvas, offset_x, offset_y, width, height) -> tuple[int, int]`**
* **`center(canvas, width, height) -> tuple[int, int]`**
* **`grid(x, y, rows, cols, cell_width, cell_height, spacing_x=0, spacing_y=0) -> list[Rect]`**
  平面网格计算，返回一个扁平化的 Rect 数组，代表所有的排列位置。
* **`row(x, y, count, cell_width, cell_height, spacing=0) -> list[Rect]`**
  横向一维列兵排部。
* **`column(x, y, count, cell_width, cell_height, spacing=0) -> list[Rect]`**
  纵向一维竖向菜单条排部。
* **`fit_row(parent_rect: Rect, count, spacing=0) -> list[Rect]`**
  模仿 Flex 横向排版。在父 Rect 区域深度等比均分切片出 `count` 个横排单元。
* **`fit_column(parent_rect: Rect, count, spacing=0) -> list[Rect]`**
  在父 Rect 区域等比均分切片出 `count` 个纵排单元。

### `Font` (字体管理类)
* **`load(font_path: str) -> str`**
  提取加载本地的 `.ttf` 或 `.otf` 字体文件，成功后返回字体所属的 Font Family 名称。

### `CustomFont` (手绘字/物理位图字与矢量字装载器) (新)
专为无字库、极客手绘字、像素字（Bitmap Font）设计的字符映射分区。
*   **`__init__(default_width=None, default_height=None)`**
    初始化一个自定义字库分区。可传入 `default_width` 与 `default_height` 锁定每个字符显示的物理基准宽高。
*   **`register(char: str, file_path: str) -> bool`**
    手动将单个字符映射到一张图片（或 SVG 矢量图）路径：
    *   `char`: 必须是长度为 1 的单个字符（支持英文、符号、单个汉字等）。
    *   `file_path`: 支持 `.png`、`.jpg` 以及 `.svg`（矢量字符）。
*   **`load_dir(dir_path: str) -> int`**
    **(核心推荐：批量扫描装载)** 扫描指定文件夹下的所有图像资产。**文件主名称即为映射的单个字符**。
    *   *示例文件夹布局*:
        ```text
        assets/retro_font/
          ├── a.png      (自动映射为字符 'a')
          ├── b.png      (自动映射为字符 'b')
          ├── 1.png      (自动映射为字符 '1')
          └── 赞.svg     (自动支持 SVG，映射为汉字 '赞')
        ```
    *   直接运行 `font.load_dir("assets/retro_font/")` 即可一键装载整个文件夹！返回成功装载的字符数量。
*   **`get_char(char: str) -> Image | SVG | None`**
    内部资产重定位，获取对应字符的底层渲染对象。

#### 绘制静态方法中：
*   **`draw.custom_text(canvas, custom_font, text, coords, spacing=2, scale=1.0, opacity=1.0)`**
    利用指定的手绘/矢量分区字库，在画布上横向顺次渲染字符串。
    *   `custom_font`: 已经初始化并装载好字符的 `CustomFont` 实例。
    *   `text`: 要绘制的字符串，如 `"hello 赞"`（若字符串中有未注册的空白符 `" "`，系统会自适应腾出字符占位）。
    *   `coords`: 绘制起点坐标 `(x, y)`。
    *   `spacing`: 字符与字符之间的水平间距（像素像素）。
    *   `scale`: 整体缩放系数（浮点，如 `2.0` 代表字型整体无损放大一倍）。
    *   `opacity`: 整体绘制透明度，范围 `0.0` ~ `1.0`。

### `Image` (图像类)
代表一份缓存在内存中的图片资源。
* **`__init__(source: str | Image | QImage)`**
  接收文件路径、其他图片实例或原生 QImage。在克隆已有的图片时为 0 IO 机制。
* **`resize(width: int, height: int, keep_aspect: bool = False)`**
  重置本张图片分辨率。
* **`scale(factor_x: float, factor_y: float = None, keep_aspect: bool = True)`**
  缩放图片比例。
* **`rotate(angle: float)`**
  旋转图片（单位度，顺时针）。
* **`flip(horizontal: bool = True, vertical: bool = False)`**
  翻转（支持左右、上下镜像翻转）。
* **`reset()`**
  重置图像为没有缩放和旋转前的最初原始数据。
* **`width` / `height`**
  返回当前最新长宽数值的属性。

### `SVG` (极客级矢量资产类)
*   **`__init__(source_path: str)`**
    解析本地的标准 SVG 矢量数据文件，构建高保真渲染数据源。
*   **`resize(width: float, height: float)`**
    设置当前矢量边界的目标渲染范围（支持精细的浮点尺度坐标）。
*   **`scale(factor_x: float, factor_y: float = None)`**
    对极值尺寸进行系数等比或非等比缩放。
*   **属性**：`width` 和 `height`，返回缩放后矢量的绝对边界。

#### 绘制静态方法中：
*   **`draw.svg(canvas, svg_obj, coords, center=False, opacity=1.0)`**
    利用 Qt 矢量几何渲染器在画布上实时光栅化矢量图形。
    *   `svg_obj`: 实例化的 `qgame.SVG` 对象。
    *   `coords`: 绘制起点 (x, y)。
    *   `center`: 设置 `True` 后以该矢量图形的正中心点对齐绘制。
    *   `opacity`: 自适应透明通道融合，范围 `0.0` (完全透明) ~ `1.0` (不透明)。

### `Rect` (矩形容器)
* **`__init__(x, y, width, height)`**
  高精度浮点数矩形存储容器。**支持原生的迭代解包机制**，通过 `x, y, w, h = rect` 即可解包传入绘图方法。
* **`center` / `centerx` / `centery`**
  可快速读取和对齐的中心点属性。
* **`collidepoint(pos: tuple) -> bool`**
  判断坐标点是否在该矩形内。

### `draw` (渲染静态方法集合)
* **`fill(canvas, color)`**
  以指定颜色 `(r, g, b)` 填充重刷画布背景。
* **`rect(canvas, color, rect, width=0)`**
  绘制空心/实心矩形（`width=0` 时为实心填充）。
* **`rounded_rect(canvas, color, rect, radius, width=0)`**
  绘制高画质抗锯齿圆角矩形。
* **`circle(canvas, color, center, radius, width=0)`**
  绘制抗锯齿空心/实心圆形。
* **`ellipse(canvas, color, rect, width=0)`**
  绘制包围圈内的椭圆形。
* **`line(canvas, color, start, end, width=1)`**
  绘制抗锯齿直线。
* **`text(canvas, text, coords, size=16, color=(255,255,255), font_name="")`**
  高渲染帧率下的抗锯齿文本绘制。
* **`image(canvas, img, coords, center=False, src_rect=None, opacity=1.0)`**
  快速渲染图面，支持居中校对、局部区域裁剪（`src_rect`）以及透明度叠加。
* **`draw.motion_blur_image(canvas, img, x, y, vx, vy, samples=5, max_blur_length=100.0, center=False)`**
    **(核心推荐)** 利用一维多采样（Multisampling）插值，对超高速位移的图像进行实时运动拉丝模糊晕影。
    *   `img`: 输入的 `qgame.Image` 实例。
    *   `x`, `y`: 绘制目标位置。
    *   `vx`, `vy`: 当前帧的矢量相对运动速度（速度越大拉丝越长；若为 0 则是清晰的原图）。
    *   `samples`: 采样叠加渲染点数，推荐设在 `3` ~ `6` 之间，采样数越高画质越顺滑。
    *   `max_blur_length`: 限制最大拉丝物理像素长度（防止发生超高大运动导致粒子虚无飘渺）。
    *   `center`: 设置 `True` 后开启高度物理自适应的中心原点跟随机制。

---

## 碰撞检测系统 (`qgame.collision`)

### 函数方法
* **`check_rect(rect1: tuple, rect2: tuple) -> bool`**
  检测两个矩形是否相交。
* **`check_circle(pos1, r1, pos2, r2) -> bool`**
  检测两圆碰撞冲突。
* **`check_rect_circle(rect, center, radius) -> bool`**
  检测圆与矩形是否相碰。
* **`check_point_rect(point, rect) -> bool`**
  检测点是否在矩形内。
* **`check_point_circle(point, center, radius) -> bool`**
  检测点是否在圆形内。

---

## 物理引擎系统 (`qgame.physics`)

### `PhysicsWorld` (物理世界类)
管理刚体的受力情况及发生碰撞后的物理解算。
* **`__init__(gravity_x: float = 0.0, gravity_y: float = 600.0)`**
  配置重力加速度。默认为 Y 轴向下 `600.0` 像素/秒平方。
* **`add_body(body: RigidBody)`**
  向物理环境里注册一个刚体。
* **`remove_body(body: RigidBody)`**
  将指定刚体移出物理模拟。
* **`step(dt: float)`**
  物理时钟微步前进。自动处理多个子时间步叠影，防止物体卡死穿墙。

### `RigidBody` (刚体类)
受力学约束控制的物理对象。
* **`__init__(shape_type: str, x: float, y: float, width_or_radius: float, height: float = 0, is_static: bool = False, mass: float = 1.0, friction: float = 0.5, restitution: float = 0.0)`**
  `shape_type` 可选 `"circle"` 或 `"rect"`。静态地面或不动墙体参数设 `is_static=True`。`restitution` 代表绝对弹性指数（0为像面团无弹力，1为完美钢弹）。
* **`apply_impulse(impulse_x: float, impulse_y: float, offset: tuple[float, float] = (0, 0))`**
  施加瞬时冲量力矢量，用于产生初速度或跳跃运动。

---

## 音频控制系统 (`qgame.audio`)

### `Sound` (音效类)
用于快速播放时间短、反复调用的音效（支持扩展如 `.wav`）。
* **`play()`, `stop()`**
* **`set_volume(volume: float)`** (范围 0.0 - 1.0)
* **`set_loop(loop: bool)`**

### `Music` (背景音乐类)
用于低资源播发大型的背景音乐文件（支持机制如 `.mp3`）。
* **`play(loop: bool = True)`, `pause()`, `unpause()`, `stop()`**
* **`set_volume(volume: float)`** (范围 0.0 - 1.0)

### `SpatialSound`（2D 空间声学发生器类）
将音频加入 2D 物理空间解算，根据摄像机位置自动做立体声声道分配与近响大远响低的音量自动模拟。
* **`__init__(self, file_path, coords, max_distance = 600.0, loop = False)`**
* **`play()`**
* **`stop()`**
* **`set_position(coords)`**
* **`update_spatial_properties()`**：在主循环中伴随 camera 和声源移动实时调用。

---

## 动画 (`qgame.animation`)

# 📖 QGame 动画系统 API 手册 (`qgame.animation`)

---

## 1. 异常类 (Custom Exceptions)

用于精确捕获并定位在动画装载、控制、解包或别名寻访过程中的底层错误。

### `NotFoundFileError`
* **描述**：当尝试添加（`add_file_path`）一个在磁盘上物理不存在的动画配置文件、`.animdata` 压缩包或图片资源时跑出。

### `UnboundWindowError`
* **描述**：在未正确初始化游戏主视窗前，尝试进行某些特定视区绘制所跑出的错误。

### `ImageNotShowError`
* **描述**：试图在一个尚未开启状态（未执行 `image_show`）的图像/动画上强行驱动其动画进程（`animation_start`）时触发。

### `NotFoundAliasError`
* **描述**：检索一个从未在系统内注册过的别名（`alias`）时触发。

---

## 2. 全局动画控制函数

这一套函数主要针对经典**纯序列帧图像（如 `hero_1.png`, `hero_2.png`）**与**高级合成动画配置文件（`.json` / `.animdata`）**的资产级调度和帧前演进。

---

### `add_file_path`
```python
def add_file_path(file_path: str, alias: str, wait: int = 10) -> None:
```
* **方法说明**：注册一个多媒体动画或单张图片姿态资产。
* **参数**：
  * `file_path` (`str`)：文件路径。可以为：
    * `.json`：自研的2D骨骼或合成多图层动画配置文件。
    * `.animdata`：打包压缩的专用加密动画姿态包。
    * `.*`（如 `.png`, `.jpg`）：单帧常规像素图资产。
  * `alias` (`str`)：该资产在内存中的永久检索别名。
  * `wait` (`int`, 默认 `10`)：帧停留延迟数（以运行节拍 Tick 计）。数值越小，动画切帧频率越快。
* **抛出异常**：
  * `NotFoundFileError`：路径文件不存在。
  * `ValueError`：`wait` 参数为负数。

---

### `image_show`
```python
def image_show(alias: str, x: int, y: int, window: QImage) -> None:
```
* **方法说明**：在大世界或主画布 `window` 上的 `(x, y)` 物理坐标处激活并呈现指定的别名资产。
* **参数**：
  * `alias` (`str`)：要显示的资产别名。
  * `x`, `y` (`int`)：绘制中心点或左上角。
  * `window` (`QImage`)：接收渲染的目标游戏视口画布（Canvas）。
* **抛出异常**：
  * `NotFoundAliasError`：找不到该别名。

---

### `animation_start`
```python
def animation_start(
    alias: str, 
    total_frames: int = 1, 
    callback: Optional[Callable[[], None]] = None,  
    underline: bool = True, 
    file_type: str = "png"
) -> None:
```
* **方法说明**：驱动该别名对应的多帧动画向前迈进一帧。需在主游戏循环中持续调用。如果是 JSON/animdata 动画，会自动根据配置驱动所有子骨骼构件；如果是散图多帧，会自动检索下一数字帧图片。
* **参数**：
  * `alias` (`str`)：资产别名。
  * `total_frames` (`int`, 默认 `1`)：动画总帧数。如果是外部复杂合成动画，该字段会自动被配置读取覆盖。
  * `callback` (`Callable`, 可选)：当动画播放完一整轮（回到首帧/尾帧）时触发的回调事件。
  * `underline` (`bool`, 默认 `True`)：读取序列图时，数字前是否有下划线（例如 `hero_1.png` 对应 `True`；`hero1.png` 对应 `False`）。
  * `file_type` (`str`, 默认 `"png"`)：散图格式后缀。
* **抛出异常**：
  * `ImageNotShowError`：该资产从未渲染出来（未调用 `image_show`）。
  * `NotFoundFileError`：无法在对应的文件夹下定位到下一序列图物理文件。

---

### `animation_stop`
```python
def animation_stop(alias: str) -> None:
```
* **方法说明**：停止当前正在播放的别名动画，并重置其切帧等待计数器。
* **参数**：
  * `alias` (`str`)：要停止的资产别名。

---

### `is_image_showing`
```python
def is_image_showing(alias: str) -> bool:
```
* **方法说明**：查询某一别名下的图像/动画当前是否正处于画布渲染呈现状态下。
* **返回值**：`bool`。
* **抛出异常**：`NotFoundAliasError`。

---

### `is_animation_started`
```python
def is_animation_started(alias: str) -> bool:
```
* **方法说明**：查询特定动画当前是否正处于持续演进播放状态（`animation_start`）。
* **返回值**：`bool`。
* **抛出异常**：`NotFoundAliasError`。

---

### `get_animation_frame`
```python
def get_animation_frame(alias: str) -> int:
```
* **方法说明**：获取当前别名动画运行到的真实帧索引。
* **返回值**：`int`（从 `0` 开始的帧索号）。
* **抛出异常**：`NotFoundAliasError`。

---

### `set_animation_frame`
```python
def set_animation_frame(alias: str, frame: int = 1) -> None:
```
* **方法说明**：强行将特定动画倒带或跳转到目标帧。
* **参数**：
  * `alias` (`str`)：资产别名。
  * `frame` (`int`, 默认 `1`)：目标帧数序号。

---

### `set_animation_speed`
```python
def set_animation_speed(alias: str, speed: int = 2) -> None:
```
* **方法说明**：成倍缩短等待帧阻，提升或降低播放速度。
* **参数**：
  * `alias` (`str`)：缩放速度的目标别名。
  * `speed` (`int`, 默认 `2`)：速度倍率数值（必须为大于0的整数）。

---

### `animation_reverse`
```python
def animation_reverse(alias: str) -> None:
```
* **方法说明**：将目标动画置为**反向倒序播放模式**。
* **参数**：
  * `alias` (`str`)：目标别名。

---

### `animation_reverse_back`
```python
def animation_reverse_back(alias: str) -> None:
```
* **方法说明**：恢复目标动画为正常**顺序前进播放模式**。
* **参数**：
  * `alias` (`str`)：目标别名。

---

## 3. 状态监控类：`AnimationStatus`

---

### `AnimationStatus`
```python
class AnimationStatus:
```
* **类说明**：一个只读的监视胶囊类。传入特定资产别名，可以瞬间捕获当前时刻它的所有物理播放状态快照。

### **构造方法**
```python
def __init__(self, alias: str):
```
* 初始化并立即截取别名动画的状态。包含成员属性：
  * `alias` (`str`): 检索标识。
  * `is_showing` (`bool`): 是否正在被展现。
  * `is_started` (`bool`): 是否激活了切帧步伐。
  * `frame` (`int`): 当前运行物理帧索引。
  * `speed` (`int`): 播放速度。
  * `is_reverse` (`bool`): 是否属于反向循回状态。
  * `file_path` (`str`): 原始物理注册路径。
  * `file_name` (`str`): 剥离数字后缀后的纯粹前缀名。
  * `total_frames` (`int`): 评估得出的动画帧上限。
  * `current_frame` (`int`): 规范帧偏移量。
  * `image_type` (`str`): 类型，为 `"Image"`（单帧） 或 `"Animation"`（合成复合动画）。

### **公共方法**

#### 1. `get_settings`
```python
def get_settings(self) -> str:
```
* **方法说明**：将该资产的所有状态、配置与元数据编译并打包成一个极其规整、适合网络发送或进程存储的 JSON 文本字符串。
* **返回值**：`str`（JSON 字符串）。

#### 2. `get_status`
```python
def get_status(
    self, 
    status: Literal["animation_started", "image_showing", "animation_start", "animation_end", "animation_reverse"]
) -> bool:
```
* **方法说明**：按键提取某个具体的逻辑态布尔值。
* **参数**：
  * `status` (`Literal`)：接收查询的状态属性。
    * `"animation_started"`：动画当前是否在跑帧。
    * `"image_showing"`：图像是否出现在视口。
    * `"animation_start"`：动画指针当前是否恰好位于第一帧。
    * `"animation_end"`：动画是否正好跑到了最后一帧（用于触发终结业务逻辑）。
    * `"animation_reverse"`：是否处于反转行驶状态。
* **返回值**：`bool`。

---

## 4. 帧动画机类：`AnimatedSprite`

---

### `AnimatedSprite`
```python
class AnimatedSprite:
```
* **类说明**：现代面向对象游戏开发的主力。它在内存中组织一个角色实体的全套姿态集合（如：`idle`, `run`, `attack`, `jump`），通过极简的 `play("run")` 在状态之间跳转，并高度支持自适应主循环时间步（DT）及关键帧事件事件回调（如跑到第三帧引发打击）。

### **构造方法**
```python
def __init__(self, x: float = 0.0, y: float = 0.0):
```
* **参数**：
  * `x`, `y` (`float`, 默认 `0.0`)：动画精灵在世界空间中的初始物理原点坐标。

### **公共方法**

#### 1. `add_state`
```python
def add_state(self, state_name: str, images: list, fps: float = 10.0, loop: bool = True) -> None:
```
* **方法说明**：向该精灵动作库中添加或覆盖注册一个状态套件。
* **参数**：
  * `state_name` (`str`)：该动作特征的名字（比如 `"idle"`, `"shoot"`）。
  * `images` (`list[Image]`)：该序列内包含的一组 QGame `Image` 指针序列。
  * `fps` (`float`, 默认 `10.0`)：该动作期望播放的每秒播放帧率。
  * `loop` (`bool`, 默认 `True`)：动画到终点时，是否重新循环，或者冻结在最后一帧。

#### 2. `play`
```python
def play(self, state_name: str) -> None:
```
* **方法说明**：立即进行动画状态跃迁。如果传入的状态不存在或者本身就在播放该状态，自动拦截，从而保护动作不会因高频调用而触发非自愿重启。
* **参数**：
  * `state_name` (`str`)：要跃升跳转的动作名称。

#### 3. `bind_frame_event`
```python
def bind_frame_event(self, state_name: str, frame_index: int, callback: Callable[[], None]) -> None:
```
* **方法说明**：**帧事件触发机制**。在特定动作播到指定的帧时，爆发性触发一个特定的引擎处理函数。例如在动作 `"attack"` 播到第 `3` 帧（亮刀）时触发伤害碰撞计算，或者 `"run"` 回合第 `4` 帧时触发脚踏声效。
* **参数**：
  * `state_name` (`str`)：指定的目标动作名字。
  * `frame_index` (`int`)：目标的切帧序号（从0开始）。
  * `callback` (`Callable`)：满足判定时触发执行的无参回调。

#### 4. `update`
```python
def update(self, dt: float) -> None:
```
* **方法说明**：必须在游戏每次时钟脉冲 tick 中呼叫。传入 `delta_time` 调节时间步，保证动作卡点在网络延迟或设备帧率波动下始终顺滑均匀。
* **参数**：
  * `dt` (`float`)：时针间隔（Delta Time）。

#### 5. `get_current_image`
```python
def get_current_image(self) -> Optional[Image]:
```
* **方法说明**：获取此时此刻动作机姿态对应的真实图片物理句柄，以送入 `qgame.draw.image` 进行精细绘制。
* **返回值**：`Image` 实例，或者在没有状态时返回 `None`。

---

## 弹窗 & 文件对话框系统 (`qgame.messagebox`)
`MessageBox` 是 `qgame` 引擎中的**高级弹窗交互系统**。为了保持游戏画面的沉浸感与整体视觉的统一，它基于 PySide6 自定义了一套无边框、支持鼠标拖动、可自由换肤的现代弹窗，并提供文件选择器接口，避免了开发者在主程序中直接导入 PySide6 的复杂性。

下面是关于 `MessageBox` 的详细技术介绍，包括组件结构、函数名及参数详解。

---

### 一、 辅助类：`DraggableMessageBox`
继承自原生 `QMessageBox`。当弹窗被设置为无系统边框（`frameless=True`）时，系统默认的拖动条会消失。该类通过重写鼠标事件，实现了**按住弹窗任意背景区域均可自由拖动**的功能。
*   **`__init__(self, parent=None, draggable=True)`**
    *   `parent`: 父级窗口。
    *   `draggable`: 是否启用鼠标拖动。

---

### 二、 核心类：`MessageBox` 接口及参数详解

#### 1. 核心显示主方法：`show()`
这是最通用的弹窗方法，支持完全的自定义按钮、图标、主题和坐标。

*   **`show(title="系统提示", message="", buttons=["确定"], icon="info", canvas=None, draggable=True, frameless=True, coords=None, theme="nord") -> str`**
    *   **参数介绍**:
        *   `title (str)`: 弹窗标题（在任务栏或非无边框模式下显示）。
        *   `message (str)`: 弹窗正文文本。
        *   `buttons (list[str])`: 按钮选项数组，如 `["同意并继续", "拒绝并退出"]`。
        *   `icon (str)`: 预设图标，可选值为 `"info"`、`"success"`、`"warning"`、`"error"`、`"question"`。
        *   `canvas`: 绑定的画布对象，若传入此参数，弹窗将自动在游戏视口中央进行**绝对居中**，并进行模态阻断（玩家在关闭弹窗前无法操作主游戏窗口）。
        *   `draggable (bool)`: 是否允许按住背景拖动，默认为 `True`。
        *   `frameless (bool)`: 是否隐藏系统原生标题栏。默认为 `True`，隐藏后弹窗看起来更加现代化。
        *   `coords (tuple[int, int])`: 弹窗的初始像素坐标 `(x, y)`。
        *   `theme (str | dict)`: 主题。可接收预设主题名（如 `"nord"`、`"dark"`、`"light"`），亦可直接传入一个自定义 CSS 样式的 `dict`。
    *   **返回值**: 返回用户点击的按钮文本（`str`），如点击了“同意并继续”按钮，则返回 `"同意并继续"`。

---

#### 2. 便捷弹窗封装 (Wrappers)
系统内建了 6 个针对不同业务场景的简化包装函数。这些包装函数在底层最终都会调用 `show()`：

*   **`info(message, title="提示", canvas=None, lang="cn", **kwargs) -> str`**
    *   信息提示弹窗。默认按钮在 `lang="cn"` 时为 `["确定"]`，在 `lang="en"` 时为 `["Yes"]`。

*   **`success(message, title="成功", canvas=None, lang="cn", **kwargs) -> str`**
    *   操作成功提示弹窗。默认按钮派发 `["好的！"]` 或 `["OK!"]`。

*   **`warning(message, title="警告", canvas=None, lang="cn", **kwargs) -> str`**
    *   警告弹窗。默认按钮为 `["我知道了"]` 或 `["I know"]`。

*   **`error(message, title="错误", canvas=None, lang="cn", **kwargs) -> str`**
    *   错误报告弹窗。默认按钮为 `["确定"]` 或 `["Yes"]`。

*   **`question(message, title="问题", canvas=None, lang="cn", **kwargs) -> str`**
    *   询问弹窗。默认带有双选项按钮 `["确定", "取消"]` 或 `["Yes", "Cancel"]`。

*   **`confirm(message, title="请确认操作", canvas=None, lang="cn", **kwargs)`**
    *   确认操作弹窗。同样默认带双选按钮。

---

#### 3. 文件资源选择器：`select_file()`
一个实用的工具函数，可以在不污染主程序依赖的前提下，拉起系统的文件浏览器。

*   **`select_file(title="选择本地文件", file_filter="所有文件 (*.*)", canvas=None) -> str`**
    *   `title (str)`: 资源管理器窗口标题。
    *   `file_filter (str)`: 格式过滤器，例如 `"图片文件 (*.png *.jpg);;所有文件 (*.*)"`。
    *   `canvas`: 绑定的父视口。
    *   **返回值**: 用户选中的文件绝对路径（`str`），若取消选择则返回空字符串 `""`。

---

#### 4. 高级主题映射定义：`add_theme()`
支持动态注册自定义 UI 主题，可由 RGB 元组或十六进制颜色码定义。

*   **`add_theme(name, bg, border, text, btn_bg, btn_hover, btn_text)`**
    *   `name`: 自定义主题的名称标识。
    *   `bg` / `border` / `text` / `btn_bg` / `btn_hover` / `btn_text`: 可接收 RGB 元组 `(R, G, B)` 或十六进制字符串 `"#HEX"`。注册后可在后续的 `show(theme="ThemeName")` 中直接运用。

如默认提供的 `"nord"` 主题配置为：
```python
"nord": {
    "bg": "#2e3440", "border": "#4c566a", "text": "#eceff4",
    "btn_bg": "#434c5e", "btn_hover": "#88c0d0", "btn_text": "#eceff4"
}
```

---

### 💡 简短概括

`MessageBox` 是一套**高定制化的现代游戏弹窗系统**。它通过封装 `QMessageBox` 并重写鼠标事件，实现了**无边框拖拽**和**一键更换暗黑/極光主题**。开发者能以极简的代码（例如 `MessageBox.success("加载成功！", canvas=self)`）在主循环派发阻塞/非阻塞通知，且无需面对 PySide6 底层复杂的排版代码。

---

## UI 输入与容器控件 (`qgame.ui`)

QGame UI 控件全面打通了**自适应等比高清缩放机制**。所有 UI 控件的比例、字号、圆角、甚至点九贴图拉伸边缘与环形进度条的物理粗细，都会随视口分辨率自适应变焦，在高 DPI 屏或 F11 全屏切换下依然能保持完美的像素清晰度。

*   **属性按需极简配置**：所有控制组件的 `set_theme()` 均支持**可选的关键字实参**传入（例如快速更改颜色只需要写 `set_theme(text_color=(0, 255, 0))`），未指定的样式将安全继承自默认高级暗黑科技底色，无需再传递冗余的 `None`。
*   **图像与万能 SVG 支持**：各个控件不仅支持普通的 `.png`、`.jpg` 背景和前景图，还全面接入了高品质 `.svg` 矢量渲染，直接通过 `QSvgRenderer` 在视口刷新时根据物理像素实时光栅化，保证在 4K 甚至 8K 大屏下锐利无锯齿。

---

### `Button` (按钮控件)

在游戏画布上呈现一个可进行悬浮变色、点击按压，并支持本地贴纸和全局快捷按键触发的原生高交互按钮。

*   **`__init__(coords: tuple[float, float], width: int, height: int, text: str = "")`**
    *   `coords`：虚拟坐标，支持传递元组 `(x, y)` 或是动态 lambda 坐标生成。
*   **`set_theme(normal_bg=None, hover_bg=None, pressed_bg=None, border_color=None, text_color=None, border_radius=None, font_size=None, font_family=None, font_weight=None)`**
    *   配置按钮三态（常态、悬浮、按压）的背景色彩、框线、字体大小、字粗与圆角。
*   **`set_image(image_path: str)`**
    *   为按钮设置前景高保真 Icon。图标会自动清理按钮原有的文本，且尺寸会与按钮大小等比自适应。
*   **`set_image_bg(image_path: str, top=12, right=12, bottom=12, left=12)`**
    *   利用九宫格拉伸算法为按钮填充底纹贴图，确保拉伸时边框和圆角永不发生拉伸畸变。
*   **`connect(callback: Callable[[], None])`**
    *   连接按钮点击（Mouse Click）释放后的行为触发回调函数。
*   **`set_shortcut(shortcut_str: str)`**
    *   为按钮绑定键盘物理热键（如 `"Return"`、`"Space"`、`"Ctrl+S"`），触发时等同于点击该按钮。
*   **`set_enabled(enabled: bool)`**
    *   传入 `False` 可以立刻禁用按钮，使灰色禁用态生效，阻断用户的点击操作。
*   **`set_text(text: str)` / `get_text()`**
    *   修改或读取按钮中的文本。
*   **`set_visible(visible: bool)`**
    *   显示或隐去按钮。
*   **`destroy()`**
    *   安全卸载并彻底物理销毁该按钮。

---

### `Panel` (可拖拽浮动窗口容器)

高级面板容器，常用来制成大型装备面板、游戏设置浮窗、网络聊天大厅，并且支持往里递归塞入按钮、单选、文本框并实现级联大小同步计算。

*   **`__init__(coords: tuple[float, float], width: int, height: int, title: str = "Window", hide_close: bool = False)`**
    *   `title`：顶端标题栏文本。
    *   `hide_close`：**【核心更新】**如果置为 `True`，顶端右上角的 ✕ 关闭按钮将被彻底干掉，隐藏物理退出按钮。此时开发者可以让用户输入协议、通过内部按钮自主控制关闭流程。
*   **`set_theme(header_bg=None, content_bg=None, border_color=None, border_radius=None, font_size=None, text_color=None, font_family=None, font_weight=None)`**
    *   配置标题栏背景、内容区底色、框色、边框圆角及标题文本大小与字粗。
*   **`set_image_bg(image_path: str, top=24, right=24, bottom=24, left=24)`**
    *   设置九宫格拉伸底图（如欧式羊皮纸底、暗色金属骨架贴图）。
*   **`add_widget(obj)`**
    *   塞入 UI 控件。塞入的对象会从游戏主窗口中脱离、受控并挂载至 Panel 局部布局体系下，追随 Panel 的拖拽平移和触角拉伸进行级联自适应。
*   **`connect_close(callback: Callable[[], None])`**
    *   **【核心更近】**关闭信号槽。无论是用户点击右上角 ✕，还是在脚本里执行了 `.close()`，该回调会被立刻激发抛出，让开发者捕获该时机（如自动游戏暂停或保存本地云存档）。
*   **`close()`**
    *   执行关闭离开，并同步抛出关闭信号给注册的回调。
*   **`set_visible(visible: bool)`**
    *   设置面板以及它所有自子构件整体显隐。

---

### `Label` (标签与高清前景绘图控件)

纯文本或高清贴图呈现层。当无文字且载入图片时，可作为一个性能极佳的自适应平面立绘或 UI 背景层来运用。

*   **`__init__(coords: tuple[float, float], width: int, height: int, text: str = "")`**
*   **`set_text(text: str)` / `get_text()`**
*   **`set_theme(text_color=None, bg_color=None, font_size=None, font_family=None, font_weight=None)`**
*   **`set_image(image_path: str)`**
    *   设置展现的前景图像，在拉伸和多分辨率变焦时，内部会自适应调用无损光栅化像素，防止贴纸模糊。
*   **`set_image_bg(image_path: str, top: int = 0, right: int = 0, bottom: int = 0, left: int = 0)`**
    *   设置九宫格底纹贴纸。
*   **`set_position(x, y)` / `set_size(width, height)` / `destroy()`**

---

### `ProgressBar` (抗锯齿进度条与血条控件)

带有抗锯齿圆角描边的多姿态数值可视化工具，自带**高仿真阻塞装载器**。无论是普通横向、纵向亦或是复杂酷炫的画作大作圆环（Circular ProgressBar）均可胜任。

*   **`__init__(coords: tuple[float, float], width: int, height: int, direction: str = "horizontal")`**
    *   `direction`：可选 `"horizontal"`（水平）、`"vertical"`（垂直）或 `"circular"`（环形）。
*   **`set_value(val: float)`**
*   **`set_range(min_val: float, max_val: float)`**
*   **`set_show_text(show: bool)`**
    *   是否在圆心或中心优雅绘制百分比值。
*   **`set_circular_thickness(thickness: int)`**
    *   当方向为 `"circular"`（圆形）时自如改变旋转能量环的肥胖边框像素度。
*   **`set_theme(bg_color=None, fill_color=None, border_color=None, text_color=None, border_radius=None, border_width=None, font_size=None, font_family=None, font_weight=None)`**
*   **`load_tasks(tasks: list[Callable], on_progress: Callable = None, on_complete: Callable = None)`**
    *   **【线程级防假死任务装载器】**：顺序多步骤执行耗时的无参装载函数（例如加载纹理、连接网线、解析音轨）。加载时，会定时激发底层事件泵冲洗视口，哪怕玩家在期间疯狂拖拽或挂起，也**绝不产生“窗口未响应”或灰白假死**！

---

### `Slider` (高感交互式调节滑块)

*   **`__init__(coords, width, height, direction = "horizontal")`**
    *   `direction` 可为 `"horizontal"` 或 `"vertical"`。
*   **`set_value(val: int)` / `get_value() -> int`**
*   **`set_range(min_val: int, max_val: int)`**
*   **`connect(callback: Callable[[int], None])`**
    *   挂载数值监听，当用户用鼠标拉动滑条时，会把最新进度（数字）实时传入回调。
*   **`set_theme(track_bg_color=None, track_fill_color=None, handle_color=None, handle_hover_color=None, track_height=None, handle_width=None, handle_height=None)`**
    *   可以极细致地改变中央吸子滑块、已填充段和未填充轨道的颜色圆角半径。

---

### `TextBox` (原生文本录入框)

玩家可以点击并调出 IME 输入法直接在里面键入汉字、英文和复杂游戏控制台密匙的组件。

*   **`__init__(coords, width, height, placeholder="", multi_line=True)`**
    *   `multi_line`：传入 `False` 会自动改变构造为单行（QLineEdit），多行则使用 QTextEdit 并附赠平滑滚动。
*   **`set_theme(bg_color=None, text_color=None, border_color=None, border_radius=None, font_size=None, font_family=None, font_weight=None)`**
*   **`set_image_bg(image_path: str, top=6, right=6, bottom=6, left=6)`**
    *   背景九宫格贴纸填充入，可以做出极佳的魔幻复古输入底。
*   **`get_text() -> str` / `set_text(text: str)` / `clear()`**
*   **`set_focus()`**
    *   无需点击，全自动高亮聚焦并劫持光标聚焦，方便快速进入打字态。


### `SecureInput`
`SecureInput` 是 `qgame` 引擎中专门为处理敏感数据（如密码、秘钥）设计的**高安全性物理隔离输入框**。它与普通的 `TextBox` 不同，目标是让明文数据在内存中的存在时间趋近于零。

以下是 `SecureInput` 的详细技术手册：

### 1. 类定义与初始化
**类名：** `qgame.ui.SecureInput`

*   **`__init__(self, coords, width, height, placeholder)`**
    *   `coords`: `tuple[float, float]`。控件在虚拟画布上的 (x, y) 坐标。
    *   `width`: `int`。控件宽度。
    *   `height`: `int`。控件高度。
    *   `placeholder`: `str`。未输入时的占位提示文字。默认值为 `"WAITING FOR ENCRYPTED FREQUENCY..."`。

### 2. 核心功能函数

#### 🚀 `access_data(self, consumer_func)` 【最关键接口】
由于安全设计，该控件**不提供** `get_text()` 方法。如果你需要读取内容（例如进行哈希比对或发送给服务器），必须通过这个门禁函数。

*   **参数 `consumer_func`**: 一个回调函数（通常是 `lambda` 或 `def`），格式为 `func(plaintext: str)`。
*   **动作流程**:
    1.  从受保护的内存缓冲区（XOR 乱码）解密出瞬时明文。
    2.  立即将明文传递给你的 `consumer_func`。
    3.  **物理抹除**：一旦你的函数执行完毕，控件会立即用 `0` 覆盖那块内存并触发垃圾回收。
*   **使用方式**:
    ```python
    # 验证密码
    success = txt_pass.access_data(lambda p: qgame.hash.verify_password(p, stored_hash))
    ```

#### 🧹 `clear(self)`
*   **动作**: 立即清除输入框内容，并手动将内存缓冲区中的所有字节重置为 `0`。在切换关卡或重置登录框时建议手动调用。

#### 🎯 `set_focus(self)`
*   **动作**: 让输入框获得键盘焦点（鼠标光标直接定位进去）。

#### 💥 `destroy(self)`
*   **动作**: 彻底销毁控件并从 UI 管理队列中移除，同时执行内存抹除。

---

### 3. 三大底层安全屏障

1.  **内存层 (Memory Layer - XOR Obfuscation)**
    *   控件内部使用 `bytearray` 而非 `string` 存储。
    *   **随机盐值加密**：初始化时生成一个随机的 64 位 `_xor_key`。
    *   **即时混淆**：用户每敲一个键，数据会立即与密钥进行异或运算存入内存。内存里永远是一堆毫无意义的二进制乱码，黑客通过 Cheat Engine 搜不到明文。

2.  **物理层 (Physical Layer - Interaction Block)**
    *   **禁用右键菜单**：防止“显示明文”或右键拷贝。
    *   **禁用剪贴板**：阻断系统级的 复制 (Ctrl+C)、粘贴 (Ctrl+V) 和 剪切 (Ctrl+X)，防止密码泄露到不安全的剪贴板。
    *   **禁用拖拽**：防止将密码内容通过鼠标拖拽到其他程序窗口。

3.  **周期层 (Lifecycle Layer - Self-Destruction)**
    *   明文仅在 `access_data` 执行的那几微秒内存在。
    *   **手动覆盖**：利用 Python 可变字节数组特性，处理完后直接把内存块填满零。

---

### 💡 极简概括

**`SecureInput` = 内存乱码存储 + 物理动作封锁 + 处理后立即自毁。**

它通过改变数据的形态和控制明文的寿命，解决了“黑客扫描内存直接看密码原文”的问题。

---

### 🚀 `ListWidget` (多功能可拖拽列表) —— **NEW!**

专为游戏物品格、配置文件夹及关卡自建编辑器推出的多功能重载容器。

*   **`__init__(coords: tuple[float, float], width: int, height: int)`**
*   **`add_item(text: str, icon_path: str = None) -> int`**
    *   向列表尾部推入一行文本，可额外附带一个精美的左置 Icon（完美兼容 `.svg` / `.png` ）。
*   **`clear()`** / **`remove_item(index: int)`**
    *   清空列表或将指定行的物理行在视线中消除。
*   **`get_selected_index() -> int`**
    *   获取当前高亮行索引（未选择时返回 `-1` ）。
*   **`get_selected_text() -> str`**
*   **`set_draggable(enabled: bool)`**
    *   **【鼠标拖拽排序】** 传入 `True` 即可让玩家直接用鼠标**按住条目上下甩动、无缝拖拽重排序**，并自带平滑插入指引和微弹跳，重置排序后的索引完全自动修正。
*   **`set_context_menu(menu_items: list[str], callback: Callable[[int, str, str], None])`**
    *   **【右键快捷气泡】** 允许为此列表的一键注入扁平半透明悬浮选项组。例如 `["🪓 保蓄", "🧪 回收", "🗑️ 抛弃"]`，一旦点击其中任何一项，便会激发 `callback(选中行索引, 原本文字, 被点击的操作文本)`，让装备背包互动开发难度瞬间降为零。
*   **`connect_clicked(callback: Callable[[int, str], None])`**
    *   点击左键绑定侦听器。
*   **`connect_double_clicked(callback)`**
    *   连接道具双击（Double Click）快速使用和装备监听器。
*   **`set_theme(bg_color=None, text_color=None, border_color=None, border_radius=None, item_hover_bg=None, item_selected_bg=None, font_size=None, font_family=None, font_weight=None)`**
    *   额外支持列表项的常态背景、悬停和激活选中态（item_hover_bg / item_selected_bg）的主题定阻配置。

---

### 🚀 `ComboBox` (高质扁平下拉选择框) —— **NEW!**

多选游戏设置项（如分辨率选择、抗锯齿方案调节、物理重力频率倍率）的黄金搭档。

*   **`__init__(coords: tuple[float, float], width: int, height: int)`**
*   **`add_items(items: list[str])`**
    *   批量推入一系列下拉文本。
*   **`clear()`**
*   **`get_selected_index() -> int` / `get_selected_text() -> str`**
*   **`set_selected_index(index: int)`**
*   **`connect_changed(callback: Callable[[int, str], None])`**
    *   当下拉栏发生改动时，瞬间将 `(改变后新索引, 最新选中字符文本)` 抛送到该响应函数。
*   **`set_theme(bg_color=None, text_color=None, border_color=None, border_radius=None, font_size=None, font_family=None, font_weight=None)`**
    *   可以极度华美地美化悬浮出的二级选择下拉气泡、滑过和选中特效。

---

### 🚀 `CheckBox` (未来感发光单/复选块) —— **NEW!**

常态化的布尔判定（如音效开关、绘制骨骼碰撞盒包络开关等）最直观的操纵者。

*   **`__init__(coords: tuple[float, float], width: int, height: int, text: str = "")`**
*   **`set_checked(checked: bool)`**
*   **`is_checked() -> bool`**
    *   快速窥视该按钮此时是处于打勾勾还是空白模式。
*   **`connect(callback: Callable[[bool], None])`**
    *   挂载极敏感的回调，当它状态波动（开启或关闭），回传一个纯 Bool 值状态。
*   **`set_text(text: str)`**
*   **`set_theme(bg_color=None, text_color=None, active_color=None, font_size=None, font_family=None, font_weight=None)`**
    *   `active_color`：配置打勾勾之后的标志荧光色主题和点击高亮色。

---

## 💻 `CodeText` 代码/富文本编辑器

`CodeText` 是一款极高级的多行富文本与代码高亮编辑器。它完美打通了基于 QRegularExpression 的自定义着色管线，并提供高频触发的补全气泡、波浪线警告下划线、光标辅助定位 Tooltip、以及手势级视口字体调配。

```
     ┌────────────────────────────────────────────────────────┐
     │  # 1. 自动高亮 (Regular Expressions Highlighter)        │
     │  def init_system():                                    │
     │      qgame.init()                                      │
     │                                                        │
     │  # 2. 故障波浪线标记 ( add_marker )                     │
     │      eror_code = 404                                   │
     │      ~~~~~~~~~  <--- [Error Wave Marker]               │
     │                                                        │
     │  # 3. 光标定位 Tooltip ( show_tooltip )                 │
     │      ┌───────────────────────┐                         │
     │      │ 💡 [qgame.init Tooltip]│                         │
     │      │ 初始化视口核心           │                         │
     │      └───────────────────────┘                         │
     └────────────────────────────────────────────────────────┘
```

### 1. 核心属性与方法

*   **`CodeText(coords: tuple, width: int, height: int, placeholder: str = "")`**
    *   在画布上构建高精度编辑器视口框线。
*   **`add_highlight_rule(pattern: str, color: tuple, bold: bool = False, italic: bool = False)`**
    *   绑定符合规则正则表达式的自定义语法着色。
    *   `pattern`：高亮正则，例如匹配所有 Python 的关键字可写为 `r'\b(def|class|import|from|return)\b'`。
    *   `color`：高新颜色的 RGB三元组 `(R, G, B)`。
*   **`add_marker(start_pos: int, length: int, line_type: str, color: tuple)`**
    *   在指定的某段长字段下标记故障直观的警告波浪线。
    *   `line_type`：可选择 `"wave"`（红/黄警告波浪下划线）、`"straight"`（实直下划线）、`"dash"`（虚线线段）以及 `"dot"`（精巧密集点线）。
*   **`clear_markers()`**
    *   清空文本区内所有的波浪或警告标记。
*   **`set_suggestions(words: list[str])`**
    *   提供代码智能联想替换词库。只需输入首部分字符并按住 **`[Ctrl + Space]`**，便会立刻生成悬浮辅助词条单。
    *   **防单词重叠覆盖**：补全器高频解析原有字符，会在点击或确认时执行安全重写掩盖（即替换 `"qga"` -> `"qgame"`，绝无 `"qgaqgame"` 的叠加 Bug ）。
    *   **智能避让隐退**：键入空格、回车、或是联想词库本身已和当前输入字符精准匹配时，联想词提示框绝不遮挡视线，自动低调隐去。
*   **`set_tab_spaces(count: int)`**
    *   设置 Tab 缩进转换的空格数，默认为完美的 `4` 空格。
*   **`show_tooltip(text: str, x: int = -1, y: int = -1)`**
    *   挂载完全由开发者脚本操控的高度自适应 Tooltip 弹窗。
    *   **光标自然追随**：不传具体 `x` 和 `y` (默认为 `-1` ) 时，弹窗将高灵敏**计算当前文字光标处所在的物理绝对坐标，并在正下方弹出提示**，并自带防冲出控件四边界限边界算法。
    *   **超长气泡折叠滚动**：当里面内容很多时，提示框会高度自适应。一旦高度冲破 `130px`，右侧会自动出现特制的气泡窄滚动条，极利于查阅。
*   **`hide_tooltip()`**
    *   隐藏悬下Tooltip。

---

### 2. ⚡ 手势级字体放大 (Ctrl + Mouse Wheel)

为了避免固定分辨率对视弱者的不尊重，`CodeText` 内置了高级 IDE 级的手势缩放。只要**按住键盘 `[Ctrl]` 键的同时滚动鼠标中键滚轮**，代码编辑器的文本像素字号便会在 `6px`（超高同视率）~ `72px`（巨无霸看板）之间极其顺滑流畅地进行放大或缩小重绘。

---

### 3. API 开发高配示范

```python
import qgame

qgame.init()
canvas = qgame.set_settings(width=800, height=600, title="高阶代码编辑器演示")

# 1. 创建高性能 CodeText 沙屏并做细节缩进设置
editor = qgame.CodeText((100, 100), 600, 380, placeholder="在此处开始打字...")
editor.set_theme(bg_color=(20, 24, 30), text_color=(230, 240, 255), font_size=14, font_weight="normal")
editor.set_tab_spaces(2)  # 更适合前端写手，Tab 转换为 2 个空格

# 2. 从多角度多项式，灌入丰富的语法着色正则表达式
editor.add_highlight_rule(r'\b(def|class|import|from|return|if|elif|else)\b', (94, 129, 172), bold=True)
editor.add_highlight_rule(r'("[^"\\]*(?:\\.[^"\\]*)*"|\'[^\'\\]*(?:\\.[^\'\\]*)*\')', (163, 190, 140)) # 字符串高亮
editor.add_highlight_rule(r'#.*', (101, 115, 126), italic=True) # 灰色小斜体注释

# 3. 设定词库骨架
editor.set_suggestions(["qgame", "set_settings", "set_theme", "CodeText", "draw", "update", "quit"])

# 4. 模拟在第 15 个字符处画一段 8 个字符长度的红色严重警告波浪卷褶线！
editor.add_marker(15, 8, "wave", (235, 94, 94))

# 5. 完全自主控制，为可能发生报错行的右下方投映精美自适应 Tooltip 控制器气泡
guide_docs = (
    "⚠ ERROR DETECTED\n"
    "---------------------------------\n"
    "拼写错误！当前视窗找不到 'draw_txt'。\n"
    "您想要执行的 API 是不是以下选项之一：\n"
    "1. qgame.Draw.text\n"
    "2. qgame.draw.rect"
)
editor.show_tooltip(guide_docs, x=150, y=280)

# 6. 开启游戏心跳
clock = qgame.Clock()
running = True
while running:
    clock.tick(60)
    for event in qgame.events.get():
        if event.type == qgame.eventType.QUIT:
            running = False
            
    qgame.draw.fill(canvas, (24, 26, 32))
    qgame.window.update()
    
qgame.quit()
```

## 游戏场景结构 (`qgame.scene`)

### `Scene` (场景基类)
实现各种游戏阶段（如 `MenuScene` 菜单场景、`PlayScene` 核心玩法场景）。
* **`on_enter(*args, **kwargs)`**
  进入场景时调用。
* **`on_exit()`**
  退出场景时调用。由 `add_ui()` 挂载的所有组件，在此阶段都会顺便全自动销毁。
* **`handle_event(event)`, `update(dt)`, `draw(canvas)`**
* **`add_ui(widget)`**
  绑定一个 UI 控件到当前的场景生命周期中。

### `scene_manager` (管理器)
* **`switch(new_scene_instance, *args, **kwargs)`**
* **`handle_event(event)`, `update(dt)`, `draw(canvas)`**

---

## 剧情对话框 (`qgame.dialog`)

### `DialogBox` (多路由剧情对话框)
* **无感自适应形变**：挂载后能动态抓取父窗口几何尺寸，在拉伸或自适应窗口尺寸缩放时等比缩放背景、页脚高、文本字号和按钮间距。
* **中断式打字机**：内置高频字符逐字输出系统。在打字未结束前鼠标点击对话框，会立刻打断动画并安全展现完整台词。
* **双重头像方案**：头像字段表现出强通用性。支持直接传入 Emoji 表情字符渲染，也可以传入本地图片相对/绝对路径并进行高保真缩放抗锯齿显示。
* **智能节点路由**：如果当前话术节点被编辑器设定了多个选择按钮，它会自动生成按钮排列方案，自动重定向至下层剧情树节点，支持连接完结回调。

---

## 分组 (`qgame.group`)

### `Group` （共同分享坐标）

`Group` 是一个轻量级的游戏对象容器。它非常适合用来进行**批量管理**、**父子级坐标联动**（例如：UI 面板与其子按钮、载具与乘客、飞船与炮塔、怪物集群）以及**生命周期统一委托**。

##### 1. 核心特性
* **坐标级联移动 (Coordinate Coupling)**：
  当你修改 `Group` 的 `x`、`y` 属性或调用 `move()` 时，所有子对象会**等量同步移动**。
* **智能坐标重映射 (Coordinate Remapping)**：
  * 当你向组内 `add()` 添加子对象时，子对象会自动叠加 `Group` 的偏移，转换到父级空间。
  * 当你从组内 `remove()` 或 `clear()` 回收子对象时，它会自动减去父级偏移，**无缝还原为绝对坐标**。
* **生命周期托管 (Lifecycle Delegation)**：
  只需在主循环中调用 `group.update(dt)` 和 `group.draw(canvas)`，即可一键批量调度组内所有合规子对象的绘制和物理更新。
* **原生 Python 容器支持 (Native Python Container)**：
  完全支持迭代（`for child in group:`）、求长度（`len(group)`）以及成员查询（`if sprite in group:`）。

##### 2. 常用方法与属性
* `Group(x=0, y=0)`: 构造函数，支持设定初始父级锚点。
* `group.x` / `group.y`: 读写属性，修改会带动全体子成员平移。
* `group.move(dx, dy)`: 同时增量移动本身及所有子成员。
* `group.add(*entities)`: 添加一个或多个实体（自动应用坐标叠加）。
* `group.remove(*entities)`: 移出实体（自动扣除偏移，还原绝对坐标）。
* `group.clear()`: 清空组内所有实体并还原其独立坐标。
* `group.update(dt, *args, **kwargs)`: 遍历调用所有含 `update` 方法的子成员。
* `group.draw(canvas, *args, **kwargs)`: 遍历调用所有含 `draw` 方法的子成员。


---
###### 1
###### _QGame_    : Oh?! What`s that?
###### _QGame_    : It\`s... It\`s DialogBox!
###### _QGame_    : Oh my Gosh! DialogBox? Welcome!
###### _DialogBox_: Oh thank you bro, thank you
###### _QGame_    : What? What did you say to me?
###### _DialogBox_: Uh... Bro? Can\`t say it? I, I don\`t...
###### _QGame_    : You are the first one to call me that!
###### _DialogBox_: ???
---

### `项目模板生成工具`
## 💻 全自适应 QGame 终端环境管家与诊断芯片 (CLI)
修复了 Windows 平台 CMD 等 GBK 控制台的文字重叠及中文乱码现象，且自动向下兼容老版本 DOS 骨架。

### 1. ⚙️ 全息环境诊疗器 (`doctor`)
我们对多层级打包和编译、运行依赖设置了专门的物理排查渠道：
*   **`qgame doctor package`**
    检测本地的打包编译工具链。检测 Nuitka 加速编译器、MinGW (GCC 编译器和环境变量) 以及 PySide6-deploy 工具状态。
    *   *修复命令*: 附加 `--fix` 参数由引擎尝试一键解决由于缺失等导致的打包安装问题：
        ```bash
        qgame doctor package --fix
        ```
*   **`qgame doctor lib`**
    快速扫描多媒体、连麦底层和图像切片等可选运行扩展包。如有缺失，控制台会输出这些模块对于写项目有什么用，并自动对齐依赖。

---

### 2. 📦 自动化可视化依赖安装面板 (`install`)
舍弃了老旧生硬的 `qgame icon install`，升级为智能化一键极速安装箱：
*   **`qgame install lib`**
    唤起交互式全自动安装管家
    使用示例：
    ```text
    qgame install lib
[QGame 报错] 未检测到 sounddevice 库，请先运行: pip install sounddevice numpy
[QGame 报错] 未检测到 numpy 库，请先运行: pip install numpy 或 qgame install lib
============================================================
🚀 Welcome to QGame 自动化生态依赖库安装管家
============================================================

👉 正在智能为您寻找，发现您还有 4 个强大的插件尚未安装：
------------------------------------------------------------
  (1) Pillow
      大小概估: ~15.4 MB
      功用解释: Required for png to .ico icon conversion, automatic square cropping and basic image processing tasks

  (2) sounddevice
      大小概估: ~3.8 KB
      功用解释: Required for low-latency audio stream, LAN voice chat, and vocal input triggers

  (3) numpy
      大小概估: ~30 MB
      功用解释: Required for real-time audio matrix processing, vector calculations, and fast coordinates computations

  (4) lupa
      大小概估: ~3.8 MB
      功用解释: Required for executing high-performance Lua MOD scripts, secure sandbox proxies, and custom entity behaviors

------------------------------------------------------------
请输入以下对应指令：
  [ A ] 📦 一键打包，下载安装【全部】缺失的优秀资源 (推荐)
  [ N ] 🛑 狠心拒绝并直接退出
  [ 1 ] ⭐ 仅单独针对性下载安装 Pillow
  [ 2 ] ⭐ 仅单独针对性下载安装 sounddevice
  [ 3 ] ⭐ 仅单独针对性下载安装 numpy
  [ 4 ] ⭐ 仅单独针对性下载安装 lupa

👉 请输入您的抉择与编号指令 (A/N/数字): A

👷 正在全力为您下载安装所挑选的 4 个扩展依赖...
------------------------------------------------------------
⏳ 正在通过 pip 通道为您拉取 Pillow ...
Collecting sounddevice
  Using cached sounddevice-0.5.5-py3-none-win_amd64.whl.metadata (1.4 kB)
Requirement already satisfied: cffi in C:\Users\Administrator\AppData\Local\Python\pythoncore-3.14-64\Lib\site-packages (from sounddevice) (2.1.0)
Requirement already satisfied: pycparser in C:\Users\Administrator\AppData\Local\Python\pythoncore-3.14-64\Lib\site-packages (from cffi->sounddevice) (3.0)
Using cached sounddevice-0.5.5-py3-none-win_amd64.whl (365 kB)
Installing collected packages: sounddevice
Successfully installed sounddevice-0.5.5
✅ 安装成功: sounddevice 已成功注册至本机！
⏳ 正在通过 pip 通道为您拉取 numpy ...
Collecting numpy
  Downloading numpy-2.5.2-cp314-cp314-win_amd64.whl.metadata (6.6 kB)
Downloading numpy-2.5.2-cp314-cp314-win_amd64.whl (12.6 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 12.6/12.6 MB 5.9 MB/s  0:00:02
Installing collected packages: numpy
Successfully installed numpy-2.5.2
✅ 安装成功: numpy 已成功注册至本机！
⏳ 正在通过 pip 通道为您拉取 lupa ...
Collecting lupa
  Using cached lupa-2.8-cp314-cp314-win_amd64.whl.metadata (62 kB)
Using cached lupa-2.8-cp314-cp314-win_amd64.whl (2.0 MB)
Installing collected packages: lupa
Successfully installed lupa-2.8
✅ 安装成功: lupa 已成功注册至本机！
------------------------------------------------------------
📊 操作完毕！本次已自动帮您一键修复了 4/4 个游戏引擎扩展！
============================================================
    ```
    只需在提示下输入 `a`/`A` 即可一键拉齐所有环境！

---

### 3. 🏹 游戏生成 (`game`)
直接`qgame new game --help`查看所有可生成的游戏（大部分都是字面意思）

---

## 进阶引擎工具

### `Camera` 摄像机对象
* **`follow(target, lerp_speed)`, `update(dt)`**
  平滑追踪绑定物体。推荐将缓动系数 `lerp_speed` 设在 `5.0` 到 `8.0` 之间。
* **`set_deadzone(w, h)`**
  设置相机死区，使其在此长宽区域移动时背景不平移。
* **`set_bounds(min_x, min_y, max_x, max_y)`**
  配置大地图边界限制。防止镜头滑出地图产生黑色虚空。
* **`shake(intensity, duration)`**
  对相机触发一定强度和时长的抖动效果（震屏）。
* **`apply(coord_or_rect)`**
  将游戏内世界坐标在渲染时映射成屏幕的最终像素点配置。

### `Spritesheet` 雪碧图包分析器
* **`get_image(x, y, w, h) -> Image`**
  抓取大图中的单个位置物体图像。
* **`parse_grid(tile_width, tile_height, margin=0, spacing=0) -> list[Image]`**
  规则网格划分图层（适合帧动画等）。
* **`parse_atlas(json_path) -> dict[str, Image]`**
  解析来自 TexturePacker 的 JSON 配置文件字典。

### 🌐 网络骨架接口参考 (`qgame.network`)

网络通讯基于 QtNetwork 非阻塞机制。请直接覆写逻辑或绑定 connect 数据槽。

### 📡 1. UDP 分包网络组件
#### `UDPNetworkServer` (UDP 服务端监听器)
* **`__init__(port: int)`** - 设定网络侦听本机的目标端口。
* **`start() -> bool`** - 启动监听，返回绑定是否成功。
* **`send_to(data: bytes, host: str, port: int)`** - 给特定的网络地址广播该字节报文。
* **`connect_receive(callback: Callable)`** - 连接接收信号槽，回调结构：`callback(data: bytes, ip: str, port: int)`。
* **`close()`** - 注销套接字。

#### `UDPNetworkClient` (UDP 客户端)
* **`start(local_port: int = 0) -> bool`** - 本地开启套接字防线。
* **`send(data: bytes, host: str, port: int)`** - 发送网络数据包。
* **`connect_receive(callback: Callable)`** - 接通回包信号。

---

### 🕸️ 2. WebSocket 大厅组件
已经放在`qgame/examples/Web/UPD`中
#### `WSNetworkServer` (WebSocket 服务端)
* **`__init__(port: int, server_name: str = "QGame")`** - 声明服务端。
* **`start() -> bool`** - 开启 WebSocket 侦听。
* **`broadcast(message: str)`** - 给旗下所有连入的玩家广播消息。
* **`send_to(client_socket, message: str)`** - 给特定网络通道发送文本。
* **`connect_client(callback)`** / **`connect_disconnect(callback)`** - 玩家接入与断开的回调监听槽。
* **`connect_message(callback)`** - 解析某个客户端消息回调：`callback(client_socket, message: str)`。

#### `WSNetworkClient` (WebSocket 客户端)
* **`connect_to(url: str)`** - 连接目标节点，如 `ws://127.0.0.1:80`。
* **`send(message: str)`** - 发送文本指令包。
* **`connect_open(callback)`** / **`connect_close(callback)`** - 连接成功及断线的回调。
* **`connect_message(callback)`** - 监听服务器发来的报文接收：`callback(message: str)`。

---

### 🎙️ 3. 局域网实时双向语音对讲组件 (`QGameVoiceChat`)
需要可选依赖环境支持。如果缺失该包，请运行终端指令 `qgame install lib` 唤醒安装管家一键修复。

#### `QGameVoiceChat` (UDP 音频对等连接器)
*   **`__init__(target_ip: str, bind_port: int = 19999, target_port: int = 19999)`**
    初始化独立双向音频通讯线路。
    *   `target_ip`: 通话同伴（队友）的局域网/公网 IP 地址。
    *   `bind_port`: 本机监听对方发来语音信号的端口，默认 `19999`。
    *   `target_port`: 对方电脑监听你发去声音的接收端口，默认 `19999`。
*   **`start()`**
    正式启动语音通话。同时在本机创建后台音频线程进行双向操作：麦克风采集 + 高比例 zlib 网络高压缩 + UDP 低时延实时发射；异步接收网络远端音频数据 + PCM 还原 + 声卡扬声器极速输出。
*   **`stop()`**
    挂断并完全关闭当前通话，彻底释放声卡通道和套接字占用。
*   **`mute(is_muted: bool)`**
    开麦 / 闭麦（实用交互属性，可直接在游戏循环中绑定按键热键）。闭麦后不仅停止发送音频包，且不产生任何多余的网络流量占用！

---

## 🤖 3. 游戏人工智能参考 (`qgame.ai`)
### 🧭 1. A* 智能寻路组件 (`PathFinder`)
* **`find_path_on_screen(start_pos: tuple, end_pos: tuple, screen_w: int, screen_h: int, grid_size: int = 32) -> list`**
  **（核心推荐）** 输入起点屏幕坐标与终点像素坐标，算法将全自动拉取当前 `collision.active_colliders` 中存放的活动物理碰撞箱作为格栅阻碍进行 8 方向 A* 寻径，最终返回平滑的屏幕像素目标点折线数组。

---

### 🔮 2. 行为预判器类 (`TrajectoryPredictor`)
* **`__init__(history_len: int = 15)`** - 初始化预判队列深度。
* **`update(pos: tuple)`** - 输入跟随角色的当前位置坐标 (x, y)。
* **`predict_future(steps_ahead: int = 10) -> tuple`** - 根据速度和一阶/二阶惯性变化加速度趋势，预判目标在几帧后的屏幕像素点位置。

---

### ⌨️ 3. 输入预判器类 (`InputPredictor`)
* **`__init__(n_gram: int = 3)`** - 定义用于判定的最短记录长度。
* **`record_action(action)`** - 输入玩家按压指令内容。
* **`predict_next() -> Any`** - 根据玩家连续按下规律，智能断言下一时刻最有可能会去点击哪个按键，返回按键对象。

---
###### **_QGame_: Welcome AI module to QGame Library**_😁_
###### **This will become a very good module, Bro**_🤔_
###### **Ha ha ha, bro, do you know? This is "Rainbow Egg"!**_😜_
###### **Don\`t forget me, I\`m _🍉_**
---

### `调试窗口`
* **`qgame.debugger.init(width=360, height=600, title="调试器", font_size=11, echo=True)`**
  打开并启动调试窗口。
  - `width` / `height`：调试窗口的高宽尺寸。
  - `title`：调试窗口顶部的装饰性文案。
  - `font_size`：面板中英文字型的字号大小（建议在 10 ~ 16 之间，行高会自动扩展适配）。
* **`qgame.debugger.watch(name: str, value_func)`**
  注册或更新一个被观察变量。
  - `name`：在左侧高亮显示的白蓝色键名。
  - `value_func`：**匿名 Lambda 表达式（例如 `lambda: hero.hp`）**或一个固定常量。Lambda 表达式能防止悬空指针错误，保证每次绘图抓取到的是堆内存中的最新值。
* **`qgame.debugger.unwatch(name: str)`**
  从调试视图中取消对该变量名的追踪展示。
* **鼠标滚轮支持**
  当观测数据量比较大并超出窗口可视区域时，将鼠标悬停在调试窗口内进行**滚轮滚动**即可上下滑动翻页，按住不松即可顺滑查阅。
**交互式视觉引导**：当鼠标划过支持修改的变量行时，光盘指针会自动切换为点击手型且背景行微亮高亮。可写入修改的属性名后方都会显式追加标示笔图标（`✎`）。
  - **自动结构还原解析**：内置 Python 抽象语法树（AST）解构器。当你输入修改数值时，系统会自动将你的字符串还原成原始的布尔型（`True`/`False`）、整型、浮点数，甚至是复杂的列表 `list` 或字典 `dict`，防止写入类型混淆导致崩溃。
  - **接口用法与实例**：
    要启用可编辑写入功能，需传入属性所属的对象实例和属性名组成的 `tuple` 对，或者传入自定义的代码写入回调函数 `setter`：

    ```python
    # 1. 对象反射绑定（支持读写，自动操作 player.speed）
    qgame.debugger.watch("玩家速度", (player, "speed"))

    # 2. 自定义 Setter 回调绑定（lambda读取数值，setter接收新值并执行复杂逻辑）
    qgame.debugger.watch("游戏难度", lambda: world.difficulty, setter=world.set_difficulty)

    # 3. 静态只读模式（若仅仅传值或普通无 setter 的 Lambda，则保持灰色只读显示）
    qgame.debugger.watch("系统帧率", lambda: clock.get_fps())
    ```


---
# About QGame Story
## QGame的诞生与命名
其实是觉得Godot太难了，对，我说Godot太难了，我自己都不敢相信。开玩笑，只是当时写的那个游戏太石山了，我自己都看不下去了。然后就莫名想到“做一个游戏引擎吧！”，然后就开始写了，当时我都不知道要叫什么名字！然后我问AI后得出QGame，全称：Qt Game。
## 为什么要发到PyPI上？
反正之前也做过Python包过（more_math、2D-Animation-lib），所以就想“反正又没啥坏处”，让后就发到PyPI上了。
## 为什么更新得这么频繁？
由于放暑假，且也不知道干什么，然后想到我还有个项目，叫QGame，所以这几天更新得很频繁。如果没放假或不是那种3天以上的假期，我基本没时间去搞。所以一般寒暑假才会更新
## QGame如何推广？
我在B站上有号，虽然还没发这个视频，因为Bro电脑不怎么好，虽然用EV录屏还好且介绍2D-Animation-lib发现也不怎么卡。所以为什么没录呢？因为我想更新到QGame特别牛逼的成都再录和发
## 彩蛋是怎么来的？
彩蛋是在1.3.0加入的。为什么加入？是在跟xx聊天时，我说了句“那xx，你觉得我🍉的“`Ｏ、给木”主🦾（打）的是什么？”而最先引发的。然后我问““Ｏ、给木” = QGame，那英语呢？`”然后“英国人be like：”当时我其实是想模拟英国人看到“给木”俩中文看不懂，然后去中国后不走的剧情，当时就纯粹为了搞笑而搞笑的，但谁知，这竟然变成了：
**`自己寻找哦`**
这是QGame彩蛋时空中的一个重要历史！

---
**Hey! Bro, congratulations on finishing reading this entire document!**
**Thank you very much! Bro,  ha ha ha...**
**That`s right, this is "Rainbow egg" too!**
**Thank you use QGame engine!**
**Wishing you a happy life!**
---
---
