Qt Graphics:如何实现CQTank前后移动并解决位置重叠消失问题
嘿,我来帮你搞定CQTank的前后移动和碰撞消失的问题!下面分步骤给你讲清楚怎么实现:
一、实现CQTank的前后移动
要让坦克能前后移动,我们需要给它加上键盘事件处理,同时确保它能接收键盘焦点。
1. 先给CQTank启用键盘焦点
在CQTank的构造函数里加上两行代码,让它能捕获键盘输入:
CQTank::CQTank(QGraphicsScene *scena) { czolg = new CTank(); setPos(czolg->x, czolg->y); scena->addItem(this); // 关键:启用焦点,让坦克能接收键盘事件 setFlag(QGraphicsItem::ItemIsFocusable); setFocus(); }
2. 重写键盘事件处理函数
在CQTank类里添加keyPressEvent方法,处理前后移动的逻辑。这里给你两种方案:
方案A:简单的上下移动(不考虑坦克旋转)
如果你的坦克不需要旋转,直接用W/S或上下箭头控制前后:
void CQTank::keyPressEvent(QKeyEvent *event) { // 移动步长,你可以根据需求调整大小 const qreal moveStep = 6.0; switch(event->key()) { case Qt::Key_W: case Qt::Key_Up: // 向前移动(假设向上为前) setPos(x(), y() - moveStep); break; case Qt::Key_S: case Qt::Key_Down: // 向后移动 setPos(x(), y() + moveStep); break; default: // 别忘了调用父类的事件处理,保证其他事件正常工作 QGraphicsItem::keyPressEvent(event); break; } // 移动后立刻检查是否碰到水 checkCollisionWithWater(); }
方案B:基于旋转角度的前后移动(更真实)
如果你的坦克会旋转,前后移动应该跟着朝向走,这时候需要计算角度对应的偏移:
void CQTank::keyPressEvent(QKeyEvent *event) { const qreal moveStep = 6.0; switch(event->key()) { case Qt::Key_W: case Qt::Key_Up: { // 根据当前旋转角度计算移动方向 qreal angleRadian = qDegreesToRadians(rotation()); qreal dx = moveStep * qSin(angleRadian); qreal dy = -moveStep * qCos(angleRadian); setPos(x() + dx, y() + dy); break; } case Qt::Key_S: case Qt::Key_Down: { // 向后移动就是向前的反方向 qreal angleRadian = qDegreesToRadians(rotation()); qreal dx = -moveStep * qSin(angleRadian); qreal dy = moveStep * qCos(angleRadian); setPos(x() + dx, y() + dy); break; } default: QGraphicsItem::keyPressEvent(event); break; } checkCollisionWithWater(); }
二、实现CQTank碰到CQWater时消失
这里推荐用Qt自带的碰撞检测功能,比直接判断位置更准确(毕竟图形项的位置是中心点,碰撞检测会考虑你定义的boundingRect或shape)。
1. 添加碰撞检测函数
在CQTank类里写一个专门检查和水碰撞的函数:
void CQTank::checkCollisionWithWater() { // 获取所有和当前坦克碰撞的图形项 QList<QGraphicsItem*> collidingItems = this->collidingItems(); foreach(QGraphicsItem* item, collidingItems) { // 判断碰撞的是不是CQWater对象 if(dynamic_cast<CQWater*>(item)) { // 从场景中移除坦克并销毁 scene()->removeItem(this); delete this; return; } } }
2. 确保CQWater能被检测到
在CQWater的构造函数里加上一行,确保它参与碰撞检测:
CQWater::CQWater(QGraphicsScene *scena) { setPixmap(QPixmap(":/new/prefix1/images/woda.png")); setTransformOriginPoint(50,50); setRotation(180); woda = new CWater(); setPos(woda->x, woda->y); scena->addItem(this); // 让水对象能被碰撞检测到 setFlag(QGraphicsItem::ItemIsMovable, false); }
最后补充
记得在CQTank的头文件里声明这些新增的函数:
class CQTank : public QGraphicsItem { // ... 原有代码 ... protected: void keyPressEvent(QKeyEvent *event) override; private: void checkCollisionWithWater(); };
内容的提问来源于stack exchange,提问作者Badum
相关产品推荐
相关产品推荐

