How do I do Mouse inputs?

Started by zutokaza, October 19, 2016, 04:24:42 AM

Previous topic - Next topic
October 19, 2016, 04:24:42 AM Last Edit: October 19, 2016, 04:45:26 AM by zutokaza
I was wondering if I can have a simple script example for mouse input.
http://www.solarus-games.org/doc/latest/lua_api_input.html#lua_api_input_get_mouse_position

EX:
How would I do this?

Code ( lua) Select
local mouse_position = sol.input.get_mouse_position(96,128)

local pressed_right_mouse = sol.input.is_moutton_button_pressed("right")

if mouse_position and pressed_right_mouse == true then
  print("Pressed")
end
Solarus Works on ReactOS Opensource Windows OS

https://www.reactos.org/forum/viewtopic.php?f=2&t=14759&p=120616#p120616

What are you trying to do? sol.input.get_mouse_position() does not take any parameter, it returns the current position of the mouse.

Oh, I want to print "pressed" when clicking a specific area of the screen with the cursor.
Solarus Works on ReactOS Opensource Windows OS

https://www.reactos.org/forum/viewtopic.php?f=2&t=14759&p=120616#p120616

There is an event function that allows mouse input
It is parameter:on_mouse_button_pressed() i think
Check in the Lua api

Then you can do what you want from there

*parameter = the context (sol.main, game, map or a menu)

Wow, I goofed. I was in the wrong part of the documentation.
http://www.solarus-games.org/doc/latest/lua_api_game.html#lua_api_game_on_mouse_pressed

Code ( lua) Select
function sol.main:on_mouse_released(button)

  if button == "right" then
    print("right pressed")
  end
end


Okay, the mouse button clicking works, but how do I get the coordinates to work? Is it possible with a function?

Code ( lua) Select
function sol.main:on_mouse_released(button,x,y)

x = 10
y = 100

  if button == "right" then
    print("right pressed")
  end
end
Solarus Works on ReactOS Opensource Windows OS

https://www.reactos.org/forum/viewtopic.php?f=2&t=14759&p=120616#p120616

I think you are confused about how the coordinates work. x & y are the coordinates of where the player clicked, not where they have to click for the action to occur.

You probably want something more like the following:
Code (lua) Select

function sol.main:on_mouse_released(button,x,y)

    if button=="right" and x==10 and y==100 then
        print("right pressed")
    end
end


Although that code requires the player to click exactly on one pixel, which could be tricky to do. In all likelihood, you'd be specifying a range for x and y (i.e. x>=10 and x<=20).

Thank you llamazing!

The following code works when clicking in the upper left corner. I kinda wish there was a debug mode that would show an outline of the area, but maybe it can be done with 4 pieces of a block image? Min/max?

EX:

|````minX  ````|maxX
Two pieces split
|,,,,,,,minY  ,,,,,,,|maxY

Code ( lua) Select
function sol.main:on_mouse_pressed(button,x,y)

  if button == "left" and x <=50 and y<= 50 then
    print("left pressed")
  end

end
Solarus Works on ReactOS Opensource Windows OS

https://www.reactos.org/forum/viewtopic.php?f=2&t=14759&p=120616#p120616

October 21, 2016, 04:07:15 PM #7 Last Edit: October 21, 2016, 04:12:38 PM by MetalZelda
You can do better, for example, using left clic for multiple positions

Code (lua) Select

local handled = false

if button == "left" then -- Condition that englobe all event while left clicking

  -- Area between x[41; 59] and y[17;42], you can do this for a clickable hud or for custom systems
  if (x > 40 and x < 50) and (y > 16 and y < 43) then
   
    your code
   
    handled = true -- Want to make this event unique ?
  end
end

return handled


My though is, is a clickable menu doable, like Wind Waker HD / A Link Between Worlds , where you can drag and drop items on the fly while playing

And again, your function is registered as sol.main, which will be active as soon as the game starts

I think it might be possible.

click the item on pressed. (Hold it down)
Code ( lua) Select
on_mouse_press(button,x,y)

put the mouse over the location and release. This would activate a calculated image movement loop to the destination.
Code ( lua) Select
on_mouse_released(button,x,y)

The only problem with my method is how to get the image to follow the cursor....is there a way to have a custom cursor??? Might be a good feature to add to Solarus.

Solarus Works on ReactOS Opensource Windows OS

https://www.reactos.org/forum/viewtopic.php?f=2&t=14759&p=120616#p120616

To do drag/drop, you can start a timer when the player clicks down on the object in the on_mouse_pressed(button,x,y) event. Then the timer calls sol.input.get_mouse_position() repeatedly while it is running and each time draws the object at the current location of the cursor. Having the timer update at a rate of 10 times per second would probably be good enough.

Finally, when the on_mouse_released(button,x,y) event is detected the timer would be stopped, and then you could perform some action depending on the current location of the mouse (where the player dragged the object to).

Doesn't sol.input.get_mouse_position() just return the position of the mouse?

I can't find much on it in the documentation.
http://www.solarus-games.org/doc/latest/lua_api_input.html#lua_api_input_get_mouse_position

