0
\$\begingroup\$

I am writing a C++ game using Qt. As this is the first time, I am trying to understand how the structure should be.

I have two objects derived from the type QGraphicsRectItem which appear as boxes on the screen, which will each represent a player. I want to make them move independently in response to key presses, with a different set of keys assigned to the motion of each object. These are added to a QGraphicsScene object, which is set by a QGraphicsView inherited object.

As only one of these can be focused at any given point of time, and thus respond to key press events, I have defined a function in a class which inherits from QGraphicsView (and is used as a view for viewing the scene) that receives all the key press events. Its constructor receives pointers to the two box objects, and sends the required information (by setting a variable) to the appropriate object through the pointer based on the key press.

I have a few questions regarding this:

  • Is QGraphicsRectItem (or QGraphicsItem) the correct class for creating such "objects"? I see that there is a QObject class, but I could not understand where it is meant to be used.
  • Sending pointers of the box objects to the constructor of the view during initialization doesn't seem right. What would be a more appropriate way to design this? The idea is that based on the key pressed, the corresponding box should respond. The problem is, how does this class access the object, unless it is declared inside it or passed as an argument?
  • Is there a better or more commonly used way to handle the requirement of different objects responding to different key presses, even if done simultaneously? I have seen suggestions for using Event filters, which would pass the event using postEvent. However, event filters send messages to objects of type QObject, which is not what I am currently using. Additionally, the question again arises - who would receive the key press events? How would it know about the existence of the box objects?

I have been reading about design patterns. Is there any particular pattern that would be suitable for this?

Thank you.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

QGraphicsItem is the correct base for things drawing pixels on screen, but that is a much tighter responsibility than "The model of the player's actions".

More traditionally, you would have something like

class GameObject : QObject
{
    void draw() { QRectF bounds = m_graphic->rect(); bounds.moveCenter(m_position); m_graphic->set_rect(bounds); }
    void update(std::chrono::duration delta_time) { do_update(delta_time); }
protected:
    virtual void do_update(std::chrono::duration delta_time) = 0;

    QGraphicsItem * m_graphic;
    QPointF m_position; // or 3d point
}

class Player : GameObject
{
    // event handlers
public:
    Player(QGraphicsScene & scene) : m_graphic(new PlayerGraphic) { scene.addItem(m_graphic); }
public slots:
    void keyPressEvent(QKeyEvent * event) { /* set movement direction */ }
private:
    void do_update(std::chrono::duration delta_time) { /* handle movement that occurs in this time step */ }
}

class PlayerGraphic : QGraphicsRectItem
{
    void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0) { /* art here*/ }
}
\$\endgroup\$
7
  • \$\begingroup\$ Thank you! I am still having a bit of difficulty understanding this. Could you please give an example (such as one based on the example in my question)? \$\endgroup\$
    – GoodDeeds
    Commented Feb 6, 2017 at 16:40
  • 1
    \$\begingroup\$ added some more detail \$\endgroup\$
    – Caleth
    Commented Feb 6, 2017 at 17:01
  • \$\begingroup\$ Thank you. If I have multiple players, would I have multiple objects of class Player? In that case, wouldn't it be the case that only one of them can be focused, and be able to respond to key presses? \$\endgroup\$
    – GoodDeeds
    Commented Feb 6, 2017 at 17:13
  • 1
    \$\begingroup\$ They will presumably respond to different sets of keys. You could have PlayerActions and a std::map<Qt::Key, PlayerAction> for each player, and keyPressEvent would check if the key is present in the map, then do the appropriate thing \$\endgroup\$
    – Caleth
    Commented Feb 6, 2017 at 17:27
  • \$\begingroup\$ E.g. {Qt::Key_Up, Player::MoveUp} for player 1 and {Qt::Key_W, Player::MoveUp} for player 2 \$\endgroup\$
    – Caleth
    Commented Feb 6, 2017 at 17:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .