the camera jumps with the player

Sorry for the mistakes, English is not my first language.
My camera will follow the player, and when he jumps the camera also jumps after him.
How to set up the camera so that when jumping it does not rise, but when the player falls, it moves down following the player.

GML:
---------------------------------------------------------------------------------------------------------
Сreate
---------------------------------------------------------------------------------------------------------
enum CAM_MODE {
    FOLLOW_OBJECT,
    FIXED,
    FREE
}
cam_mode = CAM_MODE.FIXED;

enum RES {
    WIDTH = 640,
    HEIGHT = 360,
    SCALE = 2 //Zoom.
}

display_width = display_get_width();
display_height = display_get_height();

offset_x = 0;
offset_y = -110;

var _x_border = 128;
var _y_border = 128;
global.CAMERA = camera_create_view(0, 0, RES.WIDTH, RES.HEIGHT, 0, -1, -1, -1, _x_border, _y_border);
view_set_camera(0, global.CAMERA);

window_set_size(RES.WIDTH * RES.SCALE, RES.HEIGHT * RES.SCALE);

surface_resize(application_surface, RES.WIDTH * RES.SCALE , RES.HEIGHT * RES.SCALE );

display_set_gui_size(RES.WIDTH,  RES.HEIGHT );

alarm[3] = 1;

follow = noone;

camera_pan_speed_initial = 0.15;    //lower = slowed pan
camera_pan_speed = 1;

alarm[CAMERA_RESET] = 3; //alarm [0].

---------------------------------------------------------------------------------------------------------
User event.
---------------------------------------------------------------------------------------------------------
/// @description FOLLOW_OBJECT
if (instance_exists(follow)) {

var _current_cam_x = camera_get_view_x(global.CAMERA);
var _current_cam_y = camera_get_view_y(global.CAMERA);

var _follow_x = (follow.x - RES.WIDTH /2) + offset_x;
var _follow_y = (follow.y - RES.HEIGHT/2) + offset_y;

_follow_x = clamp(_follow_x, 0, room_width - RES.WIDTH);
_follow_y = clamp(_follow_y, 0, room_height - RES.HEIGHT);

var _new_cam_x = lerp(_current_cam_x, _follow_x, camera_pan_speed);
var _new_cam_y = lerp(_current_cam_y, _follow_y, camera_pan_speed);
 
camera_set_view_pos(global.CAMERA, _new_cam_x, _new_cam_y);
}
 

Vusur

Member
First make the camera follow the player at all time. Assuming obj_player is the player instance you are following.

GML:
//in create
camera_offset_x = camera_get_view_width(global.camera); / 2; //half the width
camera_offset_y = camera_get_view_heigth(global.camera) / 2; //half the heigth

//in step

// lock the middle of the screen to the player
var _x = obj_player.x - camera_offset_x;
var _y = obj_player.y - camera_offset_y;
camera_set_view_pos(global.camera, _x, _y );
Well, it moves always as soon as you move the player. So you have to limit it.

GML:
var _old_x = camera_get_view_x(global.camera); //has the right coords from previous step
var _old_y = camera_get_view_y(global.camera); //has the right coords from previous step

var _new_x = obj_player.x - camera_offset_x;
var _new_y = obj_player.y - camera_offset_y;

//maybe you still wanna move the camera left and right?
//old_y, not new_y. setting y comes later
camera_set_view_pos(global.camera, _new_x, _old_y);

//it the player moves down, the y gets bigger. Only update camera y then
if(_old_y < _new_y)
{
    //new_x is redudant, but pos needs x and y.
    camera_set_view_pos(global.camera, _new_x, _new_y );
}
basic idea. This won't work with copy&paste. Just take it as a general idea.
 
Thank you! This works great. But now if the player jumps on the platforms and goes up, the camera does not follow him. What can be done?
 

TheouAegis

Member
What if you just use
Code:
offset_y = max(offset_y - player.vspd, -110);
The idea is when the player jumps, the camera will still follow the player, but move toward the player at the same rate the player moves away from the last stable position. When the player falls, it will lock in at the default offset.
 

Vusur

Member
Oh, so you wanted this:
The player jumps, the camera stays locked.
The player falls, the camera follows.
The player jumps ON a platform above him, platform elevator, slope up, the camera follows him/snaps back, while he stands on a platform.
?

