2 个 QGraphicsPixmapItems 之间的 QT 冲突检测
QT collision detection between 2 QGraphicsPixmapItems
链接到项目 有趣的部分应该在游戏引擎.cpp的"launchSplash"功能和splashanimation中.cpp
游戏在可接受的是随机创建气泡。玩家的工作是用水滴射击气泡。水滴从游戏屏幕的中间底部发射。网格仅用于调试,稍后将消失,但它使可视化区域更容易。
气泡通过向它们发射水滴来破坏,但当水滴击中气泡或游戏的上边界时,水滴会消失。水滴射向鼠标点击的方向。
我正在尝试为基本的泡泡射击游戏创建碰撞检测,但我不确定如何以整洁的方式检测碰撞。
游戏板看起来像这个游戏板,水滴从屏幕的中间底部射到光标的方向。
最终我会让水滴从墙上弹起,但目前我对弄清楚如何首先检测碰撞感到蔑视。
游戏板是 500x600 单位(宽 x 高(,因此水滴射击的点是 (250, 600(。
当水滴被射出时,我使用
void GameEngine::launchSplash(int clickX, int clickY){
// <my long method of calculating the coordinates for the water drop's path>
graphicalGameBoard_.animateSplash(graphicalGameBoard_.width()/2, graphicalGameBoard_.height(), xDestination, yDestination);
}
xDestination
和yDestionation
的地方是水滴如果畅通无阻地移动最终会到达的地方。水滴最终会达到 x=0/x=500 和/或 y=0/y=600,但我认为这无关紧要。
气泡被添加到游戏板上
board_.clear();
for(int y = 0; y < HEIGHT; ++y)
{
std::vector< std::shared_ptr<Bubble> > row;
for(int x = 0; x < WIDTH; ++x)
{
std::shared_ptr<Bubble> newBubble = nullptr;
// There will be bubbles only in the top 3/4 of the board only in the middle
// (i.e. not in the first two and last two columns).
if (y < HEIGHT*3/4 && x > 1 && x < WIDTH-2)
{
// Generate random numbers using the enumearation type defined in
// file bubble.hh. The value COLOR_COUNT is used to represent no bubble.
std::uniform_int_distribution<int> distribution(RED,COLOR_COUNT);
// If you want no empty squares, change the initialization to:
// std::uniform_int_distribution<int> distribution(RED,BLUE);
Color color = static_cast<Color>(distribution(randomEngine_));
if(color != COLOR_COUNT) {
newBubble = std::make_shared<Bubble>(x, y, color);
}
}
row.push_back(newBubble);
}
board_.push_back(row);
}
在画板和水滴射向气泡的gameengine.cpp
中。
水滴是用
SplashAnimation::SplashAnimation(GameBoard* scene, QPointF startPoint, QPointF endPoint):
QVariantAnimation(0),
scene_(scene),
item_()
{
scene_->addItem(&item_);
// The animation runs for the given duration and moves the splash
// smoothly from startpoint to endpoint.
setDuration(2000);
setKeyValueAt(0, QPointF(startPoint));
setKeyValueAt(1, QPointF(endPoint));
}
我认为有两种方法可以做到这一点:内置的QT碰撞检测或进行单独的计算。我无法使用QT碰撞,我手动检测碰撞的尝试效果不佳。
我已经有一个用于检测某些单元格处的气泡对象的功能,但它在列/行中而不是原始坐标 (500x600(。
std::shared_ptr<Bubble> GameEngine::bubbleAt(int x, int y) const
{
if (0 <= x and x < WIDTH and 0 <= y and y < HEIGHT){
return board_.at(y).at(x);
}
else{
return nullptr;
}
}
编辑:目前我正在尝试做这样的事情,但我担心它会对游戏来说有点沉重,因为它迭代了这么多(或不迭代?
for (int i = 0; i<600;++i)
{
xfract = (xDestination+250.0)/600.0;
yfract = (600.0-yDestination)/600.0;
xStep = xfract*i;
yStep = yfract*i;
if (xStep >= 50){
thisX = xStep/50-5;
}else{
thisX=5;
}
if (yStep >= 50){
thisY = 11-yStep/50 + 1;
}else{
thisY = 11;
}
thisX = abs(thisX);
if (bubbleAt(thisX, thisY)!=nullptr){
endX = xfract*i;
endY = yfract*i;
i = 600;
std::cout << "collision at x: "<<thisX<< " y: "<<thisY<<std::endl;
std::cout << "collision at x: "<<xStep<< " y: "<<yStep<<std::endl;
std::cout << graphicalGameBoard_.width() << " " << graphicalGameBoard_.height()<<std::endl;
removeBubble(thisX, thisY);
graphicalGameBoard_.removeBubble(thisX, thisY);
endY = 600-endY;
}
}
graphicalGameBoard_.animateSplash(graphicalGameBoard_.width()/2, graphicalGameBoard_.height(), endX, endY);
我正在尝试将步骤分成小部分,并检查当前步骤中是否有气泡,直到水滴到达终点或找到气泡。
在计算方面,这仅适用于我唯一的一侧,但是动画偏离了标记,并且由于某种原因,右侧(x>250(碰撞检测根本不起作用(它在右侧不可能的位置击中看似随机的气泡(。
编辑^2:以下是我尝试过的事情,以便与QT的实际碰撞检测一起使用:
在飞溅动画.cpp中,使用
SplashAnimation::SplashAnimation(GameBoard* scene, QPointF startPoint, QPointF endPoint):
QVariantAnimation(0),
scene_(scene),
item_()
{
scene_->addItem(&item_);
// The animation runs for the given duration and moves the splash
// smoothly from startpoint to endpoint.
setDuration(2000);
setKeyValueAt(0, QPointF(startPoint));
setKeyValueAt(1, QPointF(endPoint));
}
SplashAnimation::~SplashAnimation()
{
scene_->removeItem(&item_);
}
void SplashAnimation::updateCurrentValue(QVariant const& value)
{
item_.setPos(value.toPointF());
}
其中场景是 QGraphicsScene,this
的父级包含气泡。
我已经在游戏板上尝试过这个.cpp(气泡和动画的父级(和飞溅.cpp(为水滴制作动画(,但两者都给了我相同的编译错误。
QGraphicsItem::QGraphicsItem();
给
错误:无法调用构造函数?QGraphicsItem::QGraphicsItem?直接 [-允许] QGraphicsItem::QGraphicsItem((; ^
QList<QGraphicsItem *> list = collidingItems() ;
给error: ?collidingItems? was not declared in this scope
QList<QGraphicsItem *> list = collidingItems() ;
^
QList<QGraphicsItem *> list = QGraphicsItem::collidingItems() ;
给error: cannot call member function ?QList<QGraphicsItem*> QGraphicsItem::collidingItems(Qt::ItemSelectionMode) const? without object
QList<QGraphicsItem *> list = QGraphicsItem::collidingItems() ;
^
我也尝试添加参数,但我有心尝试的一切都没有比这更好的了。
在这个答案中,我将为您提供一些用于实现解决方案的建议:
-
避免使用以下指令,使用Qt最强大的元素之一并且事件循环完成工作的信号。
while (animations_.state() == QAbstractAnimation::Running) { QCoreApplication::processEvents(QEventLoop::AllEvents); }
-
QGraphicsScene
使用支持浮点的坐标,因此场景的坐标使用QPointF
进行处理。 -
使用上述方法,如果您要发送点信息,请使用
QPointF
而不是信号中的int, int
。 -
使用Qt提供的方法,例如:
if (0 <= clickPosition.x() and clickPosition.x() <= GRID_SIDE*WIDTH and 0 <= clickPosition.y() and clickPosition.y() <= GRID_SIDE*HEIGHT)
它可以简化为以下内容:
if(sceneRect().contains(event->scenePos()))
该实现的优点是它更具可读性
我不明白为什么你不能实现碰撞项目,也许是你的.pro的配置,
使用以下命令添加 gui 模块、核心和小部件
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
还要实现动画使用我之前的答案
完整的功能代码可以在以下链接中找到。
- QT Framewrok 和 Visual Studio - 图标冲突
- C++ / Qt:如何检测主机名或IP地址何时引用当前系统?
- 项目引用上的QT访问冲突
- 检测键按事件 - Qt C++上的插入符号 (^) 键
- 如何以及在何处使用带QT的Basler Cam实现opencv人脸检测代码
- 谷歌语音识别不起作用,因为冲突线程Qt C++
- Protobuf版本与Qt冲突
- HDF5 C++ Qt 冲突声明
- Qt安装程序框架:检测是否安装了VC++可再发行组件
- 2 个 QGraphicsPixmapItems 之间的 QT 冲突检测
- 如何从 DirectXTK (ToolKit) DirectX::Model 类获取所有顶点坐标以用于冲突检测
- 如何在Qt中检测Windows关闭或注销
- 如何在Qt中检测Windows事件
- 在 SFML 和冲突检测中使用磁贴
- Qt-如何检测换行后的行数增加
- 冲突检测期间发生堆栈溢出错误
- QT碰撞检测与自定义QGraphicsItem类
- 如何在Qt中检测全局按键顺序按下
- 文本游戏字符冲突检测问题
- 如何在qt中检测屏幕分辨率