I have a crosshair game object (not a child of the player or anything) with a sprite inside it, and this script:
function init(self)
-- make sure the script will receive user input
msg.post(".", "acquire_input_focus")
end
function on_input(self, action_id, action)
if not action_id then --this is the id for mouse movement
local cursorX = action.x --sets the coordinates of the mouse input to variables
local cursorY = action.y
local cursorposition = vmath.vector3(cursorX, cursorY, 500) -- assigns the coordinates to a variable (500 on the z axis so it its always on top of other game objects)
go.set_position(cursorposition)
end
end
Im using a camera that follows the player (2d, with the camera having orthographic projection turned on), and when i try to move my cursor around to somewhere outside the range of world coordinates (1920x1080), it stops at the max x and y or min x and y coordinates. I understand that this is because i am setting the game object to the screen coordinates of the mouse input (1920x1080 maximum), but i cant find any way to get the mouse coordinates in the world. I’d greatly appreciate some help and im very new to both lua and defold. Let me know if you need more info. ty
Incase it’s also relevant, this is the script for the player’s aiming:
function init(self)
msg.post(".", "acquire_input_focus")--ensures the script gets input
end
local function look_at(target_position)
local my_position = go.get_position()--gets player's own position
local angle = math.atan2(my_position.x - target_position.x, target_position.y - my_position.y)-- calculates the angle that this object has to rotate to look at the target position
go.set_rotation(vmath.quat_rotation_z(angle))-- sets rotation as a quaternion
end
function on_input(self, action_id, action)
if not action_id then--id for mouse movement is "null"
self.target_position = vmath.vector3(action.x, action.y, 0)-- sets the cursor position to be the target position
look_at(self.target_position)-- rotate this object to look at the target position
end
end
function update(self, dt)
look_at(self.target_position)-- updates rotation constantly
end
Thanks for the assistance, but after trying this script:
local DISPLAY_WIDTH = sys.get_config_int("display.width")
local DISPLAY_HEIGHT = sys.get_config_int("display.height")
local function screen_to_world(x, y, z, camera)
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 taking into account display scaling
w = w / (w / DISPLAY_WIDTH)
h = h / (h / DISPLAY_HEIGHT)
local inv = vmath.inv(projection * view)
x = (2 * x / w) - 1
y = (2 * y / h) - 1
z = (2 * z) - 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
local z1 = x * inv.m20 + y * inv.m21 + z * inv.m22 + inv.m23
return x1, y1, z1
end
function init(self)
-- make sure the script will receive user input
msg.post(".", "acquire_input_focus")
end
function on_input(self, action_id, action)
if not action_id then --this is the id for mouse movement
local cursorX = action.x --sets the coordinates of the mouse input to variables
local cursorY = action.y
local cursorpositionscreen = vmath.vector3(cursorX, cursorY, 500) -- assigns the coordinates to a variable (500 on the z axis so it its always on top of other game objects)
local cursorpositionworld = screen_to_world(cursorposition)
go.set_position(cursorpositionworld)
end
end
I get the exact same issue as i did before. Im unsure as to what i’ve done wrong as i used a new variable to double check that the screen_to_world() function is returning coordinates
(Side question, how do i put the code into its own window thing on this website?)
As far as i can tell, its the same function as the example you sent me. How would i go about sharing my project?
EDIT:
Actually, it appears that my old crosshair script was running despite me replacing the script path with the new one in the game object. Having run it again, i get “attempt to index local ‘target_position’ (a nil value)” in my aiming script
function init(self)
msg.post(".", "acquire_input_focus")--ensures the script gets input
end
local function look_at(target_position)
local my_position = go.get_position()--gets player's own position
local angle = math.atan2(my_position.x - target_position.x, target_position.y - my_position.y)-- calculates the angle that this object has to rotate to look at the target position
go.set_rotation(vmath.quat_rotation_z(angle))-- sets rotation as a quaternion
end
function on_input(self, action_id, action)
if not action_id then--id for mouse movement is "null"
self.target_position = vmath.vector3(action.x, action.y, 0)-- sets the cursor position to be the target position
look_at(self.target_position)-- rotate this object to look at the target position
end
end
function update(self, dt)
look_at(self.target_position)-- updates rotation constantly
end
but this only happens with the new crosshair script, not my old crosshair script. As far as i can tell, neither should have an impact on the aiming script as i dont think they’re interacting, but im guessing i must be wrong
ty, does this: “/crosshair#CrosshairV2’ does not have any property called ‘projection’” mean that i need to change the go.get(camera, “projection”) and view lines to the url of the camera or something? Im unsure. Sorry to be a pain
Been really annoying trying to figure this out, thank you for all your help. In case anyone wants to do the same thing, this is what i ended up with.
cursor script:
local DISPLAY_WIDTH = sys.get_config_int("display.width")
local DISPLAY_HEIGHT = sys.get_config_int("display.height")
local function screen_to_world(x, y, z, camera)--function that converts screen coordinates into world coordinates
local projection = go.get("/camera#camera", "projection")
local view = go.get("/camera#camera", "view")
local w, h = window.get_size()
-- The window.get_size() function will return the scaled window size taking into account display scaling
w = w / (w / DISPLAY_WIDTH)
h = h / (h / DISPLAY_HEIGHT)
local inv = vmath.inv(projection * view)
x = (2 * x / w) - 1
y = (2 * y / h) - 1
z = (2 * z) - 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
local z1 = x * inv.m20 + y * inv.m21 + z * inv.m22 + inv.m23
return x1, y1, z1
end
function init(self)
msg.post(".", "acquire_input_focus")-- makes sure the script will receive user input
self.vel = vmath.vector3()
sys.set_update_frequency(60)--fps cap
end
function on_input(self, action_id, action)
if not action_id or action_id == hash("touch") then
local worldx, worldy = screen_to_world(action.x, action.y, 0, "/camera#camera")-- converts mouse/touch screen position to world position
local world = vmath.vector3(worldx, worldy, 500)-- updates cursor position to the world position of mouse/touch position
go.set_position(world)
end
if action_id == hash("up") then--these just ensure the cursor moves when the player moves
self.vel.y = 150
elseif action_id == hash("down") then
self.vel.y = -150
elseif action_id == hash("left") then
self.vel.x = -150
elseif action_id == hash("right") then
self.vel.x = 150
end
end
function update(self, dt)
local pos = go.get_position()
pos = pos + self.vel * dt
go.set_position(pos)
self.vel.x = 0
self.vel.y = 0
end
Aiming script:
function init(self)
msg.post(".", "acquire_input_focus")--ensures the script gets input
self.target_position = vmath.vector3()
end
local DISPLAY_WIDTH = sys.get_config_int("display.width")
local DISPLAY_HEIGHT = sys.get_config_int("display.height")
local function screen_to_world(x, y, z, camera)--function that converts screen coordinates into world coordinates
local projection = go.get("/camera#camera", "projection")
local view = go.get("/camera#camera", "view")
local w, h = window.get_size()
-- The window.get_size() function will return the scaled window size taking into account display scaling
w = w / (w / DISPLAY_WIDTH)
h = h / (h / DISPLAY_HEIGHT)
local inv = vmath.inv(projection * view)
x = (2 * x / w) - 1
y = (2 * y / h) - 1
z = (2 * z) - 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
local z1 = x * inv.m20 + y * inv.m21 + z * inv.m22 + inv.m23
return x1, y1, z1
end
local function look_at(target_position)
local my_position = go.get_position()--gets player's own position
local angle = math.atan2(my_position.x - target_position.x, target_position.y - my_position.y)-- calculates the angle that this object has to rotate to look at the target position
go.set_rotation(vmath.quat_rotation_z(angle))-- sets rotation as a quaternion
end
function update(self, dt)
local cursorpos = go.get_position("crosshair")
look_at(cursorpos)
end