Qt/C++基于重力模拟的像素点水平堆叠效果
本文将深入解析一个基于 Qt/C++ 的像素点模拟程序。程序通过 重力作用,将随机分布的像素点下落并水平堆叠,同时支持窗口动态拉伸后重新计算像素点分布。


程序功能概述
- 随机生成像素点:程序在初始化时随机生成一定数量的像素点,每个像素点有随机的初始位置和速度。
- 重力模拟:像素点在重力作用下不断下落,并与地面发生弹性碰撞。
- 水平堆叠:像素点在下落后静止并水平堆叠,模拟堆积效果。
- 碰撞检测:像素点之间检测是否发生碰撞并进行弹性处理。
- 窗口自适应:当窗口大小变化时,自动重新分布像素点。
核心实现细节
1. 像素点结构体
像素点通过 Pixel 结构体定义,包含以下属性:
x和y:像素点的二维位置。vx和vy:像素点的水平和垂直速度。isStatic:标记像素点是否已经静止。
定义如下:
struct Pixel {double x, y; // 像素点位置double vx, vy; // 像素点速度bool isStatic; // 是否已经静止
};
2. 重力与碰撞模拟
重力计算
每个像素点的垂直速度受重力影响,逐帧增加重力值:
p.vy += gravity;
像素点的速度更新后,其位置随之更新:
p.x += p.vx;
p.y += p.vy;
边界检测
为了防止像素点越过窗口边界,加入边界检测与反弹逻辑:
if (p.x < radius || p.x > width() - radius) {p.vx *= -restitution; // 水平方向的反弹p.x = clamp(p.x, (double)radius, (double)(width() - radius));
}
在这里:
radius是像素点的半径,防止越界。restitution控制反弹的弹性,值为0-1,1表示完全弹性,0表示无弹性。
碰撞地面
当像素点接触地面时,垂直速度反弹,同时逐渐水平减速:
if (p.y > groundLevel) {p.vy *= -restitution; // 垂直方向反弹p.y = groundLevel; // 防止越过地面p.vx *= damping;p.vy *= damping;
}
groundLevel表示地面高度。damping表示速度阻尼系数,用于减小速度,模拟摩擦力。
3. 静止与堆叠机制
像素点在速度足够小的情况下会被标记为静止:
if (std::abs(p.vx) < staticThreshold && std::abs(p.vy) < staticThreshold) {p.vx = 0;p.vy = 0;p.isStatic = true;
}
静止后,像素点不再更新速度和位置,从而节省计算资源。
水平堆叠的网格机制
为了实现堆叠效果,使用了一个二维网格 grid 来记录像素点的静止位置:
std::vector<std::vector<bool>> grid(gridWidth, std::vector<bool>(gridHeight, false));
每个网格单元表示一个像素点的静止状态。当像素点静止后,更新对应的网格状态:
int gridX = p.x / (2 * radius);
int gridY = groundLevel / (2 * radius);
if (gridX >= 0 && gridX < gridWidth && gridY >= 0 && gridY < gridHeight) {grid[gridX][gridY] = true;
}
通过检测 grid 的状态,确保新下落的像素点不会与静止点重叠。
4. 碰撞处理
当两个像素点之间的距离小于其直径时,认为发生了碰撞。处理逻辑如下:
double distance = std::sqrt(dx * dx + dy * dy);
if (distance < 2 * radius && distance > 1e-6) { // 避免除以零double overlap = 2 * radius - distance;double nx = dx / distance;double ny = dy / distance;p.x += nx * overlap / 2;p.y += ny * overlap / 2;other.x -= nx * overlap / 2;other.y -= ny * overlap / 2;// 水平速度调整p.vx *= damping;other.vx *= damping;
}
这里:
overlap表示像素点之间的重叠距离。nx和ny是碰撞方向的单位向量。- 调整每个像素点的位置以消除重叠,并减小速度。
5. 窗口自适应
窗口大小改变事件
当窗口大小改变时,重新初始化像素点,以适应新的窗口尺寸。通过重载 resizeEvent 实现:
void GravityWidget::resizeEvent(QResizeEvent *event) {initializePixels(); // 重新初始化像素点QWidget::resizeEvent(event);
}
像素点重新初始化
重新生成随机分布的像素点:
void GravityWidget::initializePixels() {pixels.clear();for (int i = 0; i < 200; ++i) {Pixel p;p.x = std::rand() % width();p.y = std::rand() % height();p.vx = 0;p.vy = 0;p.isStatic = false;pixels.push_back(p);}
}
6. 图形绘制
通过重载 paintEvent 实现像素点的绘制:
void GravityWidget::paintEvent(QPaintEvent *) {QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);painter.setBrush(Qt::blue);for (const auto &p : pixels) {painter.drawEllipse(QPointF(p.x, p.y), 3, 3); // 绘制小圆点}
}
运行效果
- 重力下落:随机生成的像素点在重力作用下逐渐下落。
- 弹性碰撞:像素点彼此碰撞时会弹开,最终逐渐稳定。
- 水平堆叠:像素点在地面静止后自然堆叠,形成类似水波的排列效果。
- 窗口自适应:拉伸或缩小窗口时,像素点会重新生成并分布。
相关文章:
Qt/C++基于重力模拟的像素点水平堆叠效果
本文将深入解析一个基于 Qt/C 的像素点模拟程序。程序通过 重力作用,将随机分布的像素点下落并水平堆叠,同时支持窗口动态拉伸后重新计算像素点分布。 程序功能概述 随机生成像素点:程序在初始化时随机生成一定数量的像素点,每个…...
Zookeeper学习心得
本人学zookeeper时按照此文路线学的 Zookeeper学习大纲 - 似懂非懂视为不懂 - 博客园 一、Zookeeper安装 ZooKeeper 入门教程 - Java陈序员 - 博客园 Docker安装Zookeeper教程(超详细)_docker 安装zk-CSDN博客 二、 zookeeper的数据模型 ZooKeepe…...
嵌入式开发工程师面试题 - 2024/11/24
原文嵌入式开发工程师面试题 - 2024/11/24 转载请注明来源 1.若有以下定义语句double a[8],*pa;int i5;对数组元素错误的引用是? A *a B a[5] C *(p1) D p[8] 解析: 在 C 或 C 语言中&am…...
Python中打印当前目录文件树的脚本
效果图: 实现脚本: 1、显示所有文件和文件夹: import osdef list_files(startpath, prefix):items os.listdir(startpath)items.sort()for index, item in enumerate(items):item_path os.path.join(startpath, item)is_last index le…...
全景图像(Panorama Image)向透视图像(Perspective Image)的跨视图转化(Cross-view)
一、概念讲解 全景图像到透视图像的转化是一个复杂的图像处理过程,它涉及到将一个360度的全景图像转换为一个具有透视效果的图像,这种图像更接近于人眼观察世界的方式。全景图像通常是一个矩形图像,它通过将球面图像映射到平面上得到…...
Redis 中的 hcan 命令耗内存,有什么优化的方式吗 ?
Redis 中的 hcan 命令耗内存,有什么优化的方式吗 ? 1. 使用合适的游标值:2. 控制每次迭代返回的键数量:3. 避免长时间运行的迭代:4. 使用HSCAN与SCAN命令结合:5. 优化哈希表结构:6. 监控和调整R…...
豆包MarsCode算法题:三数之和问题
问题描述 思路分析 1. 排序数组 目的: 将数组 arr 按升序排序,这样可以方便地使用双指针找到满足条件的三元组,同时避免重复的三元组被重复计算。优势: 数组有序后,处理两个数和 target - arr[i] 的问题可以通过双指针快速找到所有可能的组…...
【Android】AnimationDrawable帧动画的实现
目录 引言 一、AnimationDrawable常用方法 1.1 导包 1.2 addFrame 1.3 setOneShot 1.4 start 1.5 stop 1.6 isRunning 二、 从xml文件获取并播放帧动画 2.1 创建XML文件 2.2 在布局文件中使用帧动画资源 三、在代码中生成并播放帧动画 3.1 addFrame加入帧动画列…...
【消息序列】详解(7):剖析回环模式--设备测试的核心利器
目录 一、概述 1.1. 本地回环模式 1.2. 远程环回模式 二、本地回环模式(Local Loopback mode) 2.1. 步骤 1:主机进入本地环回模式 2.2. 本地回环测试 2.2.1. 步骤 2a:主机发送HCI数据包并接收环回数据 2.2.2. 步骤 2b&…...
解决Ubuntu 22.04系统中网络Ping问题的方法
在Ubuntu 22.04系统中,网络问题时有发生,尤其是当涉及到静态IP地址配置和网线直连的两台机器时。本文将探讨一种常见问题——断开并重新连接网线后,尽管网卡显示为UP状态,但无法立即ping通对方机器,以及如何解决这一问…...
【大数据学习 | Spark-SQL】Spark-SQL编程
上面的是SparkSQL的API操作。 1. 将RDD转化为DataFrame对象 DataFrame: DataFrame是一种以RDD为基础的分布式数据集,类似于传统数据库中的二维表格。带有schema元信息,即DataFrame所表示的二维表数据集的每一列都带有名称和类型。这样的数…...
15分钟做完一个小程序,腾讯这个工具有点东西
我记得很久之前,我们都在讲什么低代码/无代码平台,这个概念很久了,但是,一直没有很好的落地,整体的效果也不算好。 自从去年 ChatGPT 这类大模型大火以来,各大科技公司也都推出了很多 AI 代码助手ÿ…...
manim动画编程(安装+入门)
文章目录 1.基本介绍2.效果展示3.安装步骤3.1安装manba软件3.2配置环境变量3.3查看是否成功3.4什么是mamba3.5创建虚拟环境3.6尝试进入虚拟环境 4.vscode操作4.1默认配置文件 5.安装ffmpeg6.安装manim软件6.vscode制作7.我的学习收获 1.基本介绍 这个manim就是一款软件&#x…...
STL算法之数值算法<stl_numeric.h>
这一节介绍的算法,统称为数值(numeric)算法。STL规定,欲使用它们,客户端必须包含头文件<numeric>.SGI将它们实现与<stl_numeric.h>文件中。 目录 运用实例 accumulate adjacent_difference inner_product partial_sum pow…...
Oracle如何记录登录用户IP
在运维场景中,在定位到某个SQL引起系统故障之后,想知道是哪台机器发过来的,方便定位源头,该如何解决? 在 Oracle 数据库中记录登录用户的 IP 地址可以通过多种方法实现。以下是几种常见的方法,包括使用触发…...
Python图像处理:打造平滑液化效果动画
液化动画中的强度变化是通过在每一帧中逐渐调整液化效果的强度参数来实现的。在提供的代码示例中,强度变化是通过一个简单的线性插值方法来控制的,即随着动画帧数的增加,液化效果的强度也逐渐增加。 def liquify_image(image, center, radius…...
构建Ceph分布式文件共享系统:手动部署指南
#作者:西门吹雪 文章目录 micro-Services-TutorialCeph分布式文件共享方案部署Ceph集群使用CephCeph在kubernetes集群中的使用 micro-Services-Tutorial 微服务最早由Martin Fowler与James Lewis于2014年共同提出,微服务架构风格是一种使用一套小服务来开发单个应…...
数据结构——用数组实现栈和队列
目录 用数组实现栈和队列 一、数组实现栈 1.stack类 2.测试 二、数组实现队列 1.Queue类 2.测试 查询——数组:数组在内存中是连续空间 增删改——链表:链表的增删改处理更方便一些 满足数据先进后出的特点的就是栈,先进先出就是队列…...
vue3typescript,shims-vue.d.ts中declare module的vue声明
webpack已经有了vue-loader这些loader了,为什么还需要declare module *.vue’呢? declare module 是为了告诉 tsc 这是一个“模块”。 如果不声明, IDE 里因为 tsc 类型检查, lint 会标红。 但vue-loader 是在 Webpack 构建阶段使…...
C/C++基础知识复习(30)
1) 什么是 C 中的 Lambda 表达式?它的作用是什么? Lambda 表达式: 在 C 中,Lambda 表达式是一种可以定义匿名函数的机制,可以在代码中快速创建一个内联的函数对象,而不需要显式地定义一个函数。Lambda 表…...
别再为LoRaWAN入网失败抓狂了!手把手教你排查OTAA/ABP激活问题(以利尔达WB25模组为例)
LoRaWAN设备入网失败全链路排查指南:从频段配置到密钥管理的深度解析 当WB25模组的LED指示灯从闪烁变为常亮时,意味着它已成功加入LoRaWAN网络——这个瞬间对物联网开发者而言,往往意味着调试阶段最令人振奋的时刻。但现实情况是,…...
如何3分钟搞定游戏模组管理:XXMI启动器的终极解决方案
如何3分钟搞定游戏模组管理:XXMI启动器的终极解决方案 【免费下载链接】XXMI-Launcher Modding platform for GI, HSR, WW and ZZZ 项目地址: https://gitcode.com/gh_mirrors/xx/XXMI-Launcher 还在为复杂的游戏模组管理而烦恼吗?XXMI启动器作为…...
OpenClaw机械臂自动化部署指南:从环境配置到Docker化实践
1. 项目概述:一个为开源硬件项目量身打造的自动化部署指南最近在折腾一个叫 OpenClaw 的开源机械臂项目,发现它的社区里有个宝藏仓库,就是lorenzespinosa/openclaw-setup-guide。这可不是一份简单的安装说明书,而是一个高度集成、…...
Cursor编辑器专属JavaScript代码片段库:提升开发效率的利器
1. 项目概述:一个为开发者量身定制的代码片段管理工具如果你和我一样,每天大部分时间都在和代码编辑器打交道,那你肯定有过这样的体验:某个功能你明明写过很多遍,但每次要用的时候,要么得去翻旧项目&#x…...
别再死记硬背了!用Arduino和ESP32实测SPI、I2C、UART,看完就懂怎么选
别再死记硬背了!用Arduino和ESP32实测SPI、I2C、UART,看完就懂怎么选 刚接触嵌入式开发时,面对SPI、I2C、UART这三种通信协议,你是不是也背过各种对比表格?但一到实际项目,还是不知道如何选择。今天我们就用…...
WorkshopDL:跨平台Steam创意工坊下载器的技术探索与实践
WorkshopDL:跨平台Steam创意工坊下载器的技术探索与实践 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否曾在Epic Games Store或GOG平台购买了心仪的游戏&…...
StarRailCopilot:崩坏星穹铁道全自动脚本终极解决方案
StarRailCopilot:崩坏星穹铁道全自动脚本终极解决方案 【免费下载链接】StarRailCopilot 崩坏:星穹铁道脚本 | Honkai: Star Rail auto bot (简体中文/繁體中文/English/Espaol) 项目地址: https://gitcode.com/gh_mirrors/st/StarRailCopilot 你…...
【收藏级】2026年版 AI Agent两大核心范式详解:ReAct与Ralph Loop,小白程序员必学大模型进阶指南
本文全面拆解2026年AI Agent领域最核心的两大范式——经典ReAct“思考-行动-观察”闭环与颠覆性Ralph Loop“无限自主迭代”新模式,用通俗语言帮小白程序员快速吃透大模型Agent的核心逻辑,助力程序员抓住前沿技术红利。ReAct擅长短任务与动态规划&#x…...
告别CAN的昂贵:手把手教你用STM32的UART实现LIN总线从机节点(附完整代码)
低成本LIN从机节点实战:基于STM32 UART的完整实现方案 在汽车电子和工业控制领域,LIN总线因其极低的实现成本成为CAN总线的理想补充。本文将彻底解析如何利用STM32内置UART外设构建LIN从机节点,无需额外硬件成本即可实现与标准LIN主机的可靠通…...
从“与或非”门到AI加速:一文捋清FPGA的硬核实力与应用边界
从“与或非”门到AI加速:一文捋清FPGA的硬核实力与应用边界 在计算架构的竞技场上,FPGA(现场可编程门阵列)如同一位低调的全能选手——它既能像CPU那样灵活编程,又能像ASIC那样高效执行,却鲜少被大众熟知。…...
