将无父场景项定位在另一个场景项下

Posted

技术标签:

【中文标题】将无父场景项定位在另一个场景项下【英文标题】:Position parentless scene item under another scene item 【发布时间】:2014-04-18 11:56:14 【问题描述】:

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

相反,我得到的是:

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

#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();

【问题讨论】:

【参考方案1】:

这个想法是:

    设置两个项目的旋转; 获取发射器和火箭左下角在全局(场景)坐标中的位置; 移动火箭以使 positinos 相等。

代码:

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);

【讨论】:

很好的答案,谢谢!我已经澄清了我注意到我没有提到的问题的一部分,那就是:我怎样才能使火箭在发射器内水平居中?例如,如果你将火箭的宽度减半:mRocket = scene-&gt;addRect(0, 0, 8, 20, QPen(Qt::red)); 使用QPointF(mRocketLauncher-&gt;boundingRect().center().x(), mRocketLauncher-&gt;boundingRect().bottom())(对于发射器和火箭)似乎有效。 :)

以上是关于将无父场景项定位在另一个场景项下的主要内容,如果未能解决你的问题,请参考以下文章

如何在另一个视图控制器中访问 SpriteKit 场景的变量?

14流程分析法

如何在特定标签栏项而不是其他项下添加标题

我们在sputter中的dev依赖项下添加的内容

使用 pod 安装 Smooch 未在依赖项下列出

VB6读取注册表项下的所有值