Help with Celeste-style room transitions

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By AUD_FOR_IUV

Hello everyone! I’m having some trouble trying to implement a celeste-style room transition in this small platformer game that I’m working on. My strategy has been to use a Tween on the camera to interpolate the camera limits to the new room’s dimensions when the player enters a new room. This works really well when the entire room fits within the viewport, as shown here, but when the room is larger than the viewport the interpolation seems to introduce this weird jittery effect, as shown here. The code that is run every time the player enters a room is roughly as follows:

extends Camera2D

func transition(room: Room) -> void:
    $Tween.stop_all()
    
    var room_dimensions := _get_room_dimensions(room)
    _interpolate_property('limit_left', self.limit_left, room.global_position.x)
    _interpolate_property('limit_right', self.limit_right, room.global_position.x + room_dimensions.x)
    _interpolate_property('limit_top', self.limit_top, room.global_position.y)
    _interpolate_property('limit_bottom', self.limit_bottom, room.global_position.y + room_dimensions.y)
    
    $Tween.start()

func _interpolate_property(prop, start, end) -> void:
    var duration := 0.25
    var trans := Tween.TRANS_LINEAR
    var easing := Tween.EASE_OUT
    
    $Tween.interpolate_property(self, prop, start, end, duration, trans, easing)

func _get_room_dimensions(room: Room) -> Vector2:
    var half_extents = room.get_node('Area2D').get_node('CollisionShape2D').shape.extents
    return 2 * half_extents

Here, every room is assumed to have an Area2D that defines its boundaries, and the origin is always in the upper left corner of the room. My experimentation seems to suggest that rooms that are either wider or taller than the viewport will introduce this jittering (the room I enter in the second link is a long hallway that continues to the right past the viewport).

Any idea on what might be happening? Thanks in advance for the help!

:bust_in_silhouette: Reply From: markopolo

The camera can do some jittery things when limits suddenly change, especially when the limits are smaller than the screen size. My guess for what’s happening here is that when you transition from a smaller room to a bigger room (or vice versa), at one point during the tween the difference between left and right (or top/bottom) limits becomes less than the size of the screen, causing a jump or jitter as one of the limits ends up being ignored. In general, I try to avoid use camera limits to actually move the camera.

What you might try instead:

  1. Give each doorway / transition zone a pair of Position2Ds: each one representing the point the camera should tween to when entering the room on that side of the transition.
  2. When a transition zone is hit, remove the camera limits in the dimension the camera needs to travel (i.e. remove left/right limits when transitioning horizontally)
  3. Tween or lerp the camera position from it’s position when the transition triggered to the Position2D position for the room on the other side of the transition
  4. When the lerp/tween finishes, reinstate the limits to correctly fit the new room.

Hope this helps!

The problem with this solution is that the camera would no longer track the player when they move in a room whose boundaries exceed the camera’s viewport, since I would be tweening the camera’s global position in each room. My thought process with the camera limit tweening was that I could keep the camera fixed to the player, and just manipulate the limits to both allow for room transitions as well as controlling how the camera follows the player (when the room is larger than the viewport; if the room is the same size as the viewport, it would effectively be like pinning the camera to the center of the room).

AUD_FOR_IUV | 2019-05-16 18:19