Animating camera

Casey has shown how to add a scrolling camera by setting the camera position to the player entity at the end of the simulation.

I wanted to try and add a slight delay to the camera movement to give a elastic movement so it's slightly slower than the player when following and then when the player stops the camera continues animating until the player is at the centre.

Also I wanted to be able to move the camera to show upcoming areas etc.

So I tried to attempt this but I am getting a bit confused when it comes to world positions and chunks and offsets...

So in theory I know how to animate a movement. I get the difference between the camera and player and normalise that to get a direction and then move by multiplying the direction and a speed constant along with the delta time of the frame. But when it comes to translating that into world space I have no idea.

I attempted something like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
    if (entity->StorageIndex == worldMode->CameraFollowingEntityIndex)
    {
        Vector3 start = worldMode->CameraPosition.Offset;
        Vector3 end = storedEntity->Position.Offset;
        float speed = 10.0f;
            
        float distance = Length(end - start);
        Vector3 direction = Normalise(end - start);

        if(distance > 0)
        {
            worldMode->CameraPosition = MapIntoChunkSpace(
                worldMode->World,
                worldMode->CameraPosition,
                start + direction * speed * deltaTime);
        }
    }


But this just results in a bit of a mess. Can anyone explain how I can achieve this?

Am I going about this the right way?
I'm not sure about the specifics of the Handmade Hero code, but generally if you want the "laggy" style camera, you need to move the camera proportionally to the distance between the current camera position and the player. That way the camera never gets too far away (it will move faster if it gets too far away until it eventually reaches an equilibrium with the player speed), and when the player stops, it kind of "eases in" to the player position, slowing down as it gets closer and closer to the player.

This would be something like CameraPosition = (PlayerPosition - CameraPosition)*0.05 + CameraPosition
(although you would probably want to modify the constant based on deltaT instead of a fixed amount per loop)
I don't remember the exact details of how HH does its positions, but if I recall correctly the offset is relative to the chunk it is in. So if the camera's previous position and the player's new position are in different chunks, your end-start vector is going to be nonsensical.

Secondly, if we hit 60fps, delta time will be constant. Which means the camera position will move by a constant amount each frame. As a result, it will (most of the time) overshoot the target position, overcorrect on the next frame, etc, just oscillating around the player. Regardless of whether you want it to speed up / slow down depending on distance, you need to bound it so that if the distance is less than the distance it will move, you clamp to the player's position rather than overshoot.
As Bryan said, world position stores chunk coordinates and an offset relative to that chunk.

So you'll need to convert these into a "non chunk" world space.

Something like:

1
2
vector3 d = { position->chunk_x, position->chunk_y, position->chunk_z };
vector3 p = hadamard(world->chunk_dim_metres, d) + position->offset;


This should give you the actual position in metres which you can now use to move your camera.

Then as you doing, you would map this back into chunk space when setting the camera position.

Edited by James Hull on