Input screen position to world position

Hey there,

I changed my render script to center the camera and zoom in if the screen has a larger resolution than the game or zoom out if the screen has a smaller one according to this thread:


The update function of the render script looks like this:

function update(self)
  width_original = render.get_width()
  height_original = render.get_height()
  width_current = render.get_window_width()
  height_current = render.get_window_height()
  zoom_factor = math.min(width_current / width_original, height_current / height_original)
  width_scaled = width_original * zoom_factor
  height_scaled = height_original * zoom_factor

  render.set_depth_mask(true)
  render.clear({[render.BUFFER_COLOR_BIT] = self.clear_color, [render.BUFFER_DEPTH_BIT] = 1,[render.BUFFER_STENCIL_BIT] = 0})

  render.set_viewport((width_current - width_scaled) / 2, (height_current - height_scaled) / 2, width_scaled, height_scaled)

  render.set_view(self.view)

  render.set_depth_mask(false)
  render.disable_state(render.STATE_DEPTH_TEST)
  render.disable_state(render.STATE_STENCIL_TEST)
  render.enable_state(render.STATE_BLEND)
  render.set_blend_func(render.BLEND_SRC_ALPHA, render.BLEND_ONE_MINUS_SRC_ALPHA)
  render.disable_state(render.STATE_CULL_FACE)

  render.set_projection(vmath.matrix4_orthographic(0, width_original, 0, height_original, -1, 1))

  render.draw(self.tile_pred)
  render.draw(self.particle_pred)

  render.draw_debug3d()

  render.set_view(vmath.matrix4())

  render.enable_state(render.STATE_STENCIL_TEST)

  render.draw(self.gui_pred)
  render.draw(self.text_pred)

  render.disable_state(render.STATE_STENCIL_TEST)
  render.set_depth_mask(false)

  render.draw_debug2d()
end

Now the question is how to transform the x and y or screen_x and screen_y components of the passed action in the on_input function to world space (x should be negative if left from the game screen or greater than 720 if it’s right from it, y should be negative if below the game screen and greater than 1280 if it’s above it).

Kindly regards
André

What if you store the relevant values from the render script (scaled width, height etc) in a Lua module and let that Lua module have a function that translates input coordinates to scaled coordinates that matches your render script? I do something similar in my example with a fixed aspect ratio render script.

Yes thats what I did and I managed it to calculate the correct coordinates of the input screen coordinates with a custom Lua module:

function m.action_to_position(action)
  local width_projected = width_current / zoom_factor
  local height_projected = height_current / zoom_factor

  return vmath.vector3(action.screen_x / zoom_factor
    - (width_projected - width_original) / 2,
    action.screen_y / zoom_factor
    - (height_projected - height_original) / 2, 0)
end

The problem still is that these calculated positions seem to be incorrect for the gui.pick_node function since it did not return true when the cursor / touch position was on the node. I think I did not understand the way how pick_node exactly evaluates a position against a node.
So finally I wrote my own function in the module for checking the input position which works well:

function m.in_node(node, pos)
  local p = gui.get_position(node)
  local s = gui.get_size(node)

  s.x = s.x / 2
  s.y = s.y / 2
  return pos.x >= p.x - s.x and pos.x <= p.x + s.x
  and pos.y >= p.y - s.y and pos.y <= p.y + s.y
end