c++ - QT:即使在 static_cast 之后也无法在主窗口中设置对象的位置
问题描述
我正在制作一个小游戏,我希望游戏中的敌人同时移动并自动生成子弹。
到目前为止,我的敌人可以自动移动并产生子弹,但问题是
我的子弹无法跟随敌人的移动并在敌人的不同起点产生。
更加具体,
每次敌人产生子弹时,我都想抓住敌人的位置。但是,我不能动态设置我的子弹。
现在,我分别设计了移动敌人的函数(enemyMove())和生成子弹的函数(MakeBall())。我在我的主窗口构造函数中为每个函数设置了一个不同的计时器,以便在每个时间窗口自动调用该函数。
到目前为止我的尝试和想法:
- 我的敌人是 Enemy 类的对象,但我在主窗口构造函数中将此对象静态转换为 QGraphicsPixmapItem,所以我认为它应该能够将敌人用作 QGraphicsPixmapItem。但是,当我尝试在 MakeBall() 函数中执行诸如enemy- >x()之类的操作时,编译器强制结束。
- 我将敌人的位置作为参数发送给 MakeBall 函数,以便子弹可以在敌人的位置设置位置。但是,编译器说这是从“int”类型的右值对“int&”类型的非常量引用进行的无效初始化。
- 我将 QGraphicsPixmapItem *enemy 作为参数发送给 MakeBall 函数并使用enemy->x() 来捕捉它的位置,但是它最终甚至没有产生任何子弹,这意味着 MakeBall 函数从未成功调用。
任何分享或建议都将不胜感激。非常非常感谢你。
主窗口.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;
}
主窗口.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
敌人子弹.cpp
#include "enemybullet.h"
#include <QTimer>
#include <QGraphicsScene>
#include <QList>
EnemyBullet::EnemyBullet()
{
}
void EnemyBullet::fall()
{
setPos(x(), y() +10 );
}
敌人子弹.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());
}
敌人.h
#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
解决方案
通常,您希望避免将 UI 代码与数据结构混合,这样可以更容易扩展,因此在您的情况下,我真的建议创建仅包含数据和 UI 的支持数据类。
但是,您的问题是您正在混合信号和插槽-您正在将QTimer::timeout()信号连接到采用 type 参数的插槽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;
然后,您可以创建将使用模型将元素绘制到其位置的小部件。
推荐阅读
- json - 附上图片。我想知道突出显示的代码是做什么的
- apache-flink - flink 如何与 MySQL 交互以实现与 mysql 的 temporal join
- php - laravel 8 angular 11 子域中的 CORS 策略问题
- python - python 和 DRF :__init__() 缺少 2 个必需的位置参数:“代码”和“用户名”
- robocopy - Robocopy:如何查看失败的文件?
- material-ui - 为什么我们有多个 Material UI 的颜色声明?
- node.js - 在打包时将动态 tarball 流式传输到 s3
- node.js - 平均应用程序错误:无法从获取请求中获得响应
- python - 关于 sklearn cross_val_predict 方法的困惑
- bash - 带有grep的bash whileloop中的docker cmd