Building a Better Camera [Part 1]
Greetings again,
At last I have some updates to share for the overhaul of Beeknighted. I had to do a ton of planning before a line of code could be written to make sure the systems are all modular enough to hold up to the remainder of the game. When I made the initial demo I was learning everything on the fly and while the systems worked so far as the demo was concerned, pretty much none of the systems could handle much expansion.
I began with building a new camera system, which includes one of the most requested additions: a proper lock-on system.
The original camera "rig," as you may know if you played the demo, was extremely rudimentary. The camera can rotate around the player, cuts in front of anything and everything that collides with its view (to its detriment much of the time), and can snap behind the player. The camera rig was also directly attached to the player character, so there was no way to smooth out movements.
See It Your Way
One of the first things I did with the camera overhaul was figure out what the player should need from the system. I divided potential players into 3 groups: those who might want a modern control experience, those looking for an authentic N64 control experience, and those freaks who play Mario 64 with mouse and keyboard. My camera system seeks to accommodate all these players at once.
There is much precedence for hybrid control schemes in many platformers and action games from the 6th gen era. Mario, Zelda, Sypro, Vexx, Rayman, Pitfall; most of these games had some combination of automatic camera movements and player-controlled adjustment. I did fairly thorough research on this and I'll spare you the details, but suffice to say I looked at all of the features used by these systems as well as features I thought were absent from them and made individual determinations on what to add to my camera system by experimenting and testing different ideas. The final result is a camera system I'm confident will work well for most players, and most importantly for the gameplay I'm starting to implement.
Player Controlled Camera
The modern joystick/mouse controlled camera is relatively straightforward to set up. The user controls rotation up and down and side to side with the joystick or mouse. The lock-on button serves to reset the camera if there is no available target. My original demo's camera system focused on these bare functions.
For the purposes of building the prototype, I called this "Free" camera mode. Free camera mode engages whenever any button, joystick, or mouse input is detected, save for the lock-on and first-person view buttons.
Automatic Camera Motions
The automatic camera function set was a lot of trial and error. The automatic functions should at a base minimum be designed to guide the camera through spaces smoothly, ideally rotating in a way that aligns with the player's movements to a degree, but subtle enough that the player doesn't feel the need to take constant control beyond hard resetting the camera behind them. In the end, I took a less-is-more approach.
First off, some discarded attempts.
1. Screen-space adjustment. Some games (Banjo-Kazooie from memory, but many others) adjust the angle of the camera to show more of the space in front of where the player character is looking. Among the reasons for doing this is to show the player more of the space in the direction they presumably are looking to go as not to stumble into unseen danger before they can respond to it. Among the issues with this approach is that if the player snap turns in another direction, particularly directly opposite, they are now confronted with much less visible space than before. If the camera moves too quickly to accommodate it can be dizzying.
Banjo's implementation is particularly aggressive, for instance. If Banjo turns on a dime, regardless if he is standing still, the camera will position the frame so that he is at the power point between two lines of the rule of thirds, with the most space allocated to his vision.
I tried a few different approaches to this feature but didn't care for the results. First, I tried implementing a motion-based approach: the camera would only try to angle to the character's view if they were moving. The problem is this makes small and pulsed motions, like you might use to safely cross a tightrope, jarring and disorienting as the camera bounces back and forth each time the character stops. Even a momentum-based approach doesn't solve this unless there is a minimum threshold. However, having a minimum speed/momentum/distance qualifier causes a whole host of other issues. Setting a time delay was an option that mostly solved the issue but the problem of turning around persists.
In addition, the offset had to be accommodated by the variable distance between the camera and the player, which resulted in awkward positioning and clipping and became unwieldy when the player takes manual control. However, the reason I ultimately cut the feature is as I was testing the various options I found myself too often drifting to the joystick to wrestle control away, which contradicts my reason for trying it in the first place.
2. Delayed camera following. If the camera moves directly in lock-step with the player character, it can induce a kind of disorientation/anxiety that it is not the character moving, but the world beneath their feet. I've internally nicknamed it the "Monkey Ball Effect" because of how in Monkey Ball, the world will appear to quickly rotate while the ball appears to remain stationary, like a cognitive illusion.
To this end I tried an approach where the camera is slightly delayed in following the player, which resulted in similar issues to screen-space adjustment, in that small motions were heavily disorienting. Putting a minimum radius on the effect resulted in issues with how the collision worked and generally wasn't satisfying. Somehow the Souls series pulls off this method well, though I was unable to find a satisfying version. I instead opted for a different illusion using zoom, explained later.
3. Wall push-away and zoom. The idea of this feature is that if the camera is lingering near a wall for a while, that it begins to rotate away from it to avoid the claustrophobia, camera clipping and forced zoom, and wasted screen space, among other reasons. I vividly recall this happening in Whomp's Fortress from Mario 64 as you run up the slopes around the base of the level with walls constantly to your left.
My reason for cutting it after some testing was actually the opposite issue of the screen-space adjustment, that it pulled the camera away from where I wanted to look. Rarely is the wall the part of the scene I'm most interested in looking at, yet the feature pushes the camera into a position where it faces more of the wall, not less.
Because implementing this feature required detecting the distance to walls on both sides, I tried to piggy-back on another feature which zoomed in the camera if the player got into a tight space, alleyway, or tunnel. I ended up re-implementing this in a different way which I'll detail later.
4. Setting automatic camera actions on a timer. Many games reset the camera angle behind the player after a set period of inactivity, or turn on automatic camera motions after the camera controls have been left alone for a set period of time. I've never really cared for this approach, particularly when I wanted to look at the character or get an angle just right. Instead I opted for automatic camera motions to be a "Follow Mode" (contrasted by the "Free" mode) activated by hitting the reset/lock-on button. I found this integration just feels very natural.
5. The cliff plunge. This feature has the camera swoop up to look down as the player approaches a cliff so that they can see what is below them. Similar to the wall push, this feature had the issue of moving the camera even when the player wanted to see what was ahead of them, such as if they were hopping from platform to platform, an action which would regularly trigger the camera motion. I actually did keep this one but I restricted it to occurring only when the player stops moving by a cliff, which resets when they begin moving again on ground.
Now, to the things I did include.
1. Automatic horizontal rotation in the direction of movement. This is the most obvious and fundamental automatic camera movement, in my opinion. It ensures that the camera rotates when the player is turning a corner and assists with a sense of independence of movement, which I'll touch on later. I found this to be much more impactful than screen-space adjustment and more frequently aligns with how I as a player would want to move the camera manually anyway. It turns more aggressively the harder the character turns.
The one weak point of this approach is when the player runs directly toward the camera. While this could have been solved by a delayed momentum-based rotation reset to behind the player, I found that the issue is easy enough to reset with either angling the character naturally a bit away or hitting the lock-on button, which is already the established expectation with most early 3D platformers. Tapping a button once to reset the camera behind the player is a faster method than any automatic solution I could come up with that didn't interfere with normal gameplay.
2. Slope Angling. This angles the vertical rotation of the camera to look up or down slopes. This was a bit trickier to implement but works for most scenarios including steps. If the player is on a slope, the camera will look up if pointing toward the slope and look down if pointing away from it independent of where the character is moving.
3. Simulating free movement with zoom. Instead of allowing the character to move within a certain radius before the rig moves, I opted for a simulation of this with zooming the camera in and out depending on whether they are moving toward or away from the camera. This makes the approach compatible with the automatic horizontal rotation as well.
As the player moves toward the camera, it zooms in, creating the illusion that it is stationary. As they move away, the camera zooms out. This approach or something similar was used in Wind Waker and Rayman 3, among others.
4. "Zoom Zones." These are areas where I can manually control the maximum camera zoom to forceably move the camera in close in tight spaces or let the camera ease out in wide open spaces. While this adds a bit more tedium to designing areas, it means I have tighter artistic control of when the player's view is restricted or opened up and by how much.
5. Enhanced camera collision. This is a huge and complicated topic that took longer to puzzle out than all the other features combined so I'll try to keep this brief. The old camera worked like this: imagine a selfie stick held by the character with the camera at the end. if the stick bumps into anything, it retracts until the camera is in front of whatever it bumped into. This is how the springarm object in Godot works, which is a common and accessible approach built into the engine. The problem is it's terribly over-simplified.
If we instead imagine the character holding a selfie stick that is 20 feet long, trying to navigate through a dense forest without the stick bumping into something and constantly retracting would be incredibly cumbersome. So too with the springarm approach to collision.
The solution seems obvious: only check for objects bumping the camera directly and turn on the springarm when that occurs. The problem with this is that object collisions are by default not solid, meaning a large object like a house or boulder is considered hollow, and the camera might bump into the back, pass through the back, but not pass through the front, leaving it trapped in a horrible place with a horrible view. So I had to devise a two-pronged approach: check both the point the camera bumped and the last point between the player and the camera that is unobstructed.
In addition, if more than one object is obstructing the link to the player, only the one bumping into the camera directly should be considered. This allows small or thin objects like pillars, trees, and enemies to pass behind the player but in front of the camera without it constantly snapping around to get a view, while still respecting collision. A massive pain to build, to be honest, but done.
6. Handling jumping and flying. Jumping will be a new addition to the overhaul, and it came with a bunch of issues for the camera. Like normal movement, it requires some easing in order to create a sense of freedom of movement. It looks awkward if the camera bounces up and down in lock step with the character. However, if it does not, it can create all sorts of problems for the aforementioned collision system. I landed on a hybrid illusion approach which manages to stick right with the player while creating the illusion of looking at the vertical spot where they left the ground, similar to the zooming in/out feature. The view gradually moves back to where the player is at, faster when the player has landed or engaged flight, ensuring the camera is looking where it needs to.
That covers the basics for the standard camera system and thus that's all for now! In the next post, I'll talk more about how the new strafe and lock-on system works, as well as touch on the first-person view, all of which have already been implemented and thoroughly tested. Stay tuned!
Get Beeknighted Demo (32-Bit Game Jam)
Beeknighted Demo (32-Bit Game Jam)
Short N64-inspired action game made for the 32bit game jam 2021
Status | In development |
Author | MicrotonalMatt |
Genre | Platformer |
Tags | 3D, 3D Platformer, Action-Adventure, Action RPG, Fantasy, Female Protagonist, Low-poly, n64, Nintendo 64, PSX (PlayStation) |
More posts
- Redesigning AifeSep 02, 2023
- Demo v.3.7 released!Sep 12, 2022
- Beeknighted v.3.5 released!Aug 31, 2022
- Antfort Progress Update Towards v.2.3Aug 10, 2022
- Version 2.2 Update fixes and changes + LinuxJun 19, 2022
- 2.1 Update, Preview of Future UpdatesJun 14, 2022
- Demo Progress Update 4/14Apr 15, 2022
- 1.5 Update releasedJan 07, 2022
Leave a comment
Log in with itch.io to leave a comment.