Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Mouse Input Module (Revised)

Mouse Input Module (Revised)
Revision 1.2
based on Jaime 'Near Fantastica' Webster's system
Set_Pos feature
by Freakboy


Introduction
This is a basic module that you would use the mouse. With this system, you can detect left and right mouse button presses and the position of the mouse cursor when over the gamescreen. However, this system does not create a mouse graphic for your project. That, 'YOU' will have to do yourself.

Script
Code:
#==============================================================================
# ** Mouse Input Module (Revised)
#------------------------------------------------------------------------------
#   by DerVVulfman
#   version 1.2
#   08-18-2007
#------------------------------------------------------------------------------
#   Based on...
#   Mouse Input Module
#   by Near Fantastica
#------------------------------------------------------------------------------
#   Set_Pos feature by
#   Freakboy
#------------------------------------------------------------------------------
#
#   THE CALLS: 
#
#   Mouse.click?
#   This returns a true/false value  when you test whether a button is clicked.
#   The values you pass are 1 (for the left mouse button), 2 (for the right) or
#   3 (for the middle button).
#
#   Mouse.press?
#   This returns a true/false value  when you test  whether a button is pressed
#   and kept depressed.  The values you pass are 1 (for the left mouse button),
#   2 (for the right mouse button), or 3 (for the middle).
#
#   Mouse.pixels
#   This returns the  mouse's screen coordinates  in pixels.  Based on a screen
#   with a 640x480 dimension,  this returns an array of the mouse's position in
#   index values.  Calling Mouse.pixels returns both x & y positions  in a sin-
#   gle string,  but calling Mouse.pixels[0] returns the x position (0-639) and
#   calling Mouse.pixels[1]  returns  the y position (0-439).   If the mouse is
#   outside of the game's window region, this call returns nil.
#
#   Mouse.tiles
#   This returns  the mouse's screen  coordinates  in map tiles.   Based on the
#   system's 20x15 tile size,  this returns it in index values  (a 0-19 width & 
#   a 0-14 height).  This functions the same manner as Mouse.pixels.
#
#   Mouse.set_pos
#   This allows you  to forcefully position the mouse at an x/y position within
#   the game screen by pixel coordinates.  Given the game's normal screen width
#   of 640x480, adding:  Mouse.set_pos(320,240)  should position the mouse dead
#   center of the gaming window.
#
#   Mouse.update
#   Add this routine  into your update routines  to update  the mouse position.
#   It must be called otherwise you won't get valid mouse coordinates.
#
#==============================================================================

