Wednesday, January 13, 2010

The Elusive Perfect Platformer Camera

I've come to believe that platformers live and die by their camera system. The camera system is the code that decides how the player should be centered in the frame. The camera must somehow track the player as he moves such that the player can see what's coming. That might seem like a simple problem, but it's not. In fact, I'll go out on a limb and say that a bad (or even mediocre) camera system can ruin a 2D scrolling platformer game.

I mentioned in a previous post that the data coming back from my play testers showed them dying in droves in bottomless pits. I guessed that this had to do with the camera system scrolling up and down, and I was right; a review of the camera code revealed a lot of room for improvement, and after some tuning and bug fixing, I think the experience is much improved.

But this experience again drove home the point I made in the intro paragraph: that the camera in a 2D scrolling platformer has the potential to affect the play experience dramatically--it has to be as perfect as possible. I've made a lot of side-scrollers before, and I should know this, but I was still surprised by how much play was improved by a few simple camera tweaks.

If you are ever at a loss about what to do when it comes to 2D platformer design, refer back to Super Mario Bros. It's like the bible of platforming games--every problem that you might encounter has already been solved, and it's probably been solved in a way that works better than whatever you came up with. At least, that's been my experience. Take a look at this video from Super Mario Bros. 3. Pay attention to the amount of vertical scrolling that the game does when the player gets close to the top of the screen.



You can see that the game almost never scrolls vertically. The really interesting case is around 0:56, where the level (which has previously refused to scroll vertically) scrolls up in one very specific point to get the secret 1up. It's like vertical scrolling is only allowed in very specific situations. You can also see this sort of logic at work when Mario grabs the tanuki suit and starts to fly--immediately the game begins to follow him vertically.

Now compare the camera movement in Mario to the video below. This is Frogger Advance: The Great Quest, a GBA game that I worked on all the way back in 2001.



Quite a difference, right? The camera is all over the place, but despite all of the motion it's pretty much impossible to see where you are going. Part of the problem is that Frogger himself is really big; he takes up so much space on the screen that the camera really has to move just to keep him in the frame. This is a leading camera--it's supposed to always show you the direction that that you are moving. But in practice the physics are so fast that even if the camera rushes to show what's coming up, the player doesn't have time to react. When we made this game we understood that players were dying because they couldn't see where they would fall after a jump, but we didn't understand what to do about it. If you watch this video, you'll see the player use Frogger's float move to slow his falling motion down; this move was added explicitly to combat fall-into-pit deaths. A better solution would have been to try to reduce the amount of movement of the camera by designing levels that don't need to scroll vertically and reducing the size of the main character.

For Replica Island, my camera algorithm is based on the concept of a "window." I actually thought of it as a sphere when I wrote it, but my good friend and ultra-veteran platformer author gman pointed out that it's more accurate to think of a window. The center of the screen is defined by the center of the window, so when the window moves, the game scrolls. The rule that the camera's target (the player) must always remain within the window. When the player crosses out of the bounds of the window, the camera must move the window so that it contains the player at his new position. However, as long as the player stays within the window the camera does not move. So the player is able to cause scrolling in a particular direction by pushing up against a side of the window.

To fix the levels in which huge numbers of users were dying, I adjusted the bounds of the window so that almost no scrolling occurs in the Y axis until the player approaches the top of the screen. The camera also does not allow the player to move below the middle of the screen. So now a small jump causes no vertical camera movement, but hopping off a ledge keeps the player right in the center of the display. This makes seeing what's below you a lot easier than before.

But the heuristic wasn't good enough on its own, so I've also added a special object that, when visible, biases the camera in one direction or another. This lets me put camera hints in the map in areas that I know to be particularly problematic.

Finally, on a few levels I squeezed the level size down so that there's almost no vertical scrolling at all. This makes these levels feel a bit more like Mario, as the game almost never scrolls up and down. This makes the jumping puzzles actually fun, rather than one leap of faith after another.

So far I'm pretty happy with the results, but the real test will be to compare this new version of the code and levels with the data that I presented before; if my theory is right, the number of deaths from falls should be dramatically reduced. If I'm wrong, well, it'll be another round of iteration. It's worth it though; bad cameras are the death of 2D scrolling games.