For example,

Code ( lua) Select
function sol.main:get_mouse_position(x,y)
   
end

Solarus Works on ReactOS Opensource Windows OS

https://www.reactos.org/forum/viewtopic.php?f=2&t=14759&p=120616#p120616

Quote from: zutokaza on October 24, 2016, 06:59:02 AM
Doesn't sol.input.get_mouse_position() just return the position of the mouse?

You'd be using get_mouse_position() to find the current coordinates of the mouse cursor every time the timer loops, and in the on_draw() function draw your image you want to drag at those saved coordinates.

The code would look something like this (though you could clean it up to add an offset depending where on the source image the mouse clicked to line it up with the cursor better):

Code (lua) Select

local my_menu = {}

local mouse_update_timer
local timer_delay = 100 --time in ms

local drag_surface --dragged image to draw at cursor
local drag_x,drag_y --last known mouse coordinates

local function mouse_update() --called by timer while dragging
drag_x,drag_y = sol.input.get_mouse_position()
return true --return true makes the timer repeat until canceled
end

function my_menu:on_mouse_pressed(button, x, y)
if button=="left" then
local obj_x,obj_y,obj_width,obj_height = source_obj:get_bounds()

--mouse pressed within source object
if x>=obj_x and x<obj_x+obj_width and y>=obj_y and y<obj_y+obj_height then
print"begin drag at source"

drag_surface = source_obj
drag_x,drag_y = x,y

--stop timer if running
if mouse_update_timer then
mouse_update_timer:stop()
mouse_update_timer = nil
end

--start new timer (endless loop every 100ms until mouse released)
mouse_update_timer = sol.timer.start(my_menu, timer_delay, mouse_update)
end
end
end

function my_menu:on_mouse_released(button, x, y)
if button=="left" then
local obj_x,obj_y,obj_width,obj_height = dest_obj:get_bounds()

--mouse released within bounds of destination object
if x>=obj_x and x<obj_x+obj_width and y>=obj_y and y<obj_y+obj_height then
print"dragged to destination"
end

--don't draw source_obj at cursor anymore
drag_surface = nil
drag_x,drag_y = nil,nil

--stop timer if running
if mouse_update_timer then
mouse_update_timer:stop()
mouse_update_timer = nil
end
end
end

function my_menu:on_draw(dst_surface)

--code to draw rest of menu here...

--draws drag_surface at cursor
if drag_surface then drag_surface:draw(dst_surface, drag_x, drag_y) end
end


If it looks choppy, you can reduce the timer delay to update the mouse coordinates at a faster rate.

October 24, 2016, 09:37:11 AM #12 Last Edit: October 24, 2016, 10:46:16 AM by Zefk
I decided to test the sol.input.get_mouse_position(). I did not add a timer, but it was fun clicking the image around.

The messy quick test code:
Code ( lua) Select
--Tell the script it is a map and to use game functions
local map = ...
local game = map:get_game()

--A table because I like tables and it prevents upvalue errors
local text_box = {

     x_place,
     y_place,
     place_x,
     place_y,
     num1_img = sol.surface.create("blinker.png"),
}

text_box.num1_place = true

function sol.main:on_mouse_released(button, x, y)
   if button == "left" then
     local drag_x,drag_y = sol.input.get_mouse_position()
     text_box.place_x = drag_x
     text_box.place_y = drag_y
     print("x,",text_box.place_x, "y",text_box.place_y)
   end
end

--The draw function for showing images
function sol.main:on_draw(screen)
   if text_box.num1_place == true then
     text_box.num1_img:draw(screen, text_box.place_x,text_box.place_y)
   end
end --end of draw function



I used a timer in a funny, but it drags. I added a non-funny better way.

Code ( lua) Select
--Tell the script it is a map and to use game functions
local map = ...
local game = map:get_game()

--A table because I like tables and it prevents upvalue errors
local text_box = {

     x_place,
     y_place,
     place_x,
     place_y,
     num1_img = sol.surface.create("blinker.png"),
}

local test
text_box.num1_place = true

local num_calls = 0
sol.timer.start(80, function()
  local drag_x,drag_y = sol.input.get_mouse_position()
  text_box.place_x = drag_x
  text_box.place_y = drag_y
  print("x,",text_box.place_x, "y",text_box.place_y)
  num_calls = num_calls + 1
  return num_calls < 10000000000000000000
end)

function sol.main:on_mouse_released(button, x, y)
--blank
end

--The draw function for showing images
function sol.main:on_draw(screen)
   if text_box.num1_place == true then
     text_box.num1_img:draw(screen, text_box.place_x,text_box.place_y)
   end
end --end of draw function


This would be better:
Code ( lua) Select
local num_calls = 1
sol.timer.start(80, function()
  local drag_x,drag_y = sol.input.get_mouse_position()
  text_box.place_x = drag_x
  text_box.place_y = drag_y
  print("x,",text_box.place_x, "y",text_box.place_y)
  num_calls = num_calls + 1
  return num_calls ~= 1
end)