AkiMouse: An Akihabara Mouse Control Library

by Darius Kazemi on October 7th, 2010

I often see mouse control as a requested Akihabara feature, so I decided to write a JS file that you can include in any Akihabara project to add mouse control to your game.

First, download mouse.js and save it in the directory where your Akihabara project is. Then in your main game code, include mouse.js after all the Akihabara includes.

Next, add the special addMouseControl() function to your maingame.initialize function where all the other game objects are initialized. This creates an invisible object in your game that handles all the mouse control stuff.

  maingame.initializeGame = function() {
    addMouseControl();
    ...
   };

Finally, create a ‘mouse’ group for the mouse object to live in by adding it to your gbox.setGroups declaration.

function main() {
  gbox.setGroups(['mouse', 'object', 'game']);
  ...
}

And that’s it! AkiMouse is now running inside your game.

AkiMouse creates some global variables that you have access to at all times. It also provides some helper functions.

Variables

  • mouse.x: Current mouse x coordinate, relative to your game map. This works even with a scrolling camera implementation.
  • mouse.y: Current mouse y coordinate, relative to your game map. This works even with a scrolling camera implementation.
  • mouse.isDown: This is true whenever the mouse button is held down on the canvas.
  • mouse.isClicked: This is true for exactly 1 step after the mouse button transitions from down to up. You can use this to trigger code that fires once after a mouse click.
  • mouse.isDragging: This is true whenever an object is being dragged (see the dragCheck() helper function for more)
  • mouse.dragObject: This contains whatever object is being dragged right now. It is null if there is no object being dragged. You can use this to, for example, test for collisions with the object that is being dragged. (see the dragCheck() helper function for more)

Functions

  • mouse.dragCheck(): This should be placed in the first function of any Akihabara object (where all your step code goes). When this is inside the first function, the object can now be clicked and dragged. While the object is being dragged, mouse.dragObject contains a reference to this object and mouse.isDragging is true.
  • mouse.isColliding(object): Pass any object to this function and it will return true if the mouse is currently on top of the object.

Examples

You can see an example of the code in action. The left object can be clicked and dragged. The right object changes color when you click on it.

Here’s an example of a first function for an object that will be destroyed when you click on it.

    first: function() {
      if (mouse.isClicked && mouse.isColliding(this))
        gbox.trashObject(this); // an Akihabara function that destroys an object
      },

Here’s an example where the object is draggable:

    first: function() {
      mouse.dragCheck();
      },

Here’s an example where an object is destroyed if it touches the object that is currently being dragged:

    first: function() {
      if (mouse.dragObject != null) // first make sure there IS an object being dragged
        if (gbox.collides(this, mouse.dragObject)) // check if we collide with it
          gbox.trashObject(this); //destroy ourselves if we do
      },

If you want to spawn something where the mouse is, just create the object and set its x,y coordinates to mouse.x,mouse.y.


I added an object to demonstrate the destroy-on-touch-with-dragged-object behavior that Darius described above. ~Darren

{ 9 comments… read them below or add one }

KesieV October 8, 2010 at 1:26 AM

Seems that another painful chapter of Akihabara is going to an end. I’ve not checked the lib (I’m on a train with an iPhone :( ) but I’d like to add this to the default bundle asap. I just want to test that on touchscreen devices and eventually try to add support for them. It was the perfect “good news of the morning”! Thank you again!

Reply

Michel October 8, 2010 at 3:03 AM

This was working for me on my school browser but when I got home I noticed the clickable circle would only go to “frame 2” for, well, one frame before returning to the default yellow.

I fixed it by swapping these two lines:
if (this.upCount > 1) {mouse.isClicked = false; this.upCount = 0;}
if (mouse.isClicked) this.upCount += 1;

So this works for me:
if (mouse.isClicked) this.upCount += 1;
if (this.upCount > 1) {mouse.isClicked = false; this.upCount = 0;}

I also started hacking in some rudimentary touch support based on mouse.js but only got far enough to figure out that “gbox.pixelcollides” isn’t going to work with touch. At least not as far as I can tell. I made that circle change colour by touching anywhere on the screen though. I’d love to try and tackle full Apple device touch support on my break in two weeks.

Reply

Darren Torpey October 8, 2010 at 8:04 AM

Actually, what happened was that Darius made a quick one-line change (late at night) that the thought fixed a bug I was seeing, but which actually broke the code you reference above. I have now put the change back to restore the behavior described here.

Also, bear in mind you can follow changes to this code at: http://github.com/darrentorpey/akihabara_tutorials

Reply

Darius Kazemi October 8, 2010 at 10:07 AM

Thank you. And Kesiev is rigtht, once you figure out the different absolute/relative positioning stuff you should be good to go. The relevant code is

mouse.x = (event.layerX – tempCanvas.offsetLeft)/gbox._zoom + cam.x;
mouse.y = (event.layerY – tempCanvas.offsetTop)/gbox._zoom + cam.y;

which makes a lot of assumptions, assuming a desktop browser and standard containing HTML for the Aki game (so the game’s not in an iframe, for example)

Reply

KesieV October 8, 2010 at 11:22 AM

Another quick note: in Akimouse coords are always referred to the cam that is right for sprites and things that follow the camera but not for things that always on the screen, like gui elements. Could be nice to specify if I want absolute or relative coords as returned values and if the dragged element have to follow the cam.

Reply

KesieV October 8, 2010 at 6:50 AM

Just for not reinventing the wheel, I’ll leave the work to Michel ;)
Just a thing: touch coords are ever referred to the topleft corner of the screen. You’ve to subtract the absolute position of the canvas, if I remember well. Then I’ve seen that zoom level is not considered when calculating coords so proably the pointer position (or click) have to be divided for the zoom ratio.
Have a look to iphopad.js for getting touch positions and absolute coords of an objects, since uses them for implementing an onscreen virtual pad.

Reply

KesieV October 8, 2010 at 6:57 AM

Ow… the zoom comment was about the touches thing :)

Reply

MaurizioPz January 20, 2011 at 11:48 AM

Just a small correction
dragCheck() should be dragCheck(this) in the example. Otherwise it crashes (at least under firefox)

BTW great work! :-)

Reply

Darius Kazemi January 22, 2011 at 3:13 PM

Hmm… it’s working in both Chrome and Firefox for me.

Reply

Leave a Comment

{ 3 trackbacks }