Particles 是一个使用 Python、NumPy 和 Pygame 编写的二维粒子模拟程序。它用于观察大量不同类别粒子在非对称作用力下形成的运动模式、聚集结构或分离区域。
程序把地图视为周期环面:粒子从右边离开会从左边返回,从下边离开会从上边返回;计算粒子间作用时,也会使用所有周期映像中的最短相对位移。因此,地图边缘不会成为特殊边界。
普通粒子演示通常只支持少量粒子、对称作用力或固定参数。本项目提供一个可交互的实验环境,用于解决以下需求:
- 模拟大量粒子的连续运动,并通过范围截断和可选 Numba 加速降低计算开销。
- 表达不同类别之间的非对称关系。例如,A 可以被 B 吸引,而 B 同时被 A 排斥。
- 在周期地图中正确处理跨边界运动和跨边界相互作用。
- 用短程斥力阻止相互吸引的粒子无限坍缩到同一点。
- 在模拟过程中修改参数和粒子数据,并通过撤销、存档、备份和预案反复实验。
类别作用矩阵的约定为:
K[受力粒子类别 i][施力粒子类别 j]
K > 0:吸引
K < 0:排斥
K = 0:不产生该类别作用
矩阵不要求对称,同类粒子的作用由矩阵对角线控制。
- 随机生成粒子位置、初速度和类别。
- 可设置粒子数量、世界宽高、类别数量、随机种子、K 值范围、交互半径、软化参数和初始速度。
- K 值支持均匀分布、高斯分布和带随机正负号的对数正态幅值分布。
- 同类作用可选择偏向吸引、普通随机或设为零;默认同类有 90% 概率取吸引值。
- 世界尺寸可在运行中修改;调整后,越界粒子会按周期规则折回世界内部。
- 类别作用项:
K[i][j] · d / (r² + soft²)^(3/2),力的大小近似按平方反比变化。 - 短程斥力项:
-repulsion · d / (r² + soft²)²,力的大小近似按立方反比变化。 - 支持阻尼、速度上限、时间流速、物理步长和每帧固定步数。
- 支持两种计算模式:
范围截断:使用周期单元列表,只计算交互半径内的粒子,适合大量粒子。精确全对:计算所有粒子对,复杂度为O(N²),只建议用于约 3000 个或更少的粒子。
- 窗口中以不同颜色显示不同类别的粒子。
- 鼠标滚轮以光标为中心缩放;右键或中键拖动平移;
Home恢复完整世界视角。 - 可调整粒子的渲染大小。
- 低倍率使用可视区域栅格化,高倍率使用裁剪后的屏幕直绘;右侧面板遮挡的区域不会继续渲染粒子。
- 信息页显示粒子数量、引擎状态、视角数据和估算的相互作用对数。
- 点选或框选粒子,按住
Shift可增减选择。 - 移动选中粒子,修改速度、归零速度、添加随机速度、修改类别或删除粒子。
- 从当前选择中筛选指定颜色/类别的粒子。
- 随机添加一批粒子,或在光标附近添加粒子。
- 增加粒子类别并编辑完整的类别参数矩阵。
- 支持撤销和重做;日志页记录生成、存读档、编辑及撤销等改动。
- 启动时先选择“创建新世界”“读取存档”或“读取备份”,不会自动生成世界。
- 顶部工具栏和左下角“世界控制”条都提供暂停、存档、读档和备份按钮。
- 模拟运行时每 90 秒自动备份一次,最多保留 30 个备份文件。
- 读档窗口可以同时显示普通存档和备份;启动菜单也提供单独的备份入口。
- 世界生成参数、模拟参数和类别矩阵分别保存为三类独立预案。
- 创建新世界前可以读取三类预案;矩阵预案会在类别数量匹配时应用到新世界。
运行数据默认保存在项目根目录:
saves/*.npz 普通存档和快速存档
backups/backup_*.npz 自动或手动备份
presets/gen_*.json 世界生成预案
presets/sim_*.json 模拟参数预案
presets/matrix_*.json 类别矩阵预案
项目当前以源码形式运行。推荐使用 Windows 和 Python 3.9 或更高版本;当前开发与测试环境使用 Python 3.12。
在项目目录中打开 PowerShell,然后创建虚拟环境并安装依赖:
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install --upgrade pip
.\.venv\Scripts\python.exe -m pip install -r requirements.txt依赖包括:
- NumPy:粒子数组和向量化计算。
- Pygame:窗口、输入和渲染。
- Numba:多线程物理计算加速。代码可以在没有 Numba 时回退到 NumPy,但大量粒子下会明显变慢。
安装完成后启动:
.\.venv\Scripts\python.exe run.py如果已经激活虚拟环境,也可以使用:
python run.py启动应用后:
- 点击“创建新世界”打开生成选项;可以先读取生成、模拟或矩阵预案,再继续修改参数。
- 点击“读取存档”恢复
saves/中的世界。 - 点击“读取备份”恢复
backups/中的世界。 - 新世界生成或存档读取完成后默认暂停,按空格或点击“继续”开始模拟。
右侧“参数”页可调整时间流速、每帧步数、步长、软化、短程斥力、阻尼、最大速度、交互半径和粒子渲染大小。每个参数既有滑块,也有精确数值输入框;输入后按 Enter 应用。将鼠标停在滑块上可查看说明。
参数页还可以切换范围截断/精确全对、修改世界尺寸,以及分别保存或读取三类预案。
- 选择顶部“选择”工具,在地图中点选或拖出矩形进行框选。
- 打开右侧“编辑”页,修改选中粒子的速度、类别或删除粒子。
- 点击类别色块可修改类别;使用对应的“筛色”操作可只保留该类别的选中粒子。
- 选择“移动”工具后拖动选中粒子;选择“添加”工具后可在地图上逐粒添加。
- 使用
Ctrl+Z撤销、Ctrl+Y重做。
- “保存”或
Ctrl+S:输入名称后保存到saves/。 - 左下角“快速存档”:自动生成带时间戳的名称并保存到
saves/。 - “备份”或
Ctrl+B:立即保存到backups/。 - 顶部或左下角“读档”:打开普通存档和备份列表,点击文件即可恢复。
Ctrl+O:打开普通存档列表。
| 操作 | 鼠标或快捷键 |
|---|---|
| 暂停/继续 | Space |
| 暂停时单步 | . |
| 选择、移动、信息、添加工具 | S / M / I / A |
| 增减选择 | Shift + 点击/框选 |
| 删除选中粒子 | Delete 或 Backspace |
| 将选中粒子改为类别 0—9 | 1—9、0 |
| 微移选中粒子 | 方向键 |
| 撤销/重做 | Ctrl+Z / Ctrl+Y |
| 命名保存/读取普通存档 | Ctrl+S / Ctrl+O |
| 立即备份 | Ctrl+B |
| 创建新世界 | N |
| 开关右侧面板 | Tab |
| 缩放/复位视角 | 滚轮、+、-、Home |
| 平移视角 | 鼠标右键或中键拖动 |
| 帮助 | F1 |
鼠标位于右侧面板时,滚轮不会改变地图缩放。
下面是一次从生成世界到保存实验结果的完整示例:
- 运行
.\.venv\Scripts\python.exe run.py。 - 点击“创建新世界”。
- 将粒子数量设为
8000、世界尺寸设为1280 × 724、类别数设为4。 - 将 K 范围设为
-8000到8000,选择“高斯”分布和“同类偏向吸引”。 - 选择“范围截断”,交互半径设为
150,然后确认生成。 - 按空格开始模拟。在右侧“参数”页把时间流速改为
0.5,较慢地观察结构形成过程。 - 如果粒子聚集过紧,提高“短程斥力”;如果运动过于剧烈,提高阻尼或降低最大速度。
- 按
S切换到选择工具,框选一组粒子;打开“编辑”页,将其速度归零或筛选某个颜色。 - 点击左下角“快速存档”,程序会在
saves/中生成一个quick_日期_时间.npz文件。 - 需要恢复时,点击“读档”,从列表中选择该存档;若普通存档不可用,也可以在同一窗口选择备份。
运行完整测试套件:
.\.venv\Scripts\python.exe -m unittest discover -s tests -v本项目使用 MIT License,详见 LICENSE。