🔒 Locked
2D Camera System
Advertisement
Original Post
Basically I want to create a slightly more advanced 2D camera system than the one I'm currently using. Right now all it does is move at the same speed as the player. What I want is a camera that moves at a slower acceleration and is always leading in front of the player regardless of direction. So my idea is to have it so that when the player starts move, the camera will start to accelerate (at a rate less than the players acceleration) to the same maximum velocity as the player, and when the player begins to decelerate, or stops due to collision, the camera will decelerate. The problem I would run into though is that when you change direction, the camera would be behind the player, not in front. I could of course, allow the camera to have a greater velocity than the player so it could catch up with and pass them until it was in front, but I'm not sure how to determine where to stop it so that it doesn't go so far ahread the player is no longer in the cameras field of view. Am I even taking the right approach to this?
A camera that's always in front but accelerates smoothly must for a moment have higher acceleration than the player character to catch up with "in front". If the camera acceleration is constant and higher than the player acceleration it can look jerky especially when you turn the player around. Also, if the camera is only controlled using acceleration, it'll be difficult to make it stop at "in front", it may pass that position before it has slowed down.
There are several ways to program a camera like you describe, and any approach is probably more or less right :)
My suggestion for an approach that's simple to program and results in smooth but exact camera movement, is that you discard the acceleration and velocity of the camera. Think of the camera as wanting to focus on something, and determine that focus. Once the focus is determined, that's the center position of the camera, so we can simply position the camera at the focus. Seeing it this way, there's no need for acceleration.
So we need to determine the focus. The most straight-forward focus is the player character, which is what I think you have in your current camera system. But if I understood correctly, you want it to focus in front of the player character if its moving forward. And everybody probably wants the transition in-between to be smooth [grin]
So the focus is relative to the player position, and the distance to that relative position is dependent on the player velocity.
When the player velocity is 0, the distance to the camera focus is 0.
When the player velocity is playerMaxVelocity, the distance to the camera focus is focusMaxDistance.
k is how dependent the camera focus is on the player velocity.
For example, k = focusMaxDistance / playerMaxVelocity
What do you think, can it be worth to throw away that acceleration for this still smooth approach?
There are several ways to program a camera like you describe, and any approach is probably more or less right :)
My suggestion for an approach that's simple to program and results in smooth but exact camera movement, is that you discard the acceleration and velocity of the camera. Think of the camera as wanting to focus on something, and determine that focus. Once the focus is determined, that's the center position of the camera, so we can simply position the camera at the focus. Seeing it this way, there's no need for acceleration.
So we need to determine the focus. The most straight-forward focus is the player character, which is what I think you have in your current camera system. But if I understood correctly, you want it to focus in front of the player character if its moving forward. And everybody probably wants the transition in-between to be smooth [grin]
So the focus is relative to the player position, and the distance to that relative position is dependent on the player velocity.
When the player velocity is 0, the distance to the camera focus is 0.
When the player velocity is playerMaxVelocity, the distance to the camera focus is focusMaxDistance.
cameraFocus = playerPosition + playerVelocity * k;k is how dependent the camera focus is on the player velocity.
For example, k = focusMaxDistance / playerMaxVelocity
What do you think, can it be worth to throw away that acceleration for this still smooth approach?
Quote:
Original post by Dim_Yimma_H
A camera that's always in front but accelerates smoothly must for a moment have higher acceleration than the player character to catch up with "in front". If the camera acceleration is constant and higher than the player acceleration it can look jerky especially when you turn the player around. Also, if the camera is only controlled using acceleration, it'll be difficult to make it stop at "in front", it may pass that position before it has slowed down.
There are several ways to program a camera like you describe, and any approach is probably more or less right :)
My suggestion for an approach that's simple to program and results in smooth but exact camera movement, is that you discard the acceleration and velocity of the camera. Think of the camera as wanting to focus on something, and determine that focus. Once the focus is determined, that's the center position of the camera, so we can simply position the camera at the focus. Seeing it this way, there's no need for acceleration.
So we need to determine the focus. The most straight-forward focus is the player character, which is what I think you have in your current camera system. But if I understood correctly, you want it to focus in front of the player character if its moving forward. And everybody probably wants the transition in-between to be smooth [grin]
So the focus is relative to the player position, and the distance to that relative position is dependent on the player velocity.
When the player velocity is 0, the distance to the camera focus is 0.
When the player velocity is playerMaxVelocity, the distance to the camera focus is focusMaxDistance.
*** Source Snippet Removed ***
k is how dependent the camera focus is on the player velocity.
For example, k = focusMaxDistance / playerMaxVelocity
What do you think, can it be worth to throw away that acceleration for this still smooth approach?
Well I can certainly throw away any of my ideas as I haven't got into coding it yet, but I'm still a little confused. Wouldn't this camera sort of jump to the other side when you change direction, rather than scroll smoothly?
I'm not sure if anyone here has played Cave Story ( http://agtp.romhack.net/doukutsu.html ) but the camera system in this game is what I'm trying to mimic since I liked the way it worked so much. You can kind of see how when the player begins to move, he gets a little bit closer to the camera's focus point, and farther from it when he stops moving.
[Edited by - CandleJack on February 23, 2007 3:55:56 PM]
I tried out the game, and it seems to me like they just move the camera at a constant velocity toward a focus point, but within the player's reference frame. In other words, the math assumes the player's location is the origin, and then it's transformed to the global reference frame to get the final camera parameters passed to the engine.
Quote:
Original post by CandleJack
Well I can certainly throw away any of my ideas as I haven't got into coding it yet, but I'm still a little confused. Wouldn't this camera sort of jump to the other side when you change direction, rather than scroll smoothly?
The camera I described have a smooth transition from the maximum speed (where it's distant) to the minimum speed (where it focuses on the player character) but it requires one condition to be fulfilled. The player character movement itself must use acceleration to change its velocity, even if the player sprite changes direction instantly the velocity must gradually decrease smoothly using acceleration to change sign. As long as it does that, the camera movement will be equally smooth since the camera focus relative to the player position is proportional to the player velocity. Worth noting is that "cameraFocus = playerPosition + playerVelocity * k" must be updated every frame, though k is constant.
So we get something like this:
void InitCamera(float focusMaxDistance, float playerMaxVelocity){ k = focusMaxDistance / playerMaxVelocity;}void UpdateCamera(float playerPosition, float playerVelocity){ cameraFocus = playerPosition + playerVelocity * k;}void Update() //updates the game entities once per rendered frame (or physics step, if you use that){ UpdatePlayer(); UpdateCamera(playerPosition, playerVelocity)}The example is in one dimension, but can be extended to two dimensions with two cameraFocus, playerPosition and playerVelocity components.
Another approach would be to set a target point for the camera, based on the player's instantaneous position and velocity every frame, and have the camera attempt to move towards that point.
Quote:
Original post by Dim_Yimma_H Quote:
Original post by CandleJack
Well I can certainly throw away any of my ideas as I haven't got into coding it yet, but I'm still a little confused. Wouldn't this camera sort of jump to the other side when you change direction, rather than scroll smoothly?
The camera I described have a smooth transition from the maximum speed (where it's distant) to the minimum speed (where it focuses on the player character) but it requires one condition to be fulfilled. The player character movement itself must use acceleration to change its velocity, even if the player sprite changes direction instantly the velocity must gradually decrease smoothly using acceleration to change sign. As long as it does that, the camera movement will be equally smooth since the camera focus relative to the player position is proportional to the player velocity. Worth noting is that "cameraFocus = playerPosition + playerVelocity * k" must be updated every frame, though k is constant.
So we get something like this:
*** Source Snippet Removed ***
The example is in one dimension, but can be extended to two dimensions with two cameraFocus, playerPosition and playerVelocity components.
Ok, I see what you're saying now. I'll begin implementation and see how it goes. Thanks.
Quote:
Original post by Bob Janova
Another approach would be to set a target point for the camera, based on the player's instantaneous position and velocity every frame, and have the camera attempt to move towards that point.
The problem with that is how to deal with turning around and the speed of the camera. It would have to be going faster than the player to pass him when switching from the left side to the right, and then slow down again so that it doesn't look all jumpy. Though I wonder having it decelerate when it gets to a certain closeness to the final location would work. I'll think about that as well. Thanks for your input.
A very simply approach that I used back in my 2D days was to set the camera's velocity proportional to the distance from the player, but no greater than the velocity of the player.
like:
You can split that into X and Y if you want. You will need appropriate checks for the signs of the magnitudes - you only need the > check if they have the same sign, and flip the test for negative.
And set to zero if less then some small number.
like:
camera.velocity = player.position-camera.position;if (camera.velocity > player.velocity) camera.velocity = player.velocity;You can split that into X and Y if you want. You will need appropriate checks for the signs of the magnitudes - you only need the > check if they have the same sign, and flip the test for negative.
And set to zero if less then some small number.
Have you tried my suggestion? It should eloquently handle all these cases. It's also based on what I perceived to be happening in the game you mentioned, Cave Story (which is quite addicting by the way [smile]).
Basically, something like this:
Basically, something like this:
// Offset and speed (chose suitable values)const float cameraTargetDelta = 10.0f;const float cameraSpeed = 2.0f; void updateCamera(float deltaTime){ Vector2 cameraTargetActual = unitPlayerDirection * cameraTargetDelta; Vector2 cameraDirection = cameraTargetActual - cameraPositionLocal; if(squaredLength(cameraDirection) < EPSILON) { cameraPositionLocal = cameraTargetActual; return; } cameraPositionLocal += normalize(cameraDirection) * cameraSpeed * deltaTime; if(squaredLength(cameraPositionLocal) > squaredLength(cameraTargetActual)) cameraPositionLocal = cameraTargetActual;} void setupCamera(){ cameraPositionGlobal = cameraPositionLocal + playerPositionGlobal; setCameraPosition(cameraPositionGlobal);}Quote:
Original post by Zipster
Have you tried my suggestion? It should eloquently handle all these cases. It's also based on what I perceived to be happening in the game you mentioned, Cave Story (which is quite addicting by the way [smile]).
Basically, something like this:
*** Source Snippet Removed ***
Ahh sorry, I completely missed your post. I will take a look at all the suggestions in depth and see which one suits my needs best. Thanks to everyone who is helping, I appreciate it all.
And yes Cave Story is very addicting hehe. It was all done completely by one person (programming, art, and music) and was pretty much the biggest inspiration for me to do my own 2D game.
Quote:
Original post by Zipster
Have you tried my suggestion? It should eloquently handle all these cases. It's also based on what I perceived to be happening in the game you mentioned, Cave Story (which is quite addicting by the way [smile]).
Basically, something like this:
*** Source Snippet Removed ***
Ok I now understand the method you described and it seems to make sense to me. I'm a little bit confused by a couple things in the code you wrote though. First, is the squaredLength function simply returning the length of the vector? That's what it looks like to me, but I just want to be sure. Second, I'm not sure what EPSILON is. So the only thing I really don't get is what the first if statement is checking for.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement