[SOLVED] Camera / world position / zoom doesnt seem to work

I’m trying to do something that should be simple but been at it for hours and hours, can somebody please see if they can provide a simple solution if possible (tried google and non stop back and forth with chatGPT but nothing seems to do it) , so all im trying to do (ignore the shocking graphics :slight_smile: ) is move my player (on click) from 1 flag to another,

However when I click the flags the “hitbox” always seems to be offset by quite a bit, the further the flag the worse it gets, it also changes position if I’m at different flags, I have a custom camera added with these settings which is whats probably knocking the world co-ords off

But no matter what I try cant seem to get the click boxes to the clicks correct, does anybody have a simple script / example I can use to do this?

Thanks

You can use this camera module:

local M = {}

local DISPLAY_WIDTH = sys.get_config_int("display.width")
local DISPLAY_HEIGHT = sys.get_config_int("display.height")

local WINDOW_WIDTH = DISPLAY_WIDTH
local WINDOW_HEIGHT = DISPLAY_HEIGHT
local DISPLAY_SCALE_X = 1
local DISPLAY_SCALE_Y = 1

function M.init()
	WINDOW_WIDTH, WINDOW_HEIGHT = window.get_size()
	DISPLAY_SCALE_X = WINDOW_WIDTH / DISPLAY_WIDTH
	DISPLAY_SCALE_Y = WINDOW_HEIGHT / DISPLAY_HEIGHT
end

--- convert screen to world coordinates taking into account
-- the view and projection of a specific camera
-- @param camera URL of camera to use for conversion
-- @param screen_x Screen x coordinate to convert
-- @param screen_y Screen y coordinate to convert
-- @param z optional z coordinate to pass through the conversion, defaults to 0
-- @return world_x The resulting world x coordinate of the screen coordinate
-- @return world_y The resulting world y coordinate of the screen coordinate
-- @return world_z The resulting world z coordinate of the screen coordinate
function M.screen_to_world(camera, screen_x, screen_y, z)
	local projection = go.get(camera, "projection")
	local view = go.get(camera, "view")
	local w, h = window.get_size()
	-- The window.get_size() function will return the scaled window size,
	-- ie taking into account display scaling (Retina screens on macOS for
	-- instance). We need to adjust for display scaling in our calculation.
	w = w / (w / DISPLAY_WIDTH)
	h = h / (h / DISPLAY_HEIGHT)

	-- https://defold.com/manuals/camera/#converting-mouse-to-world-coordinates
	local inv = vmath.inv(projection * view)
	local x = (2 * screen_x / w) - 1
	local y = (2 * screen_y / h) - 1
	local x1 = x * inv.m00 + y * inv.m01 + z * inv.m02 + inv.m03
	local y1 = x * inv.m10 + y * inv.m11 + z * inv.m12 + inv.m13
	return x1, y1, z or 0
end


--- Adjust camera zoom so that the original area covered by
-- display width and height of game.project is always visible
-- this mode will reveal more content to the sides or above and
-- below if the aspect ratio is different. Call this function
-- any time the window size changes (or every frame if you wish)
-- this is the "Fixed Fit Projection" from the manual:
-- https://defold.com/manuals/render/#fixed-fit-projection
-- @param camera URL of camera to use for conversion
function M.use_fixed_fit_projection(camera)
	local w, h = window.get_size()
	-- take into display scaling (eg retina)
	w = w / DISPLAY_SCALE_X
	h = h / DISPLAY_SCALE_Y
	-- calculate the zoom so that the entire initial area of game project
	-- is visible
	local zoom = math.min(w / DISPLAY_WIDTH, h / DISPLAY_HEIGHT)
	go.set(camera, "orthographic_zoom", zoom)
end

return M

and use it to get the correct world position like this on the on input function:

local worldx, worldy = camera.screen_to_world("camera url here", action.x, action.y, 0)

Since you need to click on flags, checking for the closest flag position could be a solution for your case but I need to know more about the logic you use to be able to provide a better solution

2 Likes

thanks will give that a try, I dont really have any logic as yet, as none of it has worked, this was the first thing I tried to do but ran into so many issues soon as I added my own camera.

I’m even happy to start from scratch, all im mainly trying to do is have the ability to zoom the camera out (this doesnt need to change and go in / out etc, just 0.5 for example will do, then be able to click the locations / flags and the player move to them.

At the moment (i think due to the camera) the click boxes dont seem to be on the flags they are always offset and move about depending on the position of the player, either that or the place I’m clicking with my mouse is offset to the camera

edit: seems to be working fine with the module / code above, thanks :slight_smile:

1 Like