Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Game Development
  4. Trying To Explain To Qt That I Need QGView To Follow My Player Sprite
QtWS25 Last Chance

Trying To Explain To Qt That I Need QGView To Follow My Player Sprite

Scheduled Pinned Locked Moved Unsolved Game Development
15 Posts 4 Posters 456 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • G Offline
    G Offline
    Grepur
    wrote on last edited by
    #1

    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);
    
        });
    
    }
    
    
    1. Are these Code Blocks in the right place?
    2. 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

    JonBJ Pl45m4P 2 Replies Last reply
    0
    • G Grepur

      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);
      
          });
      
      }
      
      
      1. Are these Code Blocks in the right place?
      2. 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

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #2

      @Grepur
      What is currently "not working"?
      Although I have not looked at it in any detail, it seems reasonable to me.

      G 1 Reply Last reply
      0
      • G Grepur

        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);
        
            });
        
        }
        
        
        1. Are these Code Blocks in the right place?
        2. 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

        Pl45m4P Offline
        Pl45m4P Offline
        Pl45m4
        wrote on last edited by
        #3

        @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 a QGraphicsView but you still create another independent instance ?!
        Is there a reason to have two QGraphicViews?


        If debugging is the process of removing software bugs, then programming must be the process of putting them in.

        ~E. W. Dijkstra

        G 1 Reply Last reply
        1
        • JonBJ JonB

          @Grepur
          What is currently "not working"?
          Although I have not looked at it in any detail, it seems reasonable to me.

          G Offline
          G Offline
          Grepur
          wrote on last edited by
          #4

          @JonB Hi. The Player sprite moves without the View following it; it doesn't keep the Player sprite in the centre of the View. The Player sprite can move out of the View; the View doesn't move.

          SGaistS 1 Reply Last reply
          0
          • G Grepur

            @JonB Hi. The Player sprite moves without the View following it; it doesn't keep the Player sprite in the centre of the View. The Player sprite can move out of the View; the View doesn't move.

            SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            @Grepur @Pl45m4 is correct, you have created a secondary and invisible view that you center your sprite on. So you are not using the one you think.

            I would recommend reconsidering your architecture.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            G 1 Reply Last reply
            1
            • Pl45m4P Pl45m4

              @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 a QGraphicsView but you still create another independent instance ?!
              Is there a reason to have two QGraphicViews?

              G Offline
              G Offline
              Grepur
              wrote on last edited by
              #6

              @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.

              SGaistS JonBJ 2 Replies Last reply
              0
              • G Grepur

                @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.

                SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by SGaist
                #7

                @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.

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                G 1 Reply Last reply
                1
                • G Grepur

                  @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.

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by
                  #8

                  @Grepur
                  Have you understood @Pl45m4 post above?

                  In the constructor of Game, which itself is a QGraphicsView ,you create a new instance of a QGraphicsView. That is the one used in the connect(), but you never show it and it cannot be referenced once the constructor returns.

                  1 Reply Last reply
                  0
                  • SGaistS SGaist

                    @Grepur @Pl45m4 is correct, you have created a secondary and invisible view that you center your sprite on. So you are not using the one you think.

                    I would recommend reconsidering your architecture.

                    G Offline
                    G Offline
                    Grepur
                    wrote on last edited by
                    #9

                    @SGaist I don't know what 'reconsidering my architecture' means. I need to know how to see the situation, how to think about it, so that I'm clear on what needs to be done, and then I can do it correctly.

                    1 Reply Last reply
                    0
                    • SGaistS SGaist

                      @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.

                      G Offline
                      G Offline
                      Grepur
                      wrote on last edited by
                      #10

                      @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.

                      1 Reply Last reply
                      0
                      • G Offline
                        G Offline
                        Grepur
                        wrote on last edited by
                        #11

                        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...

                        1 Reply Last reply
                        0
                        • SGaistS Offline
                          SGaistS Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on last edited by
                          #12

                          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.

                          Interested in AI ? www.idiap.ch
                          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                          G 1 Reply Last reply
                          0
                          • SGaistS SGaist

                            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.

                            G Offline
                            G Offline
                            Grepur
                            wrote on last edited by
                            #13

                            @SGaist Thank you. I'll do my best to put that advice to work.

                            Pl45m4P 1 Reply Last reply
                            0
                            • G Grepur

                              @SGaist Thank you. I'll do my best to put that advice to work.

                              Pl45m4P Offline
                              Pl45m4P Offline
                              Pl45m4
                              wrote on last edited by Pl45m4
                              #14

                              @Grepur

                              The (simple) fix is quite easy:
                              Remove your second view and everything related to it. Then replace every call to view with this (your actual Game class)... There might be some other structural flaws as QGraphicsView isn't the best place to hold all your game logic.
                              So you could split it into multiple classes like Game (backend) and GameView (your graphics view).

                              Assuming you're actually looking at the Game GraphicsView, change your lambda from

                              view->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 (inheriting QGraphicsView as Game does now in your current situation)
                              • GameScene (inheriting QGraphicsScene, your game related custom scene, which you might want to modify other than having a standard QGraphicsScene)

                              If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                              ~E. W. Dijkstra

                              G 1 Reply Last reply
                              2
                              • Pl45m4P Pl45m4

                                @Grepur

                                The (simple) fix is quite easy:
                                Remove your second view and everything related to it. Then replace every call to view with this (your actual Game class)... There might be some other structural flaws as QGraphicsView isn't the best place to hold all your game logic.
                                So you could split it into multiple classes like Game (backend) and GameView (your graphics view).

                                Assuming you're actually looking at the Game GraphicsView, change your lambda from

                                view->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 (inheriting QGraphicsView as Game does now in your current situation)
                                • GameScene (inheriting QGraphicsScene, your game related custom scene, which you might want to modify other than having a standard QGraphicsScene)
                                G Offline
                                G Offline
                                Grepur
                                wrote on last edited by
                                #15

                                @Pl45m4 Thank you for those ideas. I'm feeling less wandering-the-wilderness now, thanks to the advice I'm getting here.

                                1 Reply Last reply
                                0

                                • Login

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • Users
                                • Groups
                                • Search
                                • Get Qt Extensions
                                • Unsolved