module Mouse
  @mouse_menu = 0
  #--------------------------------------------------------------------------
  # * Mouse Click
  #     button      : button
  #--------------------------------------------------------------------------
  def Mouse.click?(button)
    return true if @keys.include?(button)
    return false
  end  
  #--------------------------------------------------------------------------
  # * Mouse Pressed
  #     button      : button
  #--------------------------------------------------------------------------
  def Mouse.press?(button)
    return true if @press.include?(button)
    return false
  end
  #--------------------------------------------------------------------------
  # * Mouse Pressed
  #     button      : button
  #--------------------------------------------------------------------------
  def Mouse.area?(x, y, width=32, height=32)
    return false if @pos == nil
    return true if @pos[0] >= x and @pos[0] <= (x+width) and @pos[1] >= y and @pos[1] <= (y+height)
    return false
  end
  #--------------------------------------------------------------------------
  # * Mouse Pixel Position
  #--------------------------------------------------------------------------
  def Mouse.pixels
    return @pos == nil ? [0, 0] : @pos
  end
  #--------------------------------------------------------------------------
  # * Mouse Tile Position
  #--------------------------------------------------------------------------
  def Mouse.tiles
    return nil if @pos == nil
    x = @pos[0] / 32
    y = @pos[1] / 32
    return [x, y]
  end
  #--------------------------------------------------------------------------
  # * Set Mouse Position
  #-------------------------------------------------------------------------- 
  def Mouse.set_pos(x_pos=0, y_pos=0)
    width, height = Mouse.client_size
    if (x_pos.between?(0, width) && y_pos.between?(0, height))
      x = Mouse.client_pos[0] + x_pos; y = Mouse.client_pos[1] + y_pos
      Win32API.new('user32', 'SetCursorPos', 'NN', 'N').call(x, y)
    end
  end
  #--------------------------------------------------------------------------
  # * Mouse Update
  #--------------------------------------------------------------------------
  def Mouse.update
    @pos            = Mouse.pos
    @keys, @press   = [], []
    @keys.push(1)   if Win32API.new("user32","GetAsyncKeyState",['i'],'i').call(1) & 0X01 == 1
    @keys.push(2)   if Win32API.new("user32","GetAsyncKeyState",['i'],'i').call(2) & 0X01 == 1
    @keys.push(3)   if Win32API.new("user32","GetAsyncKeyState",['i'],'i').call(4) & 0X01 == 1
    @press.push(1)  if Win32API.new("user32","GetKeyState",['i'],'i').call(1) & 0X01 == 1
    @press.push(2)  if Win32API.new("user32","GetKeyState",['i'],'i').call(2) & 0X01 == 1
    @press.push(3)  if Win32API.new("user32","GetKeyState",['i'],'i').call(4) & 0X01 == 1
  end  
  #--------------------------------------------------------------------------
  # * Automatic functions below 
  #--------------------------------------------------------------------------
  #
  #--------------------------------------------------------------------------
  # * Obtain Mouse position in screen
  #--------------------------------------------------------------------------
  def Mouse.global_pos
    pos = [0, 0].pack('ll')
    if Win32API.new('user32', 'GetCursorPos', 'p', 'i').call(pos) != 0
      return pos.unpack('ll')
    else
      return nil
    end
  end
  #--------------------------------------------------------------------------
  # * Return Screen mouse position within game window
  #--------------------------------------------------------------------------
  def Mouse.pos
    x, y = Mouse.screen_to_client(*Mouse.global_pos)
    width, height = Mouse.client_size
    begin
      if (x >= 0 and y >= 0 and x < width and y < height)
        return x, y
      else
        return nil
      end
    rescue
      return nil
    end
  end
  #--------------------------------------------------------------------------
  #  * Pass Screen to Game System
  #--------------------------------------------------------------------------
  def Mouse.screen_to_client(x, y)
    return nil unless x and y
    pos = [x, y].pack('ll')
    if Win32API.new('user32', 'ScreenToClient', %w(l p), 'i').call(Mouse.hwnd, pos) != 0
      return pos.unpack('ll')
    else
      return nil
    end
  end
  #--------------------------------------------------------------------------
  # * Get Screen Window Handle
  #--------------------------------------------------------------------------
  def Mouse.hwnd
    game_name = "\0" * 256
    Win32API.new('kernel32', 'GetPrivateProfileStringA', %w(p p p p l p), 'l').call('Game','Title','',game_name,255,".\\Game.ini")
    game_name.delete!("\0")
    return Win32API.new('user32', 'FindWindowA', %w(p p), 'l').call('RGSS Player',game_name)
  end
  #--------------------------------------------------------------------------
  # * Get Game Window Size
  #--------------------------------------------------------------------------
  def Mouse.client_size
    rect = [0, 0, 0, 0].pack('l4')
    Win32API.new('user32', 'GetClientRect', %w(l p), 'i').call(Mouse.hwnd, rect)
    right, bottom = rect.unpack('l4')[2..3]
    return right, bottom
  end
  #--------------------------------------------------------------------------
  # * Get Window Position (RGSS Player)
  #--------------------------------------------------------------------------
  def Mouse.client_pos
    rect = [0, 0, 0, 0].pack('l4')
    Win32API.new('user32', 'GetWindowRect', %w(l p), 'i').call(Mouse.hwnd, rect)
    left, upper = rect.unpack('l4')[0..1]
    return left+4, upper+30
  end  
end


