Reputation: 1
The idea: When you zoom in, it should zoom towards the mouse. In some ways, it does, but it snaps and sometimes zooms in the wrong direction.
I tried zooming in and out (as seen in the linked video). For example, zooming in on a corner of the viewport, then zooming out, and then moving my mouse to the other side (in the video, it's the right side), it zooms in to the left.
Source Code:
extends Node2D
var camera : Camera2D
var zoom_min = null
var zoom_max = Vector2(3, 3)
var zoom_speed = Vector2(0.2, 0.2)
var des_zoom = null
# Called when the node enters the scene tree for the first time.
func _ready():
# Init the Map from the MapData
var Map = await load(MapData.MapFile).instantiate()
Map.name = "Map"
print_rich("[color=green]Map Loaded: [/color]", Map.name, "\n")
# Add the Map node to the scene tree
add_child(Map)
### Map.position = Vector2(-MapData.map_middlepoint[0], -MapData.map_middlepoint[1])
# Create and configure the Camera2D node
camera = Camera2D.new()
# Calculate the required zoom level based on the map's height and the viewport height
var viewport_size = get_viewport_rect().size
var map_height = MapData.map_middlepoint[1] * 2
var zoom_level = viewport_size.y / map_height
# Apply the calculated zoom level to the camera
camera.zoom = Vector2(zoom_level, zoom_level)
zoom_min = Vector2(zoom_level, zoom_level)
des_zoom = Vector2(zoom_level, zoom_level)
# Calculate the aspect ratio of the viewport
var viewport_aspect_ratio = viewport_size.x / viewport_size.y
# Calculate the extra space needed on the left and right sides
var extra_space = (MapData.map_middlepoint[1] * viewport_aspect_ratio)
print_rich("[color=yellow]Extra Space:[/color] ", extra_space)
# Setting camera position to the middle of the map
camera.position = MapData.map_middlepoint # camera starting position
# Setting limits for the camera with extra space on the left and right sides
camera.limit_left = -extra_space + MapData.map_middlepoint[0]
camera.limit_top = 0
camera.limit_right = extra_space + MapData.map_middlepoint[0]
camera.limit_bottom = MapData.map_middlepoint[1] * 2
# Add the Camera2D node to the scene tree
add_child(camera)
camera.make_current() # Make this camera the current camera
# Print the scene tree
print_tree_pretty()
func _process(delta):
camera.zoom = lerp(camera.zoom, des_zoom, 0.1)
# Get the mouse position
### var camera_position = camera.get_global_position()
### print_rich("[color=yellow]Camera Position:[/color] ", camera_position, "\n")
func _input(event):
if event is InputEventMouseButton:
if Input.is_mouse_button_pressed(MOUSE_BUTTON_WHEEL_DOWN):
if des_zoom > zoom_min:
des_zoom -= zoom_speed
var mouse_position = get_global_mouse_position()
print_rich("[color=yellow]Mouse Position (Zoom Out):[/color] ", mouse_position)
var target_position = lerp(camera.position, mouse_position, 0.2)
target_position.x = clamp(target_position.x, camera.limit_left, camera.limit_right)
target_position.y = clamp(target_position.y, camera.limit_top, camera.limit_bottom)
print_rich("[color=yellow]Target Position (Zoom Out):[/color] ", target_position)
camera.position = target_position
if Input.is_mouse_button_pressed(MOUSE_BUTTON_WHEEL_UP):
if des_zoom < zoom_max:
des_zoom += zoom_speed
var mouse_position = get_global_mouse_position()
print_rich("[color=yellow]Mouse Position (Zoom In):[/color] ", mouse_position)
var target_position = lerp(camera.position, mouse_position, 0.2)
target_position.x = clamp(target_position.x, camera.limit_left, camera.limit_right)
target_position.y = clamp(target_position.y, camera.limit_top, camera.limit_bottom)
print_rich("[color=yellow]Target Position (Zoom In):[/color] ", target_position)
camera.position = target_position
Upvotes: 0
Views: 50
Reputation: 31
The issue mainly stems from calculating target_position
from camera.position
. You are assuming that camera.position
will be within the camera's limits (a very reasonable assumption), but the reality is that camera.position
can be literally anything.
Explanation of what you see in the video: You are first moving camera.position
to the top-left corner by zooming in and out a lot at that location. Then, as you zoom in on the top-right corner, target_position
is first set to 20% between the top-left and top-right corner, then on the next mouse wheel input, another 20% closer, and so on.
Here is what the official engine documentation has to say about this:
Note that the Camera2D node's position doesn't represent the actual position of the screen, which may differ due to applied smoothing or limits. You can use get_screen_center_position to get the real position.
Try using get_screen_center_position
like the docs mention. In other words, replace var target_position = lerp(camera.position, mouse_position, 0.2)
with var target_position = lerp(camera.get_screen_center_position(), mouse_position, 0.2)
.
Upvotes: 0