Yeah, this won't work with my code. I only did the first two conditions. The third option is just another condition, but depends on you other code. It's again depends on the player.
First you need some sort of states. The states should differentiate between "jumping", "falling" or all the other states. Shorten to "jumping" and "not jumping".
Jumping is defined as "in the air AND with old_y < new_y". If this is the case, lock the camera. If this is not the case, so you are "NOT in the air" OR "old > new_y", follow the player even for the y coord.

GML:
//... 

//maybe you still wanna move the camera left and right?
//old_y, not new_y. setting y comes later
camera_set_view_pos(global.camera, _new_x, _old_y);

//is the player in the air?
if(obj_player.isAirborn)
{
    //is it jumping up or falling down?
    if(_old_y < _new_y)
    {
        //new_x is redudant, but pos needs x and y.
        camera_set_view_pos(global.camera, _new_x, _new_y );
    }
}
// player is not in the air, landed on a platform etx.
else
{
    //new_x is redudant, but pos needs x and y.
    camera_set_view_pos(global.camera, _new_x, _new_y );
}
This is again more of a basic idea and not copy&paste. You can shorten this quite a bit.
obj_player.isAirborn is just a flag, notifier or information traveller. Here it's a boolean, that is set true in obj_player, when he is in the air/jumps and set false, when he is on the ground. State machine would probably the better option.

You could also add TheouAegis idea. Makes the camera smoother. But this is up to you.
 
What if you just use
Code:
offset_y = max(offset_y - player.vspd, -110);
The idea is when the player jumps, the camera will still follow the player, but move toward the player at the same rate the player moves away from the last stable position. When the player falls, it will lock in at the default offset.
I get an error when I write in create: offset_y = max(offset_y - o_player.vsp, -110);

How can I make sure that the camera does not start moving until the player's coordinates are more than half of the screen?
 
Last edited:

TheouAegis

Member
Vertically?
Code:
if abs(camera_get_view_y(global.camera) + camera_get_view_height(global.camera) - obj_player.y) > camera_get_view_height(global.camera) / 2 {
I think those are the right functions. I don't have the manual open right now.
 
And where should I write it?
It seems to me the easiest thing to do is to make the camera move vertically when the player has raised more than half of the screen. But I don’t understand how to do it.
 

TheouAegis

Member
It would go where you set your camera movement.

Are you using my
offset_y = max(offset_y - player.vspd, -110);
code? If so, try changing it to
Code:
offset_y = median(offset_y - player.vspd, -110, camera_get_view_height(global.camera)/4);
The idea with this modification is when the player jumps, the camera will move up once the player has reached the top of the view. The camera will move down when the player attempts to dip below the lower threshhold (offset_y). You can tweak how long it takes the camera to pan up by editing camera_get_view_height(global.camera)/4 as needed. The smaller the value (i.e., the lower the numerator or the greater the denominator), the sooner the camera will scroll up.

What I like about this method, even though it does require some tweaking, is you can adjust offset_y to look up or down while standing still, then go directly into a jump, and the camera will be back to square one when you land.
 
Thank you! It works! The camera moves up slightly when jumping. This is because of offset_y - o_player.vsp. How can you make sure that the camera does not move at all when jumping?
 
I tried this option. The camera now jerks upward. Can this be fixed?

GML:
if (instance_exists(follow)) { 

    var _current_cam_x = camera_get_view_x(global.CAMERA);
    var _current_cam_y = camera_get_view_y(global.CAMERA);

    var _follow_x = (follow.x - RES.WIDTH /2) + offset_x; 
    _follow_y = (follow.y - RES.HEIGHT/2) + offset_y;

    _follow_x = clamp(_follow_x, 0, room_width - RES.WIDTH);
    _follow_y = clamp(_follow_y, 0, room_height - RES.HEIGHT);

    var _new_cam_x = lerp(_current_cam_x, _follow_x, camera_pan_speed);
    var _new_cam_y = lerp(_current_cam_y,  _follow_y, camera_pan_speed);

    camera_set_view_pos(global.CAMERA, _new_cam_x,  _current_cam_y);

    if(_current_cam_y < _follow_y) // Down
    {
        camera_set_view_pos(global.CAMERA, _new_cam_x, _new_cam_y );
    }

    if(_current_cam_y > _follow_y + RES.HEIGHT/2   ) //Up
    {
      camera_set_view_pos(global.CAMERA, _new_cam_x, _new_cam_y );
    }

}
 
Top