Qt 图形视图框架碰撞检测 官方Demo 移动的小老鼠

2023-10-12 18:50

本文主要是介绍Qt 图形视图框架碰撞检测 官方Demo 移动的小老鼠,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:

本文需要了解基本的 Qt 图形视图框架结构和坐标系统

否则 你可能看不懂

还是看一些 官方demo 可以学到人家一些编码的东西 今天看到个好玩的 见下图
在这里插入图片描述

发现没 当小老鼠 碰到以后 耳朵就变红 也就是有碰撞检测机制

整个的结构就是

管理场景 管理这些小老鼠 是: QGraphicsScene 类
能拖拉的这个窗口 视口 背景设置为了 奶酪的 图片 是 : QGraphicsView 类
移动的小老鼠是: 继承的 QGraphicsItem 类 实现自己的 类

官方的demo:

在这里插入图片描述

还是先看下 项目的 文件结构 :

在这里插入图片描述
简单的
一个 mouse 类
一个 main 函数
一个 jpg 图片 就是奶酪的背景图

main 函数
#include <QtWidgets>#include <math.h>#include "mouse.h"static const int MouseCount = 7;//! [0]
int main(int argc, char **argv)
{QApplication app(argc, argv);qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
//! [0]//! [1]QGraphicsScene scene;scene.setSceneRect(-300, -300, 600, 600);
//! [1] //! [2]scene.setItemIndexMethod(QGraphicsScene::NoIndex);
//! [2]//! [3]for (int i = 0; i < MouseCount; ++i) {Mouse *mouse = new Mouse;mouse->setPos(::sin((i * 6.28) / MouseCount) * 200,::cos((i * 6.28) / MouseCount) * 200);scene.addItem(mouse);}
//! [3]//! [4]QGraphicsView view(&scene);view.setRenderHint(QPainter::Antialiasing);view.setBackgroundBrush(QPixmap(":/images/cheese.jpg"));
//! [4] //! [5]view.setCacheMode(QGraphicsView::CacheBackground);view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);view.setDragMode(QGraphicsView::ScrollHandDrag);
//! [5] //! [6]view.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Colliding Mice"));view.resize(400, 300);view.show();QTimer timer;QObject::connect(&timer, SIGNAL(timeout()), &scene, SLOT(advance()));timer.start(1000 / 33);return app.exec();
}

在这里插入图片描述
main 函数 首先 弄了个矩形的场景 (-300,-300,600,600)
也就是 宽度和高度 为900的 正方形 ,可以去看下坐标系统

左上角是负数无穷小 右下角是正数无穷大 中心 是 (0,0)

在这里插入图片描述

scene.setItemIndexMethod(QGraphicsScene::NoIndex);

在这里插入图片描述
此属性保存项索引方法。
QGraphicsScene将索引算法应用于场景,以加速项发现函数,如items()和itemAt()。索引是最有效的静态场景(即。,这里的物品不会移动)。对于动态场景或具有许多动画项的场景,索引簿记可能会超过快速查找速度。
对于一般情况,默认索引方法BspTreeIndex工作正常。如果你的场景使用了很多动画,并且你正在经历缓慢,你可以通过调用setItemIndexMethod(NoIndex)来禁用索引。

继续向下 实例化了 7个 mouse 类 并添加到 additem 场景中 这个类等会再看
在这里插入图片描述

在向下给场景设置了个视口
给视口设置了背景图 也就是奶酪的照片

下面设置了视口的 渲染区域模式 拖动模式 标题窗口大小 等等
在这里插入图片描述

然后是一个定时器 刷新场景
在这里插入图片描述
在这里插入图片描述
译文:这个槽通过调用QGraphicsItem::advance()来将场景向前推进一步。这分两个阶段完成:在第一阶段,所有的项目都被通知场景将要改变,在第二阶段,所有的项目都被通知它们可以移动。在第一阶段,调用QGraphicsItem::advance(),传递一个值0作为参数,在第二阶段传递1。

很清晰了
下面我们主要看一下 小老鼠 怎么来 怎么动的

mouse 类
#ifndef MOUSE_H
#define MOUSE_H#include <QGraphicsItem>//! [0]
class Mouse : public QGraphicsItem
{
public:Mouse();QRectF boundingRect() const override;QPainterPath shape() const override;void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget) override;protected:void advance(int step) override;private:qreal angle;qreal speed;qreal mouseEyeDirection;QColor color;
};
//! [0]#endif

Mouse 继承了 QGraphicsItem 下面的两个函数 必须要实现
否则编译不过

