Offset troubles with mouse position using a camera2d

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

Hi, I’m actually trying to make a kind of ARPG script including buildings, but I’m having a weird trouble that I can’t seem to solve, I may be dumb, but better ask than doing nothing :

I’m pressing a button to load a build_bar which contains every buildings I can build, then when I click on one, it will show a preview of the building where my mouse is, I’ll update it for every frames to keep the preview under the mouse and then I’ll verify if the place is valid, and then I’ll build it.

But, when I added my camera 2D, the tower wasn’t on my mouse cursor at all, and in fact, if my character was moving right, the tower would follow… but not exactly. What I mean is it looks like the preview is connected somehow on the middle of the original viewport while following the movements of my mouse.

I’d like to have the tower follow only the mouse position… but can’t find it.

Here’s the code I use when I press a button to select a building to build :

func _initiate_build_mode(tower_type):
build_type = tower_type
build_mode = true
get_node("UI")._set_tower_preview(build_type, get_global_mouse_position())

Then, to update this building preview, I’m doing this under process :

func _process(delta):
if build_mode:

And the so called function :

func _update_tower_preview():
var mouse_position = get_global_mouse_position()
var current_tile = map_node.get_node("TowerExclusion").world_to_map(mouse_position)
var tile_position = map_node.get_node("TowerExclusion").map_to_world(current_tile)

if map_node.get_node("TowerExclusion").get_cellv(current_tile) == -1:
	get_node("UI")._update_tower_preview(tile_position, "66ffffff")
	build_valid = true
	build_location = tile_position + Vector2(32, 32)
	build_tile = current_tile
	build_valid = false

I’m using Vector2(32,32) to center my building on a 64x64 tile.

And once I left click to valid it, I’m doing this one :

func _verify_and_build():
if build_valid:
	##Test to verify players has enough resources
	var new_tower = load("res://Assets/Buildings/" + build_type + ".tscn").instance()
	new_tower.position = build_location
	new_tower.built = true
	new_tower.type = build_type
	map_node.get_node("Buildings").add_child(new_tower, true)
	map_node.get_node("TowerExclusion").set_cellv(build_tile, 2)

So far, it’s working really greatly. But then, I tried to use a Camera 2D on my character to make the viewport like it should be, and have a “bigger world”.

My “player” is concepted like this :

Kinematic Body 2D
Camera2D (Zoom on 0.75 x and 0.75 y )

My initial viewport at the moment is 1920 x 1080.

Hope it was clear enough… Thanks in advance for any help I could get !

It may be a good idea to show us the node tree of the scene, with the HUD and player’s scene included. The problem could come from the tower preview being the child of the wrong node.

Ertain | 2021-09-26 23:35

Ups, sorry I forgot. Was too focused trying to make a clear explanation of the code.

Here’s how my tree looks like :

Screenshot by Lightshot

Screenshot by Lightshot

it spawns at the right place, but maybe I shouldn’t add the child there anymore ? I really don’t understand how this works.

Rensae | 2021-09-27 10:13

When you call get_node("UI")._update_tower_preview(tile_position, "66ffffff") i suppose that’s a different method than the _update_tower_preview()you call in _process(), i believe that’s the actual piece of code that show the tower on the map, please share it.

Andrea | 2021-09-27 14:05

Here it is :

func _set_tower_preview(tower_type, mouse_position):
var drag_tower = load("res://Assets/Buildings/" + tower_type + ".tscn").instance()
drag_tower.modulate = Color("66ffffff")

var control =
control.add_child(drag_tower, true)
control.rect_position = mouse_position
add_child(control, true)
move_child(get_node("TowerPreview"), 0)

func _update_tower_preview(new_position, color):
	get_node("TowerPreview").rect_position = new_position
	if get_node("TowerPreview/DragTower").modulate != Color(color):
		get_node("TowerPreview/DragTower").modulate = Color(color)

Rensae | 2021-09-27 14:43

is the camera zoom set to anything different from (1,1)?

Andrea | 2021-09-27 15:36

Yes, it is 0.75x and 0.75y since I want to use a different view (I’m doing pixels, so screen wide would be too far from the art to see it)

I suppose that since you’re asking, it should be the issue ?

I should I approach this problem if I still want to zoom in the view of the player since otherwise, everything will just be too small ?

EDIT : I tried setting zoom 1 , 1 for camera2d, and it doesn’t solve anything

Rensae | 2021-09-27 16:15

I’m kinda out of ideas, sorry, you can share the project if you like, so we can have abetter look

Andrea | 2021-09-27 16:18

I’d share it if possible, but I’d like to keep my assets for myself, since I’m the one doing them, and I do suppose that sharing the project here means letting go of it, and then anyone could use it right ?

Rensae | 2021-09-27 18:01

yes, but you can create a smaller version of your project just to reproduce the issue we are talking about (while doing so you might as well understand what is the node that is causing troubles, and possibly fix it), and obviously you can remove the file from the sharing website later

Andrea | 2021-09-27 18:05

Well, sure, let me a minute, I’ll share it with you and then delete it from here and the website later

EDIT : Here’s the link to download the project without the assets I’ll use for the final, tell me when you got it

20.38 MB file on MEGA

Rensae | 2021-09-27 18:11

So i have a similar project in 3D and i don’t know why but decided to convert it to be 2D compatible and are now having the same issues as you. Been using Godot about a year now and have never had to use any node under Node2D.

Hopefully one of us will come up with a solution to what i believe is a Camera2D/viewport position problem

Wakatta | 2021-10-15 00:49

:bust_in_silhouette: Reply From: Andrea

Sorry, you edited the comment so i got no notification about it.
I just tried your project, i couldnt find an exact solution, but i understood the problem is in the TowerPreview being the child of the UI node.

This is not smart, because the UI is a canvas layer, and it is designed to be rendered on top of everything in front of the camera. I’m not sure how exactly the objects in the canvas layer are positionated relatively to the screen and world, but it appears they are moved around to follow the camera, infact if you correct the position with the camera position, like this

get_node("TowerPreview").rect_position = new_position-get_node("../Player/Camera2D").global_position

the tower is always at the same distance from the mouse, BUT the distance change when the screen dimensions change, so you should also find a way to correct that.

To be honest, the best thing would be to simply stop using a control node to show game objects, and make the preview child of the Map