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. Help in my 2d Qt game

Help in my 2d Qt game

Scheduled Pinned Locked Moved Unsolved Game Development
4 Posts 2 Posters 1.6k 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.
  • A Offline
    A Offline
    antonio_1985
    wrote on 22 Oct 2017, 13:44 last edited by
    #1

    Hi all,

    I'm having fun building a 2D game, but I'm hitting performance issue before that I even started :)

    My idea is basically to have a ground scenario as composition of tiles (set in a matrix).
    Then drawing the tiles to screen in the update loop as follows:

    • delete everything
    • iterate on the matrix
    • display the tile if it fits in the screen coordinate

    The problem I'm having is that my tiles are 45x15, and a full screen resolution is 1200x1000 which means:

    • (1200x1000) / (45x15) = 1777 tiles

    Drawing the 1777 tiles in a for loop takes between 15 and 20 msec, far too much for a 60 FPS.
    I'm simply drawing tiles into a QOpenGLWidget with the painter using the following code:

    painter->drawRect(target, *image);
    

    (I get exactly the same result when I use instead drawImage or drawPixmap, which is eventually what I want to have).

    Is there anyway I can speed up the drawRect (or any other draw functionality) to screen?
    Am I doing something completely wrong? Is not how I am supposed to draw the ground?

    I had the following two ideas but I think they are out of track:

    1. I wrote some code to aggregate ground images in bigger tiles (e.g. aggregate 10 tiles in a 450x150 image). That drastically improved performances, but then it would not work in future as I'm planning to have only the tiles around the character visible and the further away black/grayed out (imagine age of empires).

    2. I thought as well to have a not blank the screen and draw only the tiles that requires update but I will incur in two problems:
      ** when I scroll the screen I need to repaint everything anyway.
      ** if I have few units walking in the screen it is probably going to repaint everything anyway.

    What is the best way to approach my problem?

    Thanks in advance
    Antonio

    J 1 Reply Last reply 4 Nov 2017, 01:18
    0
    • A Offline
      A Offline
      antonio_1985
      wrote on 22 Oct 2017, 19:29 last edited by
      #2

      For the time being I did a composition of both option described above.
      As I got only one unit I'll deal with this problem later on.

      Scrolling is fast and paint loop is fast.

      I have few problems when the unit moves, I need to clean up the grounds "around" it as they don't repaint and if the unit was overflowing on that ground some "bits" stay on it.

      It looks cool, although not sure if it is the best solution.

      1 Reply Last reply
      0
      • A Offline
        A Offline
        antonio_1985
        wrote on 3 Nov 2017, 22:27 last edited by
        #3

        Just if somebody is wondering I tried to use qGraphicsView/qGraphicsScene/qGraphicsItem and the performance are even much much worse.

        I guess I must be doing something very wrong.
        I thought to make a game it would be possible at each frame (60fps) to clear the screen (make it all black) and then draw all my images (it didn't matter if they were 10000 images) but evidently not.

        Maybe opengl / transformer / shaders is the only way to go :(

        I'll let you know what I discover.

        1 Reply Last reply
        0
        • A antonio_1985
          22 Oct 2017, 13:44

          Hi all,

          I'm having fun building a 2D game, but I'm hitting performance issue before that I even started :)

          My idea is basically to have a ground scenario as composition of tiles (set in a matrix).
          Then drawing the tiles to screen in the update loop as follows:

          • delete everything
          • iterate on the matrix
          • display the tile if it fits in the screen coordinate

          The problem I'm having is that my tiles are 45x15, and a full screen resolution is 1200x1000 which means:

          • (1200x1000) / (45x15) = 1777 tiles

          Drawing the 1777 tiles in a for loop takes between 15 and 20 msec, far too much for a 60 FPS.
          I'm simply drawing tiles into a QOpenGLWidget with the painter using the following code:

          painter->drawRect(target, *image);
          

          (I get exactly the same result when I use instead drawImage or drawPixmap, which is eventually what I want to have).

          Is there anyway I can speed up the drawRect (or any other draw functionality) to screen?
          Am I doing something completely wrong? Is not how I am supposed to draw the ground?

          I had the following two ideas but I think they are out of track:

          1. I wrote some code to aggregate ground images in bigger tiles (e.g. aggregate 10 tiles in a 450x150 image). That drastically improved performances, but then it would not work in future as I'm planning to have only the tiles around the character visible and the further away black/grayed out (imagine age of empires).

          2. I thought as well to have a not blank the screen and draw only the tiles that requires update but I will incur in two problems:
            ** when I scroll the screen I need to repaint everything anyway.
            ** if I have few units walking in the screen it is probably going to repaint everything anyway.

          What is the best way to approach my problem?

          Thanks in advance
          Antonio

          J Offline
          J Offline
          JKSH
          Moderators
          wrote on 4 Nov 2017, 01:18 last edited by
          #4

          Hi @antonio_1985,

          The for-loop only draws one tile at a time, which is slow. To achieve a high frame rate, you need to let your program paint different parts of the screen in parallel.

          You don't need to micro-manage the screen clearing and repainting -- QGraphicsView can do that for you.

          @antonio_1985 said in Help in my 2d Qt game:

          Just if somebody is wondering I tried to use qGraphicsView/qGraphicsScene/qGraphicsItem and the performance are even much much worse.

          I recommend you build, run, and study the "40000 Chips" example. (Search Qt Creator for the examples)

          The key points are:

          • Make each ground tile an individual QGraphicsPixmapItem. (It might help to aggregate the tiles to bigger images)
          • Make your character sprite another QGraphicsPixmapItem.
          • Add all the ground tiles to your QGraphicsScene. You only need to do this once at startup, and you don't need to destroy them until your program quits.
          • For the Age of Empires-style fog-of-war, call QGraphicsView::setBackgroundBrush() once to make your background black. During the game, call setOpacity() to make the tiles around your character fully opaque, and make all the other tiles fully transparent. The transparent tiles will show the black background instead of the image.
          • To scroll, move your character sprite and call QGraphicsView::centerOn() to move the viewport.

          Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

          1 Reply Last reply
          1

          • Login

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