C++ 将无父场景项放置在另一个场景项下

C++ 将无父场景项放置在另一个场景项下,c++,qt,rotation,qgraphicsview,qgraphicsscene,C++,Qt,Rotation,Qgraphicsview,Qgraphicsscene,在我的游戏中,我想从火箭发射器发射火箭。玩家将火箭发射器作为子项目。火箭队必须没有父母。我正试图定位火箭,使其背面与火箭发射器背面对齐(屏幕截图中玩家面向北方),并在其内部水平居中: 相反,我得到的是: 旋转也不正确(运行示例并移动鼠标光标以了解我的意思)。我的代码哪里出错了 #include <QtWidgets> QPointF moveBy(const QPointF &pos, qreal rotation, float distance) { retu

在我的游戏中,我想从火箭发射器发射火箭。玩家将火箭发射器作为子项目。火箭队必须没有父母。我正试图定位火箭,使其背面与火箭发射器背面对齐(屏幕截图中玩家面向北方),并在其内部水平居中:

相反,我得到的是:

旋转也不正确(运行示例并移动鼠标光标以了解我的意思)。我的代码哪里出错了

#include <QtWidgets>

QPointF moveBy(const QPointF &pos, qreal rotation, float distance)
{
    return pos - QTransform().rotate(rotation).map(QPointF(0, distance));
}

float directionTo(const QPointF &source, const QPointF &target) {
    QPointF toTarget(target.x() - source.x(), target.y() - source.y());
    float facingTarget = qRadiansToDegrees(atan2(toTarget.y(), toTarget.x())) + 90.0f;
    facingTarget = fmod(facingTarget, 360.0f);
    if(facingTarget < 0)
        facingTarget += 360.0f;
    return facingTarget;
}

class Controller : public QObject
{
public:
    Controller(QGraphicsScene *scene) :
        mScene(scene)
    {
        mPlayer = scene->addRect(0, 0, 25, 25, QPen(Qt::blue));
        mPlayer->setTransformOriginPoint(mPlayer->boundingRect().width() / 2, mPlayer->boundingRect().height() / 2);

        mRocketLauncher = scene->addRect(0, 0, 16, 40, QPen(Qt::green));
        mRocketLauncher->setParentItem(mPlayer);
        mRocketLauncher->setPos(mPlayer->boundingRect().width() * 0.9 - mRocketLauncher->boundingRect().width() / 2,
            -mRocketLauncher->boundingRect().height() * 0.3);

        mRocket = scene->addRect(0, 0, 16, 20, QPen(Qt::red));
        scene->installEventFilter(this);

        QGraphicsTextItem *playerText = scene->addText("Player");
        playerText->setPos(0, 100);
        playerText->setDefaultTextColor(Qt::blue);
        QGraphicsTextItem *rocketLauncherText = scene->addText("Rocket launcher");
        rocketLauncherText->setPos(0, 120);
        rocketLauncherText->setDefaultTextColor(Qt::green);
        QGraphicsTextItem *rocketText = scene->addText("Rocket");
        rocketText->setPos(0, 140);
        rocketText->setDefaultTextColor(Qt::red);
    }

    bool eventFilter(QObject *, QEvent *event) {
        if (event->type() == QEvent::GraphicsSceneMouseMove) {
            const QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent*>(event);
            mPlayer->setRotation(directionTo(mPlayer->sceneBoundingRect().center(), mouseEvent->scenePos()));

            qreal rocketX = mRocketLauncher->sceneBoundingRect().center().x() - mRocket->boundingRect().width() / 2;
            QPointF rocketPos(rocketX, 0);
            rocketPos = moveBy(rocketPos, mPlayer->rotation(), mRocketLauncher->boundingRect().height() - mRocket->boundingRect().height());
            mRocket->setPos(rocketPos);
            mRocket->setRotation(mPlayer->rotation());

            return true;
        }
        return false;
    }
private:
    QGraphicsScene *mScene;
    QGraphicsRectItem *mPlayer;
    QGraphicsRectItem *mRocketLauncher;
    QGraphicsRectItem *mRocket;
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QGraphicsView view;
    view.setMouseTracking(true);
    QGraphicsScene *scene = new QGraphicsScene;
    view.setScene(scene);

    Controller controller(scene);

    view.resize(300, 300);
    view.show();

