Push Me Pull You — Our Camera

1.5M ratings
277k ratings

See, that’s what the app is perfect for.

Sounds perfect Wahhhh, I don’t wanna

Our Camera

I recently watched Itay Keren’s GDC talk about camera design for 2D games. It’s really good, you should watch it too if you like that sort of thing. In the talk, Itay takes a comprehensive look at different camera techniques, explains what they are good for, and shows how they work with animated screenshots. Watching it inspired me to share how the PMPY camera works.

During the first few months of development, the camera was something we didn’t think about at all. We originally had a fixed camera that showed the whole court. You could see everything at all times, and we assumed we were finished. We had made a perfectly fine camera first try, and that was that.

image

PMPY one month in - I guess we were only targeting square screens.

As time went on we started getting frustrated that our characters looked so small, and that large parts of the screen were completely empty. In hindsight, it’s obvious that our camera was to blame, but the solution wasn’t obvious to us at all. In desperation we actually tried making our court very small, just to zoom everything in. It took us a long time to realise that a dynamic camera might help.

Once we decided to create a dynamic camera, I made a few goals to guide us

  • The players should be ‘front and center’ at all times.
  • Avoid having ‘dead’ screen space.
  • The camera can’t be distracting/dizzying (our game is already busy enough, visually).
  • Players need to know where they are on the court (left side, right side etc.) even if the camera is zoomed in.

Our eventual system

image

First I make a list of everything that I would like to keep on screen. For PMPY this is every part of the player’s bodies, the ball, and the center point of the court (so players know where they are).

These points provide a bounding box (shown in green), which is the smallest rectangle that contains them all. I then add a fixed width margin to the bounding box,  to keep the important action away from the edges of the screen (shown in red).

I then make a ‘target camera’. The center of the target camera is the center of the red/green boxes, and the zoom level is either the tightest zoom that will still show the whole box, or a preset maximum zoom level if that is too close. Capping the zoom helps avoids the camera feeling too swoopy when players come close together.  It’s a bit hard to see in the image above, but the target camera’s position is shown by the red dot in the image below.

image

The target camera can be a bit jerky, so I take an extra step to smooth it out. Once I have the target camera, I add it to a ring buffer that stores the last ten target cameras from previous frames. The buffer cameras are shown by the black dots.

The final camera position is the average position and zoom level of the 10 target cameras, shown in blue. Because the blue dot is used as the actual camera position, it is always in the very center of the image.

Once we had it all working, the game felt way better. Suddenly everything on screen was contributing to the feeling motion, and the character’s actions were much larger. It was as though we had made the game faster and more energetic, and it was much nicer to play.

-Nico