2
\$\begingroup\$

I'm reading the book LibGDX game development by example and the author tends to follow a pattern like

 public class MyGame extends Game {
      @Override 
      public void create() {
          setScreen(new GameScreen(this));   
      } 
      ...
 }


 public class GameScreen extends ScreenAdapter {
     private Viewport viewport;
     private Camera camera;
     private final MyGame myGame;

     // code omitted for brevity

     public GameScreen(MyGame myGame) {
         this.myGame = myGame; 
     }

     @Override 
     public void show() {
         camera = new OrthographicCamera();
         camera.position.set(WORLD_WIDTH / 2, WORLD_HEIGHT / 2, 0);
         camera.update();
         viewport = new FitViewport(WORLD_WIDTH, WORLD_HEIGHT, camera);
         ...
     }  

It seems to me that creating a new camera and viewport in the show() method is not correct, as it would create new objects every time the screen becomes active (eg when the game has multiple screen and the user can switch between them). So my questions:

  • Am I correct in my reasoning? Should the camera and the viewport be created in the GameScreen class constructor?
  • Would it be possible/advisable to have just a single camera and viewport shared by all screens?
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

TL;DR

Create viewports separate from your screens and simply supply them as parameters wherever needed (i.e. your point 2).


There is no "correct" way to do it design wise per-se but if we go a bit deeper and start to think about garbage collection (GC) this is not good design at all. Realistically you should probably have 2 viewports:

  1. Game: Used to render your game.
  2. UI: Used to render your UI separate from your game.

These should be initialized separate from your screens and then passed into your screens as parameters of some form (new GameScreen(uiViepwort, gameViepwort)). This means that you limit GC by only creating these once during the entire lifecycle of your game.

If you for some reason need separate viewports / cameras per screen you should create it in the constructor for the same reason mentioned above.

You should however update the state of these objects in the show() method - not in the constructor - to ensure that the state is updated every time you show the screen to the user.

But then why put it in the show method in the first place?

The reason I used to do this was just a misunderstanding of the framework. As you may (or may not) know you have to put all initialization logic into or after your create() method of your game. To understand why let's say you decided to create 2 viewports and pass them into your screens as parameters. You might do something like this:

public class MyGame extends Game {
    /*Game is a constant size*/
    private final Viepwort game = new FitViewport(1920, 1080);
    /*UI stretches to fill the screen*/
    private final Viepwort ui = new StretchViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

    @Overrite
    public void create() {
        setScreen(new GameScreen(this, game, ui));  
    }
}

This will crash the game. Can you spot the bug? We are using Gdx.graphics before it is initialized! Gdx.graphics is initialized just before create() is called, but the viewports are created before that! Things like this just led me to assume that I should initialize all variables in the show() method as well, even though I don't have to.

Slight pet peeve

Please don't do this:

camera = new OrthographicCamera();
camera.position.set(WORLD_WIDTH / 2, WORLD_HEIGHT / 2, 0);
camera.update();
viewport = new FitViewport(WORLD_WIDTH, WORLD_HEIGHT, camera);

This is equivalent to doing this:

viewport = new FitViewport(WORLD_WIDTH, WORLD_HEIGHT);
viewport.apply(true); // true = center camera

Viewport creates its own camera, you don't have to create one yourself unless you're going to use a camera that isn't OrthographicCamera.

\$\endgroup\$
4
  • \$\begingroup\$ Thanks, that makes more sense. Still, I'm curious to why would you need two viewports, one for the ui and one for the game. After all the world size isn't going to chenge between game and menu, is it? \$\endgroup\$
    – Persson
    Jul 14, 2017 at 12:30
  • \$\begingroup\$ @Persson No but if you move the game camera you want the UI to follow the screen. The easiest way to implement this is to have one separate viewport (camera) for the UI that you never move and that is used to render the UI. Since the camera never moved the UI never moves. \$\endgroup\$
    – Charanor
    Jul 14, 2017 at 12:38
  • \$\begingroup\$ @Persson No problem. If this answer answered your question please click the "tick" box underneath the voting arrows to accept it so future users can see that it helped you. \$\endgroup\$
    – Charanor
    Jul 14, 2017 at 13:17
  • \$\begingroup\$ Yes of course, I was waiting to see if some other answer appears. \$\endgroup\$
    – Persson
    Jul 14, 2017 at 14:10

You must log in to answer this question.

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