Instructions
This script is used to detect the mouse buttons being pressed and return the mouse position for use in your scripts... whether it is for a custom menu, movement system or point-n-click action battlesystem. This script alone accomplishes nothing unless you create a system that utilizes the calls within:

Syntax
Code:
if Mouse.click?('number') == true   #If the mouse button is pressed
if Mouse.press?('number') == true   #If the mouse butten is kept depressed
x = Mouse.pixels['index']           #Returns the x and/or y position in pixels
x = Mouse.tiles['index']            #Returns the x and/or y position in map tiles

Mouse.click?('number')
This returns a true/false value when you test whether a button is clicked. The values you pass are 1 (for the left mouse button) or 2 (for the right).

Mouse.press?('number')
This returns a true/false value when you test whether a button is pressed and kept depressed. The values you pass are 1 (for the left mouse button) or 2 (for the right mouse button).

Mouse.pixels
This returns the mouse's screen coordinates in pixels. Based on a screen with a 640x480 dimension, this returns an array of the mouse's position in index values. Calling Mouse.pixels returns both x & y positions in a single string, but calling Mouse.pixels[0] returns the x position (0-639) and calling Mouse.pixels[1] returns the y position (0-439). If the mouse is outside of the game's window region, this call returns nil.

Mouse.tiles
This returns the mouse's screen coordinates in map tiles. Based on the system's 20x15 tile size, this returns it in index values (an 0-19 width and an 0-14 height). This functions the same manner as Mouse.pixels.

Mouse.set_pos(x, y)
This allows you to forcefully position the mouse at an x/y position within the game screen by pixel coordinates. Given the game's normal screen width of 640x480, adding: Mouse.set_pos(320,240) should position the mouse dead center of the gaming window.

Mouse.update
Add this routine into your update routines to update the mouse position. It must be called otherwise you won't get valid mouse coordinates.

FAQ
Again, this system is used to detect mouse input but it is up to the end-user to create system(s) that use these functions.


Compatibility
As it creates a whole new MOUSE module, it should be compatible with nearly any system. The only exception being systems that also create their own MOUSE module that would use the same names... very rare.


Example Code
This small bit of code shows how to detect the RIGHT MOUSE button and detect the x and y position of the mouse while on the field map. This is only a scriptette in the most basic format.

Well, you got start somewhere. :thumb:

Requires the Mouse Input Module.
Code:
class Scene_Map
  #--------------------------------------------------------------------------
  # * update
  #--------------------------------------------------------------------------
  alias mickey_update update
  def update
    #Update Mouse
    Mouse.update
    print Mouse.pixels[0].to_s + ' / ' + Mouse.pixels[1].to_s   if Mouse.click?(2)
    #Original Call
    mickey_update
  end
end
 
To rataime:
I haven't seen your mouse system, but given your work... should be pretty good. :thumb:

To Freakboy:
Set mouse position? Nice. and compatible.

NF's Mouse Input #5? Think I had like number... 2? It's SDK? Since Mouse isn't an SDK altered class... that's weird... You found it though.

Well, least we now have mouse buttons now.
 
DerVVulfman;263679 said:
To Freakboy:
Set mouse position? Nice. and compatible.

Your welcome ^_^ and good to know it's compatible. Although, I've posted it several months ago and nobody seem to care. (no replies :-/)
 
Funny that you had no replies seeing that you supplied Near's mouse script v5. :no: Maybe because Near's script didn't have actual instructions for use in his script. The only instructions available were you easy-to use ones.

I'll include yours into the script as you suggested. :thumb: Thanks. Now all we need is something that limits the mouse so it can't go beyond pre-set borders like off of the gamescreen.
 
DerVVulfman;265302 said:
I'll include yours into the script as you suggested. :thumb: Thanks. Now all we need is something that limits the mouse so it can't go beyond pre-set borders like off of the gamescreen.

What about using the script I provided :)

Code:
if Mouse.x < 0
 Mouse.set_pos(0, Mouse.y)
end
if Mouse.y < 0
  Mouse.set_pos(Mouse.x, 0)
end

if Mouse.x > screen_width
 Mouse.set_pos(screen_width, Mouse.y)
