How do I implement mouse input in my game?

From OHRRPGCE-Wiki
Jump to navigation Jump to search
The Mouse Options menu

For standard RPGs, there's nothing to do! Games will by default be totally playable using only the mouse (since version fufluns). You can move, activate NPCs, bring up the main menu, navigate menus and fight battles.

But mouse controls aren't enabled by default in older existing games, due to backwards compatibility. Turn them on in General Game Settings -> Controls: Mouse Options. There are many individual items; see the screenshot to the right. If you aren't scripting your own controls you probably should turn these all on.

If debug keys are enabled, you can also press F8 in-game and find Mouse Options near the bottom of the Debug Menu.


Scripting it[edit]

However, sometimes it's useful to script your own mouse input handling, for example if you want to create custom menus or a point-and-click game. Here are some examples of games (tagged "mouse only") that have scripted mouse controls. The rest of this article is about scripting.

Step 1: The script[edit]

Starting with the Callipygous stable release you can cause the normal mouse cursor to display in your game, which saves you the trouble of drawing one, and is usually far more responsive. If you go with this option, simply delete/ignore all the slice-related lines in the scripts in the rest of this article. You would use this script:

script, mouse setup, begin
  # Must be called before any other mouse command
  init mouse
  # Show the operating system's mouse cursor
  unhide mouse cursor
end

If on the other hand you want to draw the mouse yourself you would do this using a slice. Creating a slice looks like this:

global variable(1, mouseslice)

script, mouse setup, begin
  # Must be called before any other mouse command
  init mouse
  settag(tag:Mouse active, on)
  # Load the mouse graphic. Use any sprite type and spriteset number you want
  mouseslice := load walkabout sprite(4)
  # This causes the mouse to appear above textboxes
  move slice above(mouseslice, lookup slice(sl:textbox layer))
end

If using a slice, you would need to update its position continuously:

plotscript, mouse script, begin
  mouse setup
  # Infinite loop, yes, there's a reason
  while (true) do, begin
    set slice visible(mouseslice, checktag(tag:Mouse active) == on)
    put slice(mouseslice, mouse pixel x, mouse pixel y)
    # Let game.exe breathe
    wait
  end
end

This is the skeleton of the mouse control script, and doesn't do anything but move the cursor around the screen. Here's a breakdown of each line of the script:

global variable(1, mouseslice)

Create a new global variable. Change "1" to an unused ID number.

script, mouse setup, begin
  # Must be called before any other mouse command
  init mouse

Init mouse tells Game.exe that we intend to use the mouse, preventing it from doing its own conflicting handling of mouse input.

  settag(tag:Mouse active, on)

This tag will specify whether mouse-based controls should be active. Many games won't want to them to always be active. Lets start with them on.

  # Load the mouse graphic. Use any sprite type and spriteset number you want
  variable(mouseslice)
  mouseslice := load walkabout sprite(4)
  # This causes the mouse to appear above textboxes
  move slice above(mouseslice, lookup slice(sl:textbox layer))
end

This loads a sprite (specifically, the first frame of walkabout spriteset 4) and adjusts how is it displayed. load walkabout sprite can be replaced with other commands like load attack sprite to get a bigger cursor.

plotscript, mouse script, begin
  mouse setup
  # Infinite loop, yes, there's a reason
  while (true) do, begin

We're going to be updating the mouse continuously, so we need an infinite loop (you can add ways to break out of this loop if you need to for some reason)

    set slice visible(mouseslice, checktag(tag:Mouse active) == on)

This is optional. Many games don't want the mouse visible all the time. By turning OFF this tag, you can hide the mouse.

    put slice(mouseslice, mouse pixel x, mouse pixel y)

Since the cursor is just a slice, we use put slice to move it.

    # Let game.exe breathe
    wait

Infinite loops are finnicky, and you'll lock up Game.exe without this command.

  end
end

Step 2: Game Setup[edit]

Ok, the script is ready, now are you done? Not a chance! I haven't told you where to put it. It needs to be called in two places: the New Game script, and the Load Game script. It can either be set to be those scripts, or it can be called from inside them.

However, be warned. A script like this won't work as you expect:

plotscript, new game, begin
  init global variables # script to set stuff up
  mouse script # Init mouse stuff
  story cutscene # Show story
end

See, the mouse script (the version with the custom cursor) is an infinite loop, and as such will "shadow" any scripts after it. It should appear at the end of the New Game and Load Game scripts.

Step 3: Customizing the Script[edit]

Ok, script? Check. Script being called? Check. Ready? Nope!

Right now the mouse will show up, and will move around. However, nothing happens when you click! How can it? We haven't set it to do anything!

Let's add a few lines to mouse script: to check if the player is clicking on anything.

    # You can put an appropriate condition here
    if (checktag(tag:Mouse active)) then, begin
      if (mouse button(left button)) then, begin
        # Check what's been clicked
      end
    end

I added a simple if statement that gets triggered when the left mouse button (henceforth, LMB) is pressed. Inside, you need to check to see if the mouse is somewhere interesting. Here is the script revised to see if the mouse is clicking on an NPC with the ID 5:

plotscript, mouse script, begin
  mouse setup
  # Infinite loop, yes, there's a reason
  while (true) do, begin
    # You can put an appropriate condition here
    if (checktag(tag:Mouse active)) then, begin
      # In the next line, change the "0" to the ID of the mouse NPC
      put NPC (0, mouse pixel x + camera pixel x, mouse pixel y + camera pixel y)
      if (mouse button(left button)) then, begin
        variable (NPC, Num NPC, i)
        num NPC := NPC at pixel (mouse pixel x + camera pixel x, mouse pixel y + camera pixel y, get count)
        for (i,0,Num NPC -- 1) do, begin
          NPC := npc at pixel (mouse pixel x + camera pixel x, mouse pixel y + camera pixel y, i)
          if (get NPC ID(NPC) == 5) then, begin
            show text box(513)
            wait for text box
          end
        end
        # Check what's been clicked
      end
    end
    # Let game.exe breathe
    wait
  end
end

I'll explain the new section:

        variable (NPC, Num NPC, i)

We need a few variables. NPC is an NPC reference, Num NPC is the number of NPCs at the pixel where the mouse is, and i is a simple counter.

        num NPC := NPC at pixel (mouse pixel x + camera pixel x, mouse pixel y + camera pixel y, get count)

We should get the number of NPCs at that pixel. get count is a constant that causes NPC at pixel to return the number of NPCs.

        for (i,0,Num NPC -- 1) do, begin

As I said, we need to loop.

          NPC := npc at pixel (mouse pixel x + camera pixel x, mouse pixel y + camera pixel y, i)

Get one of the NPCs at that spot...

          if(get NPC ID(NPC) == 5) then, begin

... and see if it's the right kind.

            show text box(513)
            wait for text box

This is just a dummy event, which you're free to change to whatever you want.

          end
        end

And, close the blocks.

Closing Words[edit]

There's other mouse commands, but I think I'll end this now. As a review, here's the commands covered:

init mouse, mouse pixel X, mouse pixel Y, mouse button

I may expand this to cover the other two commands, put mouse and mouse region, but until then, ciao!