# mini-game-tools - 轻量级数学与游戏工具库



一个零外部依赖的Python工具库，提供分数运算、数学函数、随机数生成、颜色处理、几何碰撞检测、向量运算和存档系统。

## 特性

- 🧮 **sfrac** - 零依赖的分数类，支持精确运算
- 📐 **smath** - 基础数学函数（三角函数、对数、取整等），支持复数运算
- 🎲 **srandom** - 可种子控制的随机数生成器
- 🎨 **scolor** - RGB/HSV颜色转换、插值、常用颜色
- 📏 **sgeometry** - 2D/3D几何类型与碰撞检测（矩形、圆形、线段、AABB、球体）
- ➡️ **svector** - 二维/三维向量运算
- 💾 **ssaver** - SGT格式存档系统，带校验和验证
- **solver** - 解1~3次方程
- 📦 **smaze** - 迷宫生成与寻路
- **sui** - UI组件
- **sformat** - 转换器
## 如何使用

### 分数运算 (sfrac)

```python
from mlib import frac

a = frac(1, 2)  # 1/2
b = frac(3, 4)  # 3/4
c = frac(9, 4)

print(a + b)          # 1.25
print(repr(a * b))    # 3/8
print(float(a / b))   # 0.6666666666666666
print(a > b)          # False
print(a == b)         # false
print(c ** 0.5)       # 3/2

```

### 数学函数 (smath)

```python
from mlib import *

# 三角函数（支持复数）
print(sin(pi/2))      # 1.0
print(cos(1+2j))      # 复数结果

# 对数
print(log(100))       # 2.0
print(ln(e**2))       # 2.0

# 取整与映射
print(floor(3.7))     # 3
print(ceil(3.2))      # 4
print(map(50, 0,100, 0,360))  # 180.0

# 统记函数
...

```

### 随机数 (srandom)

```python
from mlib import SimpleRNG

rng = SimpleRNG("my_seed")
print(rng.randint(1, 10))     # 随机整数
print(rng.random())            # [0,1) 浮点数
print(rng.choice(["a","b","c"]))  # 随机选择
print(rng.sample_by_y(lambda x: x**2, 3, 10) #根据函数高度取随机数

# 随机抽牌（不重复）
cards = list(range(20))
hand = rng.sample(cards, 5)    # 抽5张，例如 [7, 1, 3, 6, 19]

# 打乱顺序（原地修改）
rng.shuffle(cards)              # cards 顺序被打乱
print(cards)                    # 例如 [7, 1, 12, 15, 18, 16, ...]

print(rng.choices(["a, "b", "c"], [0.1, 0.2, 0.7])) # 带权重的随机选择

print(rng.roll("4d6kl1+2d8kh1+2d6x2-2")) # 色子解析

```

### 颜色处理 (scolor)

```python
from mlib import *

# RGB操作
print(hex_to_rgb("#FF0000"))   # (255, 0, 0)
print(rgb_to_hex(0,255,0))     # #00ff00

# HSV转换
hsv = rgb_to_hsv(255,0,0)      # (0.0, 1.0, 1.0)
rgb = hsv_to_rgb(120, 1, 1)    # (0, 255, 0)

# 颜色插值
c1 = RED
c2 = BLUE
print(lerp(c1, c2, 0.5))       # (127, 0, 127)

# 颜色混合 - 正片叠底
blend(GREEN, PURPLE, "multiply") # (0, 112, 0)

# 颜色混合 - 滤色

blend(GREEN, PURPLE, "screen") # (147.0, 255.0, 219.0)

# 多色渐变
gradient_at(colors, place)
gradient_range(colors, step)

```

### 几何碰撞 (sgeometry)

```python
from mlib import *

# 2D矩形
rect = Rect(0,0,100,100)
print(rect.collide_point(50,50))      # True
print(rect.collide_circle(Circle((150,150),20)))  # False

# 线段
line = Line2((0,0),(100,100))
print(line.closest_point((50,0)))     # (25,25)

# 3D AABB
box = AABB((0,0,0),(10,10,10))
print(box.collide_point((5,5,5)))     # True
```

### 向量运算 (svector)

```python
from mlib import vec2, vec3

v2 = vec2(3,4)
print(v2.length())          # 5.0
print(v2.normalize())       # (0.6, 0.8)

v3 = vec3(1,0,0)
w3 = vec3(0,1,0)
print(v3.cross(w3))         # (0,0,1)
```

### 存档系统 (ssaver)

```python
from mlib import SGTsaver
from mlib import vec2

# 保存数据
saver = SGTsaver()
saver.set_value(
    score=100,
    name="hero",
    position=vec2(10,20),
    items=["sword","potion"]
)
saver.save("game.sgt")

# 加载数据
loaded = SGTsaver().load("game.sgt")
print(loaded["name"])       # "hero"
print(loaded["position"])   # (10.0, 20.0)
```

