Trying To Explain To Qt That I Need QGView To Follow My Player Sprite
-
Hello
I'm trying to understand the Code I need to write in order to get the View window to follow the Player Sprite when it moves.
I've not found a clear example that explains 'the thinking behind the code'. Browser searches have helped me cobble together some Code which Qt6 accepts (no error messages) but also it's not working.I'm working with player.h player.cpp, and the action's taking place in game.cpp .
I've got ItemChange code in Player.h :
#ifndef PLAYER_H #define PLAYER_H #include <QApplication> #include <QObject> #include <QGraphicsScene> #include <QGraphicsView> #include <QGraphicsItem> #include <QGraphicsPixmapItem> class Player : public QObject , public QGraphicsPixmapItem { Q_OBJECT public: Player(QGraphicsItem * parent=0); signals: void positionChanged(); protected: void keyPressEvent(QKeyEvent *event) override; QVariant itemChange(GraphicsItemChange change, const QVariant &value) override { if (change == ItemPositionChange && scene()) { emit positionChanged(); // Emit signal when position changes } return QGraphicsPixmapItem::itemChange(change, value); } }; #endif // PLAYER_H
and I've got a Lambda expression in game.cpp :
#include "game.h" #include <QImage> #include <QBrush> #include <QDebug> #include <QGraphicsTextItem> #include <QFont> Game::Game(QWidget * parent) : QGraphicsView(parent) { // Create the scene scene = new QGraphicsScene(); scene->setSceneRect(0,0,4800,2400); scene->setBackgroundBrush(QBrush(QImage(":/maps/map2.jpg"))); setScene(scene); // Create player and set its position player = new Player(); player->setPos(scene->width()/2, scene->height()/2); player->setFlag(QGraphicsItem::ItemIsFocusable); player->setFocus(); scene->addItem(player); QGraphicsView *view = new QGraphicsView(scene); view->setFixedSize(1500, 1200); view->centerOn(player); // Connect the players's positionChanged signal to recentre the view on the player QObject::connect(player, &Player::positionChanged, [this, view]() { view->centerOn(player); }); }
- Are these Code Blocks in the right place?
- Where am I hazy about what I need to say to the Programme to get the View following the Sprite around when it moves?
The only way I manage to learn is when I can look at Code and say it back to myself out loud, speaking in pseudocode, like a Director explaining the blocking in a Storyboard scene. Thanks for any help.
(I can be pretty thick sometimes, so please type slowly.)
Cheers -
@Grepur said in Trying To Explain To Qt That I Need QGView To Follow My Player Sprite:
QGraphicsView *view = new QGraphicsView(scene); view->setFixedSize(1500, 1200); view->centerOn(player);
What stands out to me is this:
Game
is aQGraphicsView
but you still create another independent instance ?!
Is there a reason to have two QGraphicViews? -
@Pl45m4 I'm not seeing where there are two instances of View that are the same, that one would be redundant. In one case, the Player sprite is made the focus, and in the Lambda expression, the View is intended to re-centre on the Player sprite each time the Player moves.
-
@Grepur said in Trying To Explain To Qt That I Need QGView To Follow My Player Sprite:
@Pl45m4 I'm not seeing where there are two instances of View that are the same, that one would be redundant. In one case, the Player sprite is made the focus, and in the Lambda expression, the View is intended to re-centre on the Player sprite each time the Player moves.
Your Game class is a QGraphicsView. In its constructor your create a new QGraphicsView that you then use.
That's the second instance @Pl45m4 wrote about.
-
@Grepur
Have you understood @Pl45m4 post above?In the constructor of
Game
, which itself is aQGraphicsView
,you create a new instance of aQGraphicsView
. That is the one used in theconnect()
, but you never show it and it cannot be referenced once the constructor returns. -
@SGaist Hi. (Sorry for the delays in responses; I'm being delayed 600 seconds between posts today.)
I have deleted the second call to QGraphicsView, and now the lambda expression gets an error message about 'view' being an undeclared identifier. I'm trying to figure-out what that means now.
Thanks for the pointer. -
One of the error messages was fixed by my adding QGraphicsView * view in game.h .
I'm still snagged on the other one. Very new to lambdas. Barely understand what's expected or what are the rules for what information to place between the brackets.
I generally understand the signal/slot objective: connect Player, Player's changed Position... But I'm just blanking out at that point. Something about pairing the Change with the View, but all my guesses about what to put within those braces are rubbish.
I just need to know how to think about it. I'm lost down in the Code instead of up in the Overview where everything would make sense... -
That's the issue with your architecture.
You should take a pen and paper and draw what you want to achieve and the structure you currently have.
Your Game class should not be a QGraphicsView. Make it a QWidget, set a layout on it and then add that
view
to it.
If you're not yet fluent with lambdas, then let them on the side for now and use a member function for your slot.
Don't make things needlessly complicated while you are learning. Make it work and then refactor and improve. -
The (simple) fix is quite easy:
Remove your secondview
and everything related to it. Then replace every call toview
withthis
(your actualGame
class)... There might be some other structural flaws asQGraphicsView
isn't the best place to hold all your game logic.
So you could split it into multiple classes likeGame
(backend) andGameView
(your graphics view).Assuming you're actually looking at the
Game
GraphicsView, change your lambda fromview->centerOn(player);
to
centerOn(player);
Also I wouldn't necessarily let your game/gameview hold a standard scene. You could introduce three classes (in addition to a
QMainWindow
for example):Game
GameView
(inheritingQGraphicsView
asGame
does now in your current situation)GameScene
(inheritingQGraphicsScene
, your game related custom scene, which you might want to modify other than having a standardQGraphicsScene
)