end
if Mouse.y > screen_height
  Mouse.set_pos(screen_height, 0)
end
 
This script is absolutely freaking awesome.

The only bad thing is it doesn't work properly if you have the Aleworks input module installed. (It takes 2 seconds for it to recognise a click, and half the time doesn't do the operation you told it to.) Without AIM though it works perfectly.
 

arev

Sponsor

Nice and clean. Just two suggestions. You could edit the Mouse.tiles method to read the $game_map.display and represent the true tile coords on maps bigger than 20x15. Also you could put the mid mouse button to work. I've done it in the cybersam's version so you shouldn't have problems with that.

Oh yeah, if you could make the mouse wheel to work I'd praise you :D I remember Selwyn trying at my request, but unfortunately to no effect.
 

arev

Sponsor

In some cases the third button is implemented under the wheel, but I'd want the script to be able to read if the wheel is actually scrolled up/down.
 
Full Map Mouse Tiles... I've been thinking about that. Great for a point-n-click map feature I'd gather. As to the other... I'll ask you to check this new one out...
BUMP[/FONT]
to 1.2


It now encorporates the set_pos feature designed by Freakboy, but I hardwired the 'Win32API' call to reduce resource usage.

Also now includes (hopefully) the middle mouse button. Used a Win32Api book to figure out the buttons (Dan Appleman's Visual Basic 5.0 Programmer's Guide to the WIN32 API). Can anyone tell me why the 3rd/middle mouse button was designed to work by sending a '004' value instead of a '003'???

Well, you call 1 to test for the left, 2 for the right, 3 for the middle with this one. ;)
 
Something useful would also be seeing if you click a certain event. (I.e. if the tile you click on is a tile where an event is located).
 

arev

Sponsor

DVV: simply 3 is for something else (_CANCEL - don't know what it does though:p). It may have been disigned when the mouse didn't have the mid button yet :]
And how about that scroll thingy? Wuold you give it a try?

edit down: Thanks rataime, good to know :)
 
A bit offtopic, but whatever :

I think the middle button being 004 originates from the signals sent by the mouse. I did a little project a few years ago which was based on the understanding of the way mechanical mouses communicated with the computer (with oscilloscopes : fun stuff)

Each time you do something with the mouse, it send 3 bytes (ie 3*8 = 24 bits) to the computer. The 2 last bytes describe the mouse movement (X-Axis and Y-Axis) with values between 0 and 255. The first byte is set that way :

1st bit : 1 if the left button is pressed, 0 otherwise
2nd bit : 1 if the right button is pressed, 0 otherwise
3rd bit : 1 if the middle button is pressed, 0 otherwise

and 5 other bits (negative or positive axis movement, overflows)

If you press the left button, you can see that as 00000001 = 1
If you press the right button, you can see that as 00000010 = 2
If you press the middle button, you can see that as 00000100 = 4

If you have a Linux system, you can test that with 'hexdump /dev/mouse' (or 'hexdump /dev/input/mouse'). Just substract 8 to the result ('Always On' bit...).I don't know what the block is on OSX :s

There, you'll go to sleep slightly more geek tonight !
 
DerVVulfman;266111":zm23g0kw said:
Full Map Mouse Tiles... I've been thinking about that. Great for a point-n-click map feature I'd gather.

Near did this in his module. he called the method Mouse.grid. here it is:
Code:
  def Mouse.grid
    return nil if @pos == nil
    offsetx = $game_map.display_x / 4
    offsety = $game_map.display_y / 4
    x = (@pos[0] + offsetx) / 32
    y = (@pos[1] + offsety) / 32
    return [x, y]
  end

Also, the way you have your Mouse.tiles set up, if someone were using Selwyn's Resolution script, this would not operate correctly.
 
Just wandering as there seems to be a lot of mouse systems. What happened to Astro_mech's?

I think I have a demo of it somewhere. His had draggable options, so you could drag items from one window to another and that would result in whatever you programmed i think, like a potion to a team member would use it and so on.

If you could add that, that would be a nice feature.
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top