QT: не может установить положение объекта в главном окне даже после static_cast - PullRequest
0 голосов
/ 06 июня 2018

Я играю в небольшую игру, и я хочу, чтобы мой враг в игре одновременно двигался и порождал пули.

Пока мой враг может двигаться и порождать пули автоматически, но проблемав том, что

моя пуля не может следовать за движением противника и появляться в другой начальной точке противника.

Чтобы быть более точным,

Я хочу поймать само положение врага каждый раз, когда враг порождает пулю.Однако я не могу установить свою пулю динамически.

Теперь я проектирую функцию перемещения врага ( врага () ) и функцию появления пули ( MakeBall () ) отдельно.И я установил свой таймер для каждой функции в своем конструкторе главного окна, чтобы вызывать функцию автоматически каждый раз в окне.

Мои попытки и мысли на данный момент:

  • Мой враг - объект класса Enemy, но я статически привел этот объект к QGraphicsPixmapItem в конструкторе главного окна, так что я подумалдолжен иметь возможность использовать врага как QGraphicsPixmapItem.Однако, когда я пытаюсь сделать что-то вроде врага-> х () в моей функции MakeBall (), компилятор принудительно завершился.
  • Я посылаю позицию противника в качестве аргумента функции MakeBall, такчто пуля может устанавливать Pos в самом положении противника.Однако компилятор говорит, что это недопустимая инициализация неконстантной ссылки типа 'int &' из значения r типа int.
  • Я посылаю QGraphicsPixmapItem * врага в качестве аргумента функции MakeBall и использую врага->x (), чтобы поймать свою позицию, однако, в конечном итоге он даже не порождает никакой пули, что означает, что функция MakeBall никогда не вызывается успешно.

Любой обмен или совет будет выше благодарности.Большое спасибо.

main window.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"


MainWindow::MainWindow(QWidget *parent):
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    enemyMoveTimer(new QTimer),
    balldrop(new QTimer),
    makeballtimer(new QTimer)
{ 
    ui->setupUi(this);
    //scene
    scene = new QGraphicsScene(0, 0, 1050, 600);
    //view
    view = new QGraphicsView;
    view ->setScene(scene);
    setCentralWidget(view);

    //enemy
    Enemy * enemy = new Enemy();
    enemy->setPixmap(QPixmap(QPixmap(":/img/ghost.gif").scaled(100,100)));
    enemy->setPos(0,0);
    scene->addItem(static_cast<QGraphicsPixmapItem*>(enemy));

    enemyMoveTimer->start(100);
    enemy->connect(enemyMoveTimer, SIGNAL(timeout()), enemy, SLOT(enemyMove()));

    //enemy's bullet
    makeballtimer->start(1000);
    //int & x=enemy->x();
    //connect(makeballtimer, SIGNAL(timeout()), this, SLOT(MakeBall(int & x)));
    connect(makeballtimer, SIGNAL(timeout()), this, SLOT(MakeBall(QGraphicsPixmapItem * enemy)));

}


void MainWindow::MakeBall(QGraphicsPixmapItem * enemy)
{
    EnemyBullet * ball = new EnemyBullet();
    ball->setPixmap(QPixmap(":/img/yellowblankball.png").scaled(50, 30));

    ball->setPos(enemy->x()+50, 100);//the problem is here

    balldrop->start(100);
    ball->connect(balldrop, SIGNAL(timeout()), ball, SLOT(fall()));
    scene->addItem(static_cast<QGraphicsPixmapItem*>(ball));
}

MainWindow::~MainWindow()
{
    delete ui;
}

main window.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsPixmapItem>
#include <QTimer>
#include <QKeyEvent>
#include <QtGui>

#include "enemy.h"
#include "ball.h"
#include "enemybullet.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

public slots:
    //virtual void MakeBall(int &x);
    virtual void MakeBall( QGraphicsPixmapItem * enemy);
    //virtual void MakeBall();

private:
    Ui::MainWindow *ui;
    QGraphicsScene *scene;
    QTimer *enemyMoveTimer;
    QTimer *balldrop;
    QTimer *makeballtimer;
    QGraphicsItem *enemy;

    QGraphicsView * view;

};

#endif // MAINWINDOW_H

врагаbullet.cpp

#include "enemybullet.h"
#include <QTimer>
#include <QGraphicsScene>
#include <QList>

EnemyBullet::EnemyBullet()
{

}

void EnemyBullet::fall()
{
    setPos(x(), y() +10 );
}

враги Bullet.h

#ifndef ENEMYBULLET_H
#define ENEMYBULLET_H

#include <QObject>
#include <QGraphicsPixmapItem>
#include <QGraphicsScene>

class EnemyBullet: public QObject, public QGraphicsPixmapItem
{
    Q_OBJECT

public:
    EnemyBullet();

public slots:
    void fall();
};


#endif// ENEMYBULLET_H

врага.cpp (обрезается до необходимого. Он может фактически перемещаться по прямой линии слева направо и справа налево несколько раз. Поэтому мы не можем подсчитать конкретное время для появления пули, потому чтокаждая позиция будет пересматриваться снова и снова.)

#include "enemy.h"
#include "enemybullet.h"
#include <QDebug>

Enemy::Enemy()
{

}

void Enemy::enemyMove()
{
      setPos(x() + 10,y());
}

врага.ч

#ifndef ENEMY_H
#define ENEMY_H

#include <QObject>
#include <QGraphicsPixmapItem>
#include <QTimer>


class Enemy:  public QObject,public QGraphicsPixmapItem
{
    Q_OBJECT

public:
    Enemy();

public slots:
    void enemyMove();
};

#endif // ENEMY_H

1 Ответ

0 голосов
/ 06 июня 2018

Как правило, вы хотите избежать смешивания кода пользовательского интерфейса со структурами данных, это значительно упрощает масштабирование, поэтому в вашем случае я бы действительно предложил создать резервные классы данных, которые будут содержать только данные, а затем пользовательский интерфейс.

ВашОднако проблема заключается в том, что вы смешиваете сигнал и слот - вы подключаете сигнал QTimer :: timeout () к вашему слоту, который принимает параметр типа QGraphicsPixmapItem *.Хотя это компилируется, я думаю, что по крайней мере в режиме отладки вы получите сообщение о том, что что-то вроде сигнала и слоты не совместимы.Гораздо лучше использовать современный стиль соединения, например:

 connect(makeballtimer, &QTimer::timeout, this, &MainWindow::MakeBall);

Поскольку эта запись не будет работать уже во время компиляции.

Я предлагаю вам сделать следующее: создать классы модели (или структуры, это действительно зависит от вас), который будет содержать только данные, связанные с каждым элементом;например:

struct Enemy {
    QPoint position;
};

struct BulletModel {
    std::shared_ptr<Enemy> enemy;
    QPoint position;
};

Ваш список врагов будет сохранен как вектор std::shared_ptr, чтобы обеспечить управление их временем жизни:

std::vector<std::shared_ptr<Enemy>> m_enemies;

Затем вы можете создать врага и пулю:

auto enemy = std::make_shared<EnemyModel>();
auto bullet = std::make_shared<BulletModel>();
bullet->enemy = enemy;

Затем вы можете создавать виджеты, которые будут использовать модели для рисования элементов на своих местах.

...