GML camera following multiple players (pan, zoom, no splitscreen)

mX273

Member
Hi All

Im very new to this forum and im writing, because i couldnd figure out how to do this, and the google search didnt help.

I d'like to make the camera following multiple players with moving and zooming (no splitscreen). The aspect ratio should always be 16:9. Look at the sketch: desired_camera_view.png
In my code I calculate the min and max coordinates of all players and then i slowly change the view width until it fits in the desired boarders.


create event:
-----------------------------
Code:
viewX = 0
viewY = 0
width = 640
height = 360

draw event:
---------------------
Code:
   var minX = room_width // to find the minimum, set to maximum first
   var maxX = 0
   var minY = room_height // to find the minimum, set to maximum first
   var maxY = 0
   with(obj_player) // find min und max coordinates of all players
   {
      if (x > maxX) maxX = x
      if (x < minX) minX = x
      if (y > maxY) maxY = y
      if (y < minY) minY = y
   }
  
   var viewBorderX = 96   
   var viewBorderY = 32   
   viewX = minX-viewBorderX
   viewY = minY-viewBorderY
  
      
   var step = 4

  
   if ( maxX + viewBorderX > viewX + width ) // the right most player leaves the right boarder --> extend the camera view size slowly
   {
       width += step     // increase camera_view_width           
   }
   else if ( maxX + viewBorderX < viewX + width) // the right most player is within the right boarder --> make the camera view size slowly smaller until it exactliy matches the boarder
   {
       width -= step // decrease camera_view_width   
   }
  
   else if ( maxY + viewBorderY > viewY + height)
   {
       width += step // increase camera_view_width   
   }
   else if ( maxY + viewBorderY < viewY + height)
   {
       width -= step // decrease camera_view_width   
   }

   height = width/16*9 // calculate the height and keep aspect ratio 16:9
  
   camera_set_view_pos(view_camera[0], viewX, viewY)
   camera_set_view_size(view_camera[0],width, height)
this code almost work, but the camera is always shaking (4 pixels like the step-variable), when the view reaches the final view size.

can you help me?

thanks a lot!
 

Slyddar

Member
Instead of adding/subtracting, try using lerp. The movements will be smaller, so maybe they won't be as noticeable.
 

mX273

Member
Instead of adding/subtracting, try using lerp. The movements will be smaller, so maybe they won't be as noticeable.
even if i change step to 0.1, the camera is still shaking. i also tried something with a hysteresis, but i couldnt get it work. an other problem with my code is:
if a player walks down and all other stand still - it walks out of the view... (thats the next problem which i forgot to tell :().
can you give me an example with lerp?
 
Last edited:
well to find the center of your players is as simple as adding all of the locations together and dividing by the number of players. then set a tweakable number to move the view if view center further away than that number. as for keeping a 16:9 aspect ratio I would find subtract smallest x from biggest x as xneed then subtract smallest y from biggest y yneed. add your needed borders that's how big your view needs to be although it will vary to stay in 16:9 as for finding your size of the view in the proper ratio
Code:
xc=0
yc=0
do
{
xc+=16
yc+=9
}
until xc>xneed && yc>yneed
that should find a view size that fits all the players in 16:9.
 

NightFrost

Member
Lerp can be used to incrementally move a number towards target number by a given percentage. For example:
Code:
Currentvalue = lerp(Currentvalue, Targetvalue, 0.1);
will in each step move Currentvalue towards Targetvalue by 10% of their difference. In other words it moves fast when they are far apart, slowly when they are close together.

I too would position the camera by taking the centerpoint of all players. Getting the camera view size with aspect ratio is bit more complicated. You must calculate the smallest width you need by taking min and max player x-positions and adjust by your border values, and do the same to find the minimum height you need. Then you need to compare these to 16:9 ratio. If the height you calculated is less than (the width you calculated / 16 * 9) then you must adjust the height to equal the result. Otherwise, if the width you calculated is less than (the height you calculated / 9 * 16) you must adjust the width to equal the result. Finally, if adjusted width or height is larger than the room, you must shrink it to room size and readjust the other value to retain the 16:9 ratio.

Now that you have camera view size and camera centerpoint, you can calculate then upper left corner as target number and lerp your current camera position towards it by the speed you want. This would be all you need, but you could make the view size adjustment run through lerp too, but you must keep the speed high enough that players cannot run off camera, and the room size limit must be a hard limit that immediately shrinks the view to its size without lerping, or it will bounce outside room bounds before shrinking to the limit values.

EDIT - actually, that's not quite everything. Once you have the upper left corner, you must check if view stretches outside room, since you are adding border values to view. If this happens, you must shrink the view size in ratio.
 
Last edited:

mX273

Member
I too would position the camera by taking the centerpoint of all players. Getting the camera view size with aspect ratio is bit more complicated. You must calculate the smallest width you need by taking min and max player x-positions and adjust by your border values, and do the same to find the minimum height you need. Then you need to compare these to 16:9 ratio. If the height you calculated is less than (the width you calculated / 16 * 9) then you must adjust the height to equal the result. Otherwise, if the width you calculated is less than (the height you calculated / 9 * 16) you must adjust the width to equal the result. Finally, if adjusted width or height is larger than the room, you must shrink it to room size and readjust the other value to retain the 16:9 ratio.

thank you so much!!!!

This is the solution:

Code:
    var minX = room_width // to find the minimum, set to maximum first
    var maxX = 0
    var minY = room_height // to find the minimum, set to maximum first
    var maxY = 0
    with(obj_player) // find min und max coordinates of all players
    {
       if (x > maxX) maxX = x
       if (x < minX) minX = x
       if (y > maxY) maxY = y
       if (y < minY) minY = y
    }
   

    var viewBorderX = 96  
    var viewBorderY = 96  
    var viewMinX = minX-viewBorderX
    var viewMinY = minY-viewBorderY
   
    var w = maxX-minX+viewBorderX*2
    var h = maxY-minY+viewBorderY*2
       


    if (h > w/16*9)
    {
        w = h/9*16
    }
    else if (w < h/9*16)
    {
        h = w/16*9
    }
    else
    {
        h = w/16*9  
    }
   
    viewX = lerp(viewX,viewMinX,0.5)
    viewY = lerp(viewY,viewMinY,0.5)

      width = lerp(width, w,0.05)
    height = width/16*9


    if (viewX < 0) viewX = 0  
    if (viewY < 0) viewY = 0
   
    if (viewX+width > room_width)
    {
        width = room_width - viewX
        height = width /16*9
    }
    if ( viewY+height> room_height )
    {
        height = room_height - viewY
        width = height /9*16
    }


    camera_set_view_pos(view_camera[0], viewX, viewY)
    camera_set_view_size(view_camera[0],width, height)
 

mX273

Member
In some very view moments, depending on the player positions, it can happen, that the cameraview goes outside of the room. Thats OK, better than changing the ratio or better than a player is outside of the view.

Now my question is, how can i prevent / clear the streak education, when the view goes outside of the room?

clear_view_outside_of_room.png


Thanks!
 
Last edited:
Top