原因是 基类 QgraphicsItem 把这个函数 设置为了纯虚函数

在这里插入图片描述
基类里面
在这里插入图片描述

#include "mouse.h"#include <QGraphicsScene>
#include <QPainter>
#include <QStyleOption>
#include <QDebug>
#include <math.h>static const double Pi = 3.14159265358979323846264338327950288419717;
static double TwoPi = 2.0 * Pi;static qreal normalizeAngle(qreal angle)
{while (angle < 0)angle += TwoPi;while (angle > TwoPi)angle -= TwoPi;return angle;
}//! [0]
Mouse::Mouse(): angle(0), speed(0), mouseEyeDirection(0),color(qrand() % 256, qrand() % 256, qrand() % 256)
{setRotation(qrand() % (360 * 16));
}
//! [0]//! [1]
QRectF Mouse::boundingRect() const
{qreal adjust = 0.5;return QRectF(-18 - adjust, -22 - adjust,36 + adjust, 60 + adjust);
}
//! [1]//! [2]
QPainterPath Mouse::shape() const
{QPainterPath path;path.addRect(-10, -20, 20, 40);return path;
}
//! [2]//! [3]
void Mouse::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{// Bodypainter->setBrush(color);painter->drawEllipse(-10, -20, 20, 40);// Eyespainter->setBrush(Qt::white);painter->drawEllipse(-10, -17, 8, 8);painter->drawEllipse(2, -17, 8, 8);// Nosepainter->setBrush(Qt::black);painter->drawEllipse(QRectF(-2, -22, 4, 4));// Pupilspainter->drawEllipse(QRectF(-8.0 + mouseEyeDirection, -17, 4, 4));painter->drawEllipse(QRectF(4.0 + mouseEyeDirection, -17, 4, 4));// Earspainter->setBrush(scene()->collidingItems(this).isEmpty() ? Qt::darkYellow : Qt::red);painter->drawEllipse(-17, -12, 16, 16);painter->drawEllipse(1, -12, 16, 16);// TailQPainterPath path(QPointF(0, 20));path.cubicTo(-5, 22, -5, 22, 0, 25);path.cubicTo(5, 27, 5, 32, 0, 30);path.cubicTo(-5, 32, -5, 42, 0, 35);painter->setBrush(Qt::NoBrush);painter->drawPath(path);
}
//! [3]//! [4]
void Mouse::advance(int step)
{if (!step)return;
//! [4]// Don't move too far away
//! [5]QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0));if (lineToCenter.length() > 150) {qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length());if (lineToCenter.dy() < 0)angleToCenter = TwoPi - angleToCenter;angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2);if (angleToCenter < Pi && angleToCenter > Pi / 4) {// Rotate leftangle += (angle < -Pi / 2) ? 0.25 : -0.25;} else if (angleToCenter >= Pi && angleToCenter < (Pi + Pi / 2 + Pi / 4)) {// Rotate rightangle += (angle < Pi / 2) ? 0.25 : -0.25;}} else if (::sin(angle) < 0) {angle += 0.25;} else if (::sin(angle) > 0) {angle -= 0.25;
//! [5] //! [6]}
//! [6]// Try not to crash with any other mice
//! [7]QList<QGraphicsItem *> dangerMice = scene()->items(QPolygonF()<< mapToScene(0, 0)<< mapToScene(-30, -50)<< mapToScene(30, -50));foreach (QGraphicsItem *item, dangerMice) {if (item == this)continue;QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0));qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length());if (lineToMouse.dy() < 0)angleToMouse = TwoPi - angleToMouse;angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2);if (angleToMouse >= 0 && angleToMouse < Pi / 2) {// Rotate rightangle += 0.5;} else if (angleToMouse <= TwoPi && angleToMouse > (TwoPi - Pi / 2)) {// Rotate leftangle -= 0.5;
//! [7] //! [8]}
//! [8] //! [9]}
//! [9]// Add some random movement
//! [10]if (dangerMice.size() > 1 && (qrand() % 10) == 0) {if (qrand() % 1)angle += (qrand() % 100) / 500.0;elseangle -= (qrand() % 100) / 500.0;}
//! [10]//! [11]speed += (-50 + qrand() % 100) / 100.0;qreal dx = ::sin(angle) * 10;mouseEyeDirection = (qAbs(dx / 5) < 1) ? 0 : dx / 5;setRotation(rotation() + dx);setPos(mapToParent(0, -(3 + sin(speed) * 3)));
}
//! [11]

在这里插入图片描述

