I’m running into lots and lots of issues trying to get just the right setup for a pixel art game. I want both the world and the GUI to scale with the window, but only at whole-level increments. After some work, I’ve managed to get that set up just right.
I’m using the defold orthographic framework for the camera, but I had to modify the render script to get the GUI to lock to the view instead of the window:
-- draw world per camera
local cameras = camera.get_cameras()
if #cameras > 0 then
render.disable_state(render.STATE_DEPTH_TEST)
render.disable_state(render.STATE_CULL_FACE)
render.disable_state(render.STATE_STENCIL_TEST)
for _,camera_id in ipairs(cameras) do
local viewport = camera.get_viewport(camera_id)
render.set_viewport(viewport.x, viewport.y, viewport.z, viewport.w)
render.set_view(camera.get_view(camera_id))
render.set_projection(camera.get_projection(camera_id))
render.draw(self.tile_pred)
render.draw(self.particle_pred)
render.draw_debug3d()
end
-- draw gui in game space using an orthographic projection
render.disable_state(render.STATE_DEPTH_TEST)
render.disable_state(render.STATE_CULL_FACE)
render.enable_state(render.STATE_STENCIL_TEST)
--local camera_id = cameras[1]
--local viewport = camera.get_viewport(camera_id)
--render.set_viewport(viewport.x, viewport.y, viewport.z, viewport.w)
--render.set_view(camera.get_view(camera_id))
--render.set_projection(camera.get_projection(camera_id))
render.draw(self.gui_pred)
render.draw(self.text_pred)
end
(commented out some lines that weren’t doing anything)
For the camera I’ve got the projection set to FIXED_ZOOM and it’s working great, visually. The GUI stays in the right place even when I expand the window.
My problem right now, though, is getting the GUI interactable. Since I’m rendering it scaled to the view instead of the window, the targets are off. ALSO I have a retina screen, which adds another wrinkle to things.
I’ve tried so many combinations of camera.screen_to_world
and camera.window_to_world
and camera.world_to_screen
and while I can get it to work when the window’s at its default size, as soon as it’s resized, everything is off. And I can’t for the life of me wrap my head around what I need to do to convert the action
coordinates to the correct values.
This is what I have currently:
function convert_action_to_world(action)
local cameras = camera.get_cameras()
if #cameras > 0 and action.x and action.y then
local dpi_ratio = get_scaling_factor()
local WINDOW_WIDTH, WINDOW_HEIGHT = camera.get_window_size()
WINDOW_WIDTH = WINDOW_WIDTH / dpi_ratio
WINDOW_HEIGHT = WINDOW_HEIGHT / dpi_ratio
local centerX, centerY = WINDOW_WIDTH / 2, WINDOW_HEIGHT/2
local window = {x=0, y=0, w=WINDOW_WIDTH, h=WINDOW_HEIGHT}
local DISPLAY_WIDTH, DISPLAY_HEIGHT = camera.get_display_size()
local display = {x=centerX - DISPLAY_WIDTH/2, y=centerY - DISPLAY_HEIGHT/2, w=DISPLAY_WIDTH, h=DISPLAY_HEIGHT}
local camera_id = cameras[1]
local p = vmath.vector3(action.x, action.y, 0)
p = p / dpi_ratio
return p
end
return nil
end
This solution doesn’t use any of the orthographic coordinate conversion methods, but it’s at least easier for me to follow what it’s doing. But it has the same problem as all the other approaches I’ve tried – as soon as I resize the window, the mouse/action coordinates don’t line up with the buttons.
Help?