8 comments:

  1. I had been thinking about good camera systems for a looooong time and came to the window idea as well. However, the special bias object is genius...

    Also Chris am I correct in thinking you'll be talking at Google I/O again? Your talk last year was great, and it seems to be a continuation of the same program (based on the title.)

    ReplyDelete
  2. when it comes to camera: show what is in front rather than what is behind, allow zooming ideally (test what zoom level players prefer btw :) )

    I don't know if I already linked it in the comments, but this Knytt Stories design tour is probably the most useful video for platform game devs so far.
    Here's a teaser, which I first quoted here:
    In a platformer, the player will spend most of the game running, jumping and climbing, so it's important to make those actions as intuitive and precise as possible. With better controls you can make more complicated levels, without making them frustrating or unfair. The overall difficulty of a game is a combination of the difficulty of controlling your character and the difficulty of the challenges your character faces. It is much more satisfying to have an agile character defeating complex challenges than a clumsy character defeating simple ones.

    ReplyDelete
  3. > Andrex

    The bias object works, but it's a hack. It violates my first rule of camera design, which is that the camera shouldn't move unless the player is moving (and I may actually experiment with only allowing the bias to be applied when the camera is in motion). Mario is good enough that it doesn't need a bias object (though there are clearly other rules in play--the way that 1up is revealed is pretty interesting).

    And yeah, I'll be speaking at Google IO again this year. A lot has changed since last year (and I might even have this game done by then--ha!), so I should have a lot of new stuff to talk about.

    > qubodup

    Leading cameras are petty had to get right, especially in the Y axis. The camera in Frogger leads--if I remember correctly, it looks at the player's velocity, projects out from the player's current position by some lead distance, and makes that point the camera focus. But when the player jumps, the camera has to go from below the player (or in his middle) to above him as he rises, then to below him again as he falls, which is a huge amount of camera movement (and generally causes the floor to be obscured, which makes jumping hard). The Frogger game is particularly bad at this because the character is so large and the lead distance therefore long. Leading works better in the X axis, but there's some tricky stuff there as well (you don't want to snap when the character changes his facing direction, etc).

    In Replica Island I don't lead at all. In fact I follow the player, which is generally what Mario does too (in the Y axis--it leads with the X axis). I'm also adjusting the follow distance (shorter = character closer to the center of the screen) based on the Player's state (mostly whether he's on the ground or in the air). This is all touchy-feely stuff--it's hard to codify a set of rules that will work across all platformer games.

    Thanks for the link to the piece on Knytt Stories! That looks fantastic. Note how small the character is and how the camera doesn't move when she jumps. And while I agree with the points made in the video piece, different games have different requirements (e.g. Mario has much less friction than Knytt but still manages to feel responsive and predictable).

    ReplyDelete
  4. Great stuff, I solved a similar issue by creating bars at the top and bottom of the screen and using that area to trigger scrolling...

    ratio based on sprite position within those top/bottom bars influences speed of camera y scroll. seemed to work decent enough

    can't wait to see replica island - there anywhere where lowly developers can get a sneak preview?

    宜敷く ですか ?

    有り難うございます

    ReplyDelete
  5. Interesting post.

    I think that the camera work in Replica is decent, although I do think it is really missing some sort of visual cue for bottomless pits. Right now, there are many levels that I kind of just walk off the ledge with my finger on the jump button to see if there is anything below since I find it very hard to tell if I'm just high up in the air, or if the pit is in fact a pit that will kill me. I often end up dying anyway since jumping can't reverse the downward acceleration in time before the game registers a death. I think a simple fade-to-black gradient on the bottomless pits would solve this, or for levels with a black background, instead of using pits replacing them with spikes... anything that visually says "this will kill you if you go this way."

    As for the camera problem.. would it be possible to assume that if you're just jumping (without using booster) don't move the Y-axis, but if you're using the booster and traveling in a vertical direction, you can lead the player, assuming they will want to see what is coming since they are moving up, and then as the fuel runs out, start shifting the camera to lead what is coming in a downward direction. If a player simply walks off a ledge, you can track this as well, and immediately lead downward and only shift the camera upward if they start moving in an upward motion. I feel like the fact that you have a fuel gauge, you can use this information, combined with the velocity and trajectory to good effect to anticipate where the player will be headed. That is to say, if they're low on fuel, you pretty much know they're going down.

    ReplyDelete
  6. Chris,

    It is interesting that you mentioned that you use Mario as a guide of how to implement a camera for a side-scroller. I say that because every time I play Replica Island and my wife glances at my screen she thinks I'm playing Mario. I always have to explain that it's not.

    Jack

    ReplyDelete
  7. hello friends how are you ?you can find here replica mobilesreplika telefonlar

    ReplyDelete
  8. It is a fantastic write-up, Thank you regarding offering myself these records. Retain submitting.
    Shaun

    ReplyDelete