    return app.exec();
}
#包括
QPointF moveBy(常量QPointF&pos、qreal旋转、浮动距离)
{
返回pos-QTransform().rotate(rotation).map(QPointF(0,距离));
}
浮点指向(常量QPointF和源、常量QPointF和目标){
QPointF toTarget(target.x()-source.x(),target.y()-source.y());
浮动面目标=qRadiansToDegrees(atan2(toTarget.y(),toTarget.x())+90.0f;
朝向目标=fmod(朝向目标,360.0f);
如果(朝向目标<0)
朝向目标+=360.0f;
回归目标;
}
类控制器:公共QObject
{
公众:
控制器(QGraphicscene*场景):
mScene(场景)
{
mPlayer=scene->addRect(0,0,25,25,QPen(Qt::blue));
mPlayer->setTransformOriginPoint(mPlayer->boundingRect().width()/2,mPlayer->boundingRect().height()/2);
mRocketLauncher=scene->addRect(0,0,16,40,QPen(Qt::green));
mRocketLauncher->setParentItem(mPlayer);
mRocketLauncher->setPos(mPlayer->boundingRect().width()*0.9-mRocketLauncher->boundingRect().width()/2,
-mRocketLauncher->boundingRect().height()*0.3);
mRocket=scene->addRect(0,0,16,20,QPen(Qt::red));
场景->安装事件过滤器(此);
QGraphicsTextItem*playerText=场景->添加文本(“播放器”);
playerText->setPos(01100);
playerText->setDefaultTextColor(Qt::蓝色);
QGraphicsTextItem*rocketLauncherText=场景->添加文本(“火箭发射器”);
rocketLauncherText->setPos(0,120);
rocketLauncherText->setDefaultTextColor(Qt::绿色);
QGraphicsTextItem*rocketText=场景->添加文本(“火箭”);
rocketText->setPos(0140);
rocketText->setDefaultTextColor(Qt::红色);
}
布尔事件过滤器(QObject*,QEvent*事件){
如果(事件->类型()==QEvent::GraphicsSceneMouseMove){
const Qgraphicscenemouseevent*mouseEvent=静态(事件);
mPlayer->setRotation(指向(mPlayer->sceneboundingdirect().center(),mouseEvent->scenePos());
qreal rocketX=mRocketLauncher->sceneboundingdirect().center().x()-mRocket->boundingdirect().width()/2;
QPointF rocketPos(rocketX,0);
rocketPos=moveBy(rocketPos,mPlayer->rotation(),mRocketLauncher->boundingRect().height()-mRocket->boundingRect().height());
mRocket->setPos(rocketPos);
mRocket->setRotation(mPlayer->rotation());
返回true;
}
返回false;
}
私人:
qgraphicscene*mScene;
QGraphicsRectItem*mPlayer;
QGraphicsRectItem*mRocketLauncher;
QGraphicsRectItem*mRocket;
};
int main(int argc,char*argv[])
{
QApplication应用程序(argc、argv);
QGraphicsView视图;
view.setMouseTracking(true);
Qgraphicscene*场景=新的Qgraphicscene;
视图.场景(场景);
控制器(场景);
视图。调整大小(300300);
view.show();
返回app.exec();
}
我们的想法是:

  • 设置两个项目的轮换
  • 获取发射器和火箭左下角在全局(场景)坐标中的位置
  • 移动火箭使正电子相等
  • 代码:


    回答得很好,谢谢!我已经澄清了我的问题的一部分,我注意到我没有提到,那就是:我如何在发射器内水平居中火箭?例如,如果将火箭的宽度减半:
    mRocket=scene->addRect(0,0,8,20,QPen(Qt::red))使用
    QPointF(mRocketLauncher->boundingRect().center().x(),mRocketLauncher->boundingRect().bottom())
    (对于发射器和火箭)似乎都有效。:)
    mPlayer->setRotation(directionTo(mPlayer->sceneBoundingRect().center(), 
                                     mouseEvent->scenePos()));
    mRocket->setRotation(mPlayer->rotation());
    QPointF launcherPos = mRocketLauncher->mapToScene(
      mRocketLauncher->boundingRect().bottomLeft());
    QPointF currentRocketPos = mRocket->mapToScene(
      mRocket->boundingRect().bottomLeft());
    mRocket->setPos(mRocket->pos() - currentRocketPos + launcherPos);