#### 基本寻路与迷宫生成
```python
from mlib import bfs, dfs_maker
# 地图：0可走，1障碍
grid = [
    [0,0,0,0,0],
    [0,1,1,1,0],
    [0,0,0,0,0],
    [0,1,1,1,0],
    [0,0,0,0,0]
]

# 找路径
path = bfs(grid, (0,0), (4,4))

# 输出路径
for p in path:
    print(f"({p.x}, {p.y})")

# 生成迷宫
maze = dfs_maker(width, height, seed, start=(1,1))
```

#### 配合 vec2
```python
from mlib import vec2, bfs

start = vec2(0, 0)
end = vec2(4, 4)

path = bfs(grid, start, end)
print(f"需要 {len(path)} 步")
print(f"第一步: {path[1]}")
```

#### 无路可走
```python
path = bfs(grid, (0,0), (4,4))
if path is None:
    print("到不了终点")
```

#### UI组件
```python
# 可使用方法：render、destroy、enter、config

Label(
    x, y, width, height,           # 位置和尺寸
    text="",                       # 显示的文本
    color=(240,240,240),           # 背景颜色
    text_color=(0,0,0),            # 文字颜色
    align='left'                   # 对齐方式：left/center/right
)

Button(
    x, y, width, height,           # 位置和尺寸
    text="",                       # 按钮文字
    color=(200,200,200),           # 普通状态颜色
    hover_color=(220,220,220),     # 悬停状态颜色
    press_color=(160,160,160),     # 按下状态颜色
    text_color=(0,0,0),            # 文字颜色
    border=True,                   # 是否显示边框
    radius=3                        # 圆角半径
)
# 额外方法：press、release

Bar(
    x, y, width, height,           # 位置和尺寸
    value=1.0,                     # 当前值 (0.0 - 1.0)
    bg_color=(60,60,60),           # 背景颜色
    fill_color=(255,50,50),        # 填充颜色
    text_color=(255,255,255),      # 百分比文字颜色
    show_text=True,                 # 是否显示百分比
    orientation='horizontal'        # 方向：horizontal/vertical
)
# 额外方法：set_hp
```

#### 解方程
```python
roots([a, b]) # -> 方程ax + b = 0
# 如 roots([1, 2]) -> [-2.0]
roots([a, b, c]) # -> 方程ax² + bx + c = 0
# 如 roots([2, -6, 4]) -> [1.0, 2.0]
roots([a, b, c, d]) # -> 方程ax³ + bx² + cx + d = 0
# 如roots([1, -6, 11, -6]) -> [(3-5.551115123125783e-17j), (1.0000000000000002+0j), (2+0j)](出现了一些浮点误差)
```

#### 转换器
```python
number_to_english(114514) # 'one hundred and fourteen thousand five hundred and fourteen'
english_to_number("one hundred and fourteen thousand five hundred and fourteen") # 114514
from_decimal(15, -2) #
to_poly("3x^2y^3z^4 - 5xy^2z^3 + 2x^2y^3z^4 + 7xy^2z^3 - 4x^3y^2z + 6x^2y^3z^4 - 2xy^2z^3 + 8x^3y^2z - 3x^2y^2z^3 + 5x^3y^2z - x^2y^3z^4 + 4xy^3z^2 - 2xy^3z^2 + 9x^2y^2z^3 - 6xy^3z^2 + xyz") #'6*x**2y**2z**3+10*x**2y**3z**4+9*x**3y**2z-4*xy**3z**2+xyz'
to_poly("x^2y^3z^4 + 2x^2y^3z^4 - 3x^2y^3z^4 + 4x^2y^3z^4 - 5x^2y^3z^4 + 6x^2y^3z^4 - 7x^2y^3z^4 + 8x^2y^3z^4 - 9x^2y^3z^4 + 10x^2y^3z^4", True) # '7x^2y^3z^4'
to_UUID("hello world") # 'hell-o wo-rld'
encode("hello") # '11041101110811081111'
decode('11041101110811081111') # "hello"
```
## SGT文件格式

```
SGTv1                  # 魔数（被跳过）
#score=100            # 整数
#name="hero"          # 字符串
#position=(10,20)     # 向量
#items=["sword","potion"]  # 列表
#hash=123456          # 校验和
```

- `#` 开头的行为有效数据
- 非 `#` 开头的行会被跳过
- 自动计算并验证校验和

## 依赖

- 无外部依赖，纯Python实现
- 兼容Python 3.6+

## 许可证
MIT License

## 关于版本号(从1.5.0开始有效)
1.5.0
0:当出现修复bug时，该号加一
5:当出现向下兼容的功能时，该号加一
1:当出现不向下兼容的API时，该号加一
