Trying to reproduce a camera effect from Hotline Miami. Ran into a problem.

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

So I’m trying to have the camera get pulled in the direction of the mouse, but stop at the border of the screen. It works, somewhat, but in the wrong direction. Adjusting the camera scale doesn’t seem to affect it. Some help would be very much appreciated!

Video Example: https://streamable.com/zfqeur
Notice how the camera moves towards the sides. It moves down as well, but only when it’s towards the bottom-right.

Camera script (should be unrelated but just in case):
extends Camera2D

This script assumes that the zoom.x and zoom.y are always the same.

var current_zoom
var min_zoom
var max_zoom
var zoom_factor = 0.75 # < 1 = zoom_in; > 1 = zoom_out
var transition_time = 0.25

func _ready():
max_zoom = zoom.x
min_zoom = max_zoom * zoom_factor

func zoom_in(new_offset):
transition_camera(Vector2(min_zoom, min_zoom), new_offset)

func zoom_out(new_offset):
transition_camera(Vector2(max_zoom, max_zoom), new_offset)

func transition_camera(new_zoom, new_offset):
if new_zoom != current_zoom:
current_zoom = new_zoom
$Tween.interpolate_property(self, “zoom”, get_zoom(), current_zoom, transition_time, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
$Tween.interpolate_property(self, “offset”, get_offset(), new_offset, transition_time, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
$Tween.start()

Player Script:

The main code I’m using to move the camera:
func _process(delta):
mouse_offset = (get_viewport().get_mouse_position() - get_viewport().size / 2)
camera.position = lerp(Vector2(), mouse_offset.normalized() * 250,
mouse_offset.length() / 1000)
Code for zooming in camera (just in case):
if Input.is_action_pressed(“zoomin”):
$Camera2D.zoom_in(position - $Camera2D.get_camera_position())
if Input.is_action_pressed(“zoomout”):
$Camera2D.zoom_out(Vector2(0, 0))

Im just putting the script here, in future use the {} to show script

var currentzoom
var minzoom
var maxzoom
var zoomfactor = 0.75 # < 1 = zoomin; > 1 = zoomout
var transition_time = 0.25

func ready():
    maxzoom = zoom.x
    minzoom = maxzoom * zoom_factor

func zoomin(newoffset):
    transitioncamera(Vector2(minzoom, minzoom), newoffset)

func zoomout(newoffset):
    transitioncamera(Vector2(maxzoom, maxzoom), newoffset)

func transitioncamera(newzoom, newoffset):
    if newzoom != currentzoom:
    currentzoom = newzoom
    $Tween.interpolateproperty(self, "zoom", getzoom(), currentzoom, transitiontime, 
    Tween.TRANSLINEAR, Tween.EASEINOUT)
    $Tween.interpolateproperty(self, "offset", getoffset(), newoffset, transitiontime, 
    Tween.TRANSLINEAR, Tween.EASEIN_OUT)
    $Tween.start()

Player Script:

#The main code I'm using to move the camera:
func process(delta):
    mouseoffset = (getviewport().getmouseposition() - getviewport().size/2)
    camera.position = lerp(Vector2(), mouseoffset.normalized() * 250,
    mouseoffset.length() / 1000)

    if Input.isactionpressed("zoomin"):
        $Camera2D.zoomin(position - $Camera2D.getcameraposition())
        if Input.isactionpressed("zoomout"):
        $Camera2D.zoomout(Vector2(0, 0))

Amateur.game.dev. | 2021-04-23 23:06

Oh, thanks. I’m new to this forum, or posting on forums in general :confused:

OiKeTTLe | 2021-04-24 04:34

did it work?

Amateur.game.dev. | 2021-04-24 23:05

:bust_in_silhouette: Reply From: Amateur.game.dev.

You can actually set a maximum length the camera travels for. You find this in the “limit” section of the camera2D node. What it does is it makes the camera stop following the player after a certain point on either the x or the y axis has been passed. Try this and just fiddle around with it and you’ll get it.

You can edit this effect through script by using the [example] code:

$Camera2D.limit_left = -200
$Camera2D.limit_right = 200
$Camera2D.limit_bottom = 200
$Camera2D.limit_top = -200
$Camera2D.limit_smoothed = -200

Note that left won’t work unless it is a negative, same with top, and vice versa for bottom and right. I have not yet tested the smoothed method.