这个函数 返回的是 这个自定义的 item 外包围的矩形框 碰撞检测 以及其他的都是根据这个矩形框的大小来判断的

在这里插入图片描述

这个几个变量 在构造函数里 都给赋了初始值
在这里插入图片描述
角度 0 速度0 眼睛的方向0 随机颜色 随机的角度

刚才是 我还以为 这个老鼠是图片 没想到 是paint 画出来的
在这里插入图片描述

这个注释 很清楚了
身体 眼睛 鼻子 耳朵 尾巴 等等等
画椭圆 圆形 曲线 图形叠加构成的小老鼠
在这里插入图片描述

咱们看一下 老鼠怎么跑动的

这个函数就是 在 mian 里面 用 定时器来调动的
在这里插入图片描述

这里面有一些 数学知识 sin cos 角度 啥的 不用细看 我也看不太懂

上面的注释说了 不能让老鼠跑太远

如果老鼠 和 scene 的(0,0) 也就是 场景 中心的 距离 大于 150 就要 做一些处理了

lineToCenter.length() 内部实现就是用 两点直线距离公式算的
在这里插入图片描述

下面写的我也没细看 没看太懂 就是让他旋转个角度 ,不让他向外跑就行

碰撞检测

场景里面 提供了个碰撞检测的 函数
在这里插入图片描述
在这里插入图片描述
返回与项冲突的所有项的列表。冲突是通过调用QGraphicsItem::collidesWithItem()来确定的;碰撞检测由模式决定。默认情况下,形状与项目相交或包含在项目形状内的所有项目都将返回。
项目按递减堆叠顺序返回(即,列表中的第一项是最上面的项,最后一项是最下面的项)。

当老鼠碰到其他老鼠 就把耳朵变为 红色

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

找 范围 -30 50 里面所有的 item(老鼠)
如果 找到了 其他的老鼠
让他旋转个角度
在这里插入图片描述
在这里插入图片描述
增加一些随机移动的元素

在这里插入图片描述

这里就是根据上面 算的角度 和 位置 让小老鼠 动起来

没了 到这里就结束了 跑动的小老鼠 用这套框架 轻松的就完成了
在这里插入图片描述

这篇关于Qt 图形视图框架碰撞检测 官方Demo 移动的小老鼠的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/197794

相关文章

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

我在移动打工的日志

客户:给我搞一下录音 我:不会。不在服务范围。 客户:是不想吧 我:笑嘻嘻(气笑) 客户:小姑娘明明会,却欺负老人 我:笑嘻嘻 客户:那我交话费 我:手机号 客户:给我搞录音 我:不会。不懂。没搞过。 客户:那我交话费 我:手机号。这是电信的啊!!我这是中国移动!! 客户:我不管,我要充话费,充话费是你们的 我:可是这是移动!!中国移动!! 客户:我这是手机号 我:那又如何,这是移动!你是电信!!

数据治理框架-ISO数据治理标准

引言 "数据治理"并不是一个新的概念,国内外有很多组织专注于数据治理理论和实践的研究。目前国际上,主要的数据治理框架有ISO数据治理标准、GDI数据治理框架、DAMA数据治理管理框架等。 ISO数据治理标准 改标准阐述了数据治理的标准、基本原则和数据治理模型,是一套完整的数据治理方法论。 ISO/IEC 38505标准的数据治理方法论的核心内容如下: 数据治理的目标:促进组织高效、合理地

数据视图(AngularJS)

<!DOCTYPE html><html ng-app="home.controller"><head><meta charset="utf-8"><title>数据视图</title><link href="page/common/css/bootstrap.min.css" rel="stylesheet"><script src="page/common/js/angular.js"></

ZooKeeper 中的 Curator 框架解析

Apache ZooKeeper 是一个为分布式应用提供一致性服务的软件。它提供了诸如配置管理、分布式同步、组服务等功能。在使用 ZooKeeper 时,Curator 是一个非常流行的客户端库,它简化了 ZooKeeper 的使用,提供了高级的抽象和丰富的工具。本文将详细介绍 Curator 框架,包括它的设计哲学、核心组件以及如何使用 Curator 来简化 ZooKeeper 的操作。 1

【Kubernetes】K8s 的安全框架和用户认证

K8s 的安全框架和用户认证 1.Kubernetes 的安全框架1.1 认证:Authentication1.2 鉴权:Authorization1.3 准入控制:Admission Control 2.Kubernetes 的用户认证2.1 Kubernetes 的用户认证方式2.2 配置 Kubernetes 集群使用密码认证 Kubernetes 作为一个分布式的虚拟