Trap a Mouse Cursor for PC Gaming

2,754

32

10

Published

Introduction: Trap a Mouse Cursor for PC Gaming

About: My name is Nathan Ramanathan, but my friends call me Nathan^2, you know because my first name is in my last name. I am 18 years old and took the interest in tinkering with Arduino when I was 14.

picture

picture

ll source code can be found on https://github.com/nathanRamaNoodles/AgarioJoyController


The Gamer's Issue

When playing games like Agar.io, slither.io, Cose.io, and other games that require a mouse to move the player around 360°, you feel like there's got to be an alternative to a gaming Mouse. In fact, you can lose accuracy, when you have extra space on your screen for your mouse to travel. It would be nice to keep the mouse in a small environment. And that's where the "hacked Wii nunchuck" comes into play. This project uses Arduino, AutoHotkey, and Nintendo.

Also since I am using a Wii nunchuck, I will take advantage of its accelerometer and other controls to make it work in Agario, Slitherio, Minecraft and as...A REGULAR MOUSE.

Here is a video of it in action showing all its features.

All these Controls can be found at the last step of this Instructable.


I will be using Cose.io for demonstration purposes.

Before Hack

*I made the mouse a circle so it can be easier to see while gaming*

As you can see, the mouse travels across the screen in a mess, which is bad for accuracy in gaming.

After Hack

When we're done with this project, this is what the result will be...a perfect circle for the mouse cursor to be trapped in.


Theory(Trap the mouse cursor)

After months of learning new programming languages, I found out a way to limit a mouse within any shape to my desire. In this example, I decided to trap the mouse cursor inside a Circle.

Mouse Trapped in circle

Step 1: Gather Materials

You will need the following:

  1. Arduino Pro Micro(5V or 3.3V)
  2. A Wii Nunchuck
  3. Four Jumper wires
  4. A micro USB cable
  5. A Windows Computer(Sorry Mac/Linux users)

Unfortunately, AutoHotKey only works for Windows.

For the Arduino Pro micro, I always find myself choosing the wrong micro USB cable, so you should use a data micro-USB cable. It is because the Arduino Pro micro requires a serial connection to communicate to the computer and be recognized as an HID(Human interface device).

Step 2: Connect Nunchuck to Pro-Micro

picture

Connections

Nunchuck ->Pro Micro

_________________________________________________

SDA(Data) -> Pin D2

SCL(Clock)-> Pin D3

VCC -> VCC

GND -> GND

_________________________________________________

I originally thought sticking the jumper wires into the socket of the nunchuck would be a bad idea...But turns out it's a simple and cheap way to getting the job done. But later on, I will be getting a wii nunchuck adapter from ebay, as the jumper wires will eventually break the sockets.

Step 3: Upload Code to Pro-Micro

picture

If you haven't set up the pro micro with your computer yet, follow the tutorial made by Sparkfun, the creators of the pro micro. Then you can continue back here.

Upload the code below to the Arduino pro micro using the arduino software.

<p>/*<br>   NunchuckPrint</p><p>   2007 Tod E. Kurt, <a href="http://todbot.com/blog/"> <a> http://todbot.com/blog/</a><p> ></p><p>   Change log:</p><p>      Mark Tashiro -    Changed Wire.read to Wire.write
                        Changed Wire.receive to Wire.read
                        Added code for servos</p><p>*/
//parameters for wii's joystick.  This varies for every nunchuck, so use serial monitor to check.</p><p>#define xMin 25
#define xMax 226
#define yMin 36
#define yMax 224
int centerX = 120;
int centerY = 137;
#define radius 100 //radius for square
const int deadzone = 10;
//If you want to use the two buttons on the nunchuck as keyboard inputs
char zButton = ' ';
char cButton = 'w';</p><p>#include 
#include 
#include 
#include 
Servo myServo;
unsigned long pMillis = 0;
unsigned long secMillis = 0;
unsigned long mouseioMillis = 0;
unsigned long scrollXMillis = 0;
unsigned long scrollYMillis = 0;
unsigned long hitMillis = 0;
bool scrollMode = false;
bool scrollModeTwo = false;
int counting = 1;
bool change = false;
bool previous = false;
bool escape = false;
// parameters for reading the joystick:
// parameters for reading the joystick:
int range = 12;               // output range of X or Y movement
const int mouseioDelay = 7;
const int gameioDelay = 1;
int responseDelay = gameioDelay;        // response delay of the mouse, in ms
int threshold = range / 4;  // resting threshold
int center = range / 2;     // resting position value</p><p>boolean mouseIsActive = true;    // whether or not to control the mouse</p><p>bool c = false;
bool z = false;
int countTwo = 0;
static uint8_t nunchuck_buf[6];   // array to store nunchuck data,
unsigned long dataMillis = 0;
int xReading;
int yReading;
bool action1;
bool action2;
unsigned long action1Millis = 0;
unsigned long action2Millis = 0;
unsigned long allActionMillis = 0;</p><p>bool game1 = false;
bool game2 = false;
unsigned long game1Millis = 0;
unsigned long game2Millis = 0;
unsigned long allGameMillis = 0;
bool slitherio = false;</p><p>bool mouse1 = false;
bool mouse2 = false;
unsigned long mouse1Millis = 0;
unsigned long mouse2Millis = 0;
unsigned long allMouseMillis = 0;
bool mouseio = false;
void setup()
{
  Serial.begin(115200);  nunchuck_init(); // send the initilization handshake
  Serial.println ("Finished setup\n");
  Mouse.begin();
  myServo.attach(10);
  Keyboard.begin();</p><p>}</p><p>void loop()
{
  unsigned long cMillis = millis();
  nunchuck_get_data();
  int xAxis = nunchuck_buf[0];
  int yAxis = nunchuck_buf[1];
  int xReading = readAxis(xAxis, cMillis);
  change = true;
  int yReading = readAxis(yAxis, cMillis);
  change = false;
  if (cMillis - pMillis >= responseDelay) {
    if (!scrollModeTwo && !scrollMode && mouseio && mouseIsActive) {
      Mouse.move(xReading, yReading);
    }
    else if (!mouseio) {
      Mouse.move(xReading, yReading);
    }
    pMillis = cMillis;
  }
  if (!scrollMode && !scrollModeTwo && !mouseio && (cMillis - hitMillis > 0.5) && (counting == 0 ) && (sqrt(pow((centerX - xAxis), 2) + pow((centerY - yAxis), 2)) < 50)) {
    Keyboard.press(KEY_ESC);
    Keyboard.release(KEY_ESC);
    Keyboard.press(KEY_RIGHT_CTRL);
    Keyboard.press(KEY_RIGHT_ALT);
    Keyboard.press('s');
    Keyboard.release(KEY_RIGHT_CTRL);
    Keyboard.release(KEY_RIGHT_ALT);
    Keyboard.release('s');
    counting++;
  }
  else if (!scrollModeTwo && !scrollMode && (sqrt(pow((centerX - xAxis), 2) + pow((centerY - yAxis), 2)) > 50)) {
    counting = 0;
    hitMillis = cMillis;
  }
  if (cMillis - dataMillis >= 250) {
    // un-comment next line to print data to serial monitor
    nunchuck_print_data();
    dataMillis = cMillis;
  }
  checkButtons();
  if (!scrollModeTwo && !scrollMode && !mouseio) {
    differentGame(cMillis);
    Mouse.release(MOUSE_LEFT);
    Mouse.release(MOUSE_RIGHT);
  }
  if (!scrollModeTwo && scrollMode && mouseio) {
    if ((cMillis - scrollXMillis) >= 30) {
      if ((xAxis - 10) > centerX) {
        Keyboard.release(KEY_LEFT_SHIFT);
        Mouse.move(0, 0, -1);
      }
      else if ((xAxis + 10) < centerX) {
        Keyboard.release(KEY_LEFT_SHIFT);
        Mouse.move(0, 0, 1);
      }
      scrollXMillis = cMillis;
    }
    if ((cMillis - scrollYMillis) >= 30) {
      if ((yAxis - 10) > centerY) {
        Keyboard.press(KEY_LEFT_SHIFT);
        Mouse.move(0, 0, -1);
      }
      else if ((yAxis + 10) < centerY) {
        Keyboard.press(KEY_LEFT_SHIFT);
        Mouse.move(0, 0, 1);
      }
      scrollYMillis = cMillis;
    }
  }
  if (scrollModeTwo && mouseio && !scrollMode) {
    if ((cMillis - scrollXMillis) >= 5) {
      if ((xAxis - 10) > centerX) {
        Keyboard.release(KEY_LEFT_SHIFT);
        Mouse.move(0, 0, 10);
      }
      else if ((xAxis + 10) < centerX) {
        Keyboard.release(KEY_LEFT_SHIFT);
        Mouse.move(0, 0, -10);
      }
      scrollXMillis = cMillis;
    }
    if ((cMillis - scrollYMillis) >= 15) {
      if ((yAxis - 10) > centerY) {
        Keyboard.press(KEY_LEFT_SHIFT);
        Mouse.move(0, 0, 10);
      }
      else if ((yAxis + 10) < centerY) {
        Keyboard.press(KEY_LEFT_SHIFT);
        Mouse.move(0, 0, -10);
      }
      scrollYMillis = cMillis;
    }</p><p>  }
  myServo.write(90);
  scrollMotion(cMillis);
  MouseMode(cMillis);
  if (escape) {
    shakeEsc(cMillis);
  }
}</p><p>//
// Nunchuck functions
/</p><p>/ Uses port C (analog in) pins as power & ground for Nunchuck
// initialize the I2C system, join the I2C bus,
// and tell the nunchuck we're talking to it
void nunchuck_init()
{
  Wire.begin();                      // join i2c bus as master
  Wire.beginTransmission(0x52);     // transmit to device 0x52
  Wire.write(0x40);            // sends memory address
  Wire.write(0x00);            // sends sent a zero.
  Wire.endTransmission();     // stop transmitting
}</p><p>// Send a request for data to the nunchuck
// was "send_zero()"
void nunchuck_send_request()
{
  Wire.beginTransmission(0x52);     // transmit to device 0x52
  Wire.write(0x00);            // sends one byte
  Wire.endTransmission();     // stop transmitting
}</p><p>// Receive data back from the nunchuck,
int nunchuck_get_data()
{
  int cnt = 0;
  Wire.requestFrom (0x52, 6);     // request data from nunchuck
  while (Wire.available ()) {
    // receive byte as an integer
    nunchuck_buf[cnt] = nunchuk_decode_byte(Wire.read());
    cnt++;
  }
  nunchuck_send_request();  // send request for next data payload
  // If we recieved the 6 bytes, then go print them
  if (cnt >= 5) {
    return 1;   // success
  }
  return 0; //failure
}</p><p>// Print the input data we have recieved
// accel data is 10 bits long
// so we read 8 bits, then we have to add
// on the last 2 bits.  That is why I
// multiply them by 2 * 2
void nunchuck_print_data()
{
  static int i = 0;
  int joy_x_axis = nunchuck_buf[0];
  int joy_y_axis = nunchuck_buf[1];</p><p>  int accel_x_axis = nunchuck_buf[2]; // * 2 * 2;
  int accel_y_axis = nunchuck_buf[3]; // * 2 * 2;
  int accel_z_axis = nunchuck_buf[4]; // * 2 * 2;</p><p>  int z_button = 0;
  int c_button = 0;</p><p>  // byte nunchuck_buf[5] contains bits for z and c buttons
  // it also contains the least significant bits for the accelerometer data
  // so we have to check each bit of byte outbuf[5]
  if ((nunchuck_buf[5] >> 0) & 1) {
    z_button = 1;
  }
  if ((nunchuck_buf[5] >> 1) & 1) {
    c_button = 1;
  }
  if ((nunchuck_buf[5] >> 2) & 1)
    accel_x_axis += 2;
  if ((nunchuck_buf[5] >> 3) & 1)
    accel_x_axis += 1;</p><p>  if ((nunchuck_buf[5] >> 4) & 1)
    accel_y_axis += 2;
  if ((nunchuck_buf[5] >> 5) & 1)
    accel_y_axis += 1;</p><p>  if ((nunchuck_buf[5] >> 6) & 1)
    accel_z_axis += 2;
  if ((nunchuck_buf[5] >> 7) & 1)
    accel_z_axis += 1;</p><p>  Serial.print(i, DEC);
  Serial.print("\t");</p><p>  Serial.print("joy:");
  Serial.print(joy_x_axis, DEC);
  Serial.print(",");
  Serial.print(joy_y_axis, DEC);
  Serial.print("  \t");</p><p>  Serial.print("acc:");
  Serial.print(accel_x_axis, DEC);
  Serial.print(",");
  Serial.print(accel_y_axis, DEC);
  Serial.print(",");
  Serial.print(accel_z_axis, DEC);
  Serial.print("\t");</p><p>  Serial.print("but:");
  Serial.print(z_button, DEC);
  Serial.print(",");
  Serial.print(c_button, DEC);</p><p>  Serial.print("\r\n");  // newline
  i++;
}</p><p>// Encode data to format that most wiimote drivers except
// only needed if you use one of the regular wiimote drivers
char nunchuk_decode_byte (char x)
{
  x = (x ^ 0x17) + 0x17;
  return x;
}
void shakeMouse(long cM) {
  if (cM - action1Millis > 50) {
    if (nunchuck_buf[2] > 150) {
      action1 = true;
    }
    action1Millis = cM;
  }
  if (action1)
    if (cM - action2Millis > 90) {
      if (nunchuck_buf[2] < 50) {
        action2 = true;
      }
      action2Millis = cM;
    }
  if (action1 && action2 && c) {
    if (mouseIsActive)
      Serial.println("Joystick off");
    else
      Serial.println("Joystick on");
    mouseIsActive = !mouseIsActive;
    allActionMillis -= 400;
  }
  if (cM - allActionMillis > 300) {
    action1 = false;
    action2 = false;
    allActionMillis = cM;
  }
}
void shakeEsc(long cM) {
  if (cM - action1Millis > 50) {
    if (nunchuck_buf[2] > 150) {
      action1 = true;
    }
    action1Millis = cM;
  }
  if (action1)
    if (cM - action2Millis > 90) {
      if (nunchuck_buf[2] < 50) {
        action2 = true;
      }
      action2Millis = cM;
    }
  if (action1 && action2 && c) {
    Serial.println("Escaping");
    Keyboard.write(KEY_ESC);
    Keyboard.write(KEY_RETURN);
    allActionMillis -= 400;
  }
  if (cM - allActionMillis > 300) {
    action1 = false;
    action2 = false;
    allActionMillis = cM;
  }
}
void differentGame(long cM) {
  if (game2)
    if (cM - game1Millis > 30) {
      if (nunchuck_buf[4] > 190) {
        game1 = true;
      }
      game1Millis = cM;
    }
  if (cM - game2Millis > 60) {
    if (nunchuck_buf[4] < 105) {
      game2 = true;
    }
    game2Millis = cM;
  }
  if (game1 && game2 && c && !mouseio) {
    if (slitherio) {
      Serial.println("Agar.io mode");
      previous = true;
    }
    else {
      Serial.println("Slither.io mode");
      previous = false;
    }
    slitherio = !slitherio;
    allGameMillis -= 400;
  }
  if (cM - allGameMillis > 300) {
    game1 = false;
    game2 = false;
    allGameMillis = cM;
  }
}</p><p>void MouseMode(long cM) {
  if (mouseio) {
    shakeMouse(cM);
    escape = false;
  }
  else {
    escape = true;
  }
  if (mouse2)
    if (cM - mouse1Millis > 30) {
      if (nunchuck_buf[4] > 190) {
        mouse1 = true;
      }
      mouse1Millis = cM;
    }
  if (cM - mouse2Millis > 60) {
    if (nunchuck_buf[4] < 105) {
      mouse2 = true;
    }
    mouse2Millis = cM;
  }
  if (mouseio && ((cM - mouseioMillis) >= 400)) {
    c = false;
    mouseioMillis = cM;
  }
  if (mouse1 && mouse2 && !c) {
    if (mouseio) {
      Serial.println("Mouse mode off");
      responseDelay = gameioDelay;
    }
    else {
      Serial.println("Mouse mode on");
      responseDelay = mouseioDelay;
    }
    Keyboard.write(KEY_ESC);
    mouseio = !mouseio;
    if (!previous)
      slitherio = false;
    else
      slitherio = true;
    allMouseMillis -= 400;
  }
  if (cM - allMouseMillis > 300) {
    mouse1 = false;
    mouse2 = false;
    allMouseMillis = cM;
  }
}
void checkButtons() {
  if ((nunchuck_buf[5] >> 1) & 1) {
    if (!c)
      c = true;
    if (mouseio) {
      Mouse.release(MOUSE_LEFT);
    }
    else if (slitherio)
      Keyboard.release(cButton);
  }
  else {
    if (c) {
      if (mouseio) {
        Mouse.press(MOUSE_LEFT);
      }
      else {
        Keyboard.press(cButton);
        if (!slitherio) {
          c = false;
          Keyboard.release(cButton);
        }
      }
    }
  }
  if ((nunchuck_buf[5] >> 0) & 1) {
    if (!z)
      z = true;
    if (mouseio) {
      Mouse.release(MOUSE_RIGHT);
    }
    else if (slitherio)
      Keyboard.release(zButton);
  }
  else {
    if (z) {
      if (mouseio) {
        Mouse.press(MOUSE_RIGHT);
      }
      else {
        Keyboard.press(zButton);
        if (!slitherio) {
          z = false;
          Keyboard.release(zButton);
        }
      }
    }
  }
}
void scrollMotion(long cM) {
  if (nunchuck_buf[2] > 170) {
    scrollMode = true;
    scrollModeTwo = false;
    countTwo = 0;
  }
  else if ((nunchuck_buf[2] > 70) && (nunchuck_buf[2] < 90)) {
    scrollModeTwo = true;
    scrollMode = false;
    countTwo = 0;
  }
  else {
    scrollMode = false;
    scrollModeTwo = false;
    if (countTwo == 0)
      Keyboard.release(KEY_LEFT_SHIFT);
    countTwo++;
  }
}</p><p>int readAxis(int thisAxis, long cM) {
  // read the analog input:
  int reading = thisAxis;</p><p>  if (change)
    reading = map(reading, yMin, yMax, range, 0);  //y-axis
  else
    reading = map(reading, xMin, xMax, 0, range);  //x-axis</p><p>  // if the output reading is outside from the
  // rest position threshold,  use it:
  int distance = reading - center;</p><p>  if (abs(distance) < threshold) {
    distance = 0;
  }
  // return the distance for this axis:
  return distance;
}</p></p>

The problem I faced when uploading this code is when I couldn't upload the code! :(

The issue could be because you didn't set the proper settings for the arduino board. Make sure you set the following:

Board: Sparkfun Pro Micro (Make sure you selected the right Voltage)

  • If you were like me and put 3.3V instead of 5V...We got an issue. You have "bricked" your board. To fix it, simply follow these steps

Port: The port the board is connected to.

Step 4: AutoHotKey

  1. Install the AutoHotKey app from here.
  2. Install the AutoHotKey code Editor(sciTe4Autohotkey) from here.
  3. Copy the code from below and paste it into a new program in sciTe4Autohotkey.
#SingleInstance, Forcestarted:=false
Location:=false
Global escaped:=false
Global scrollCount:=0
^!+s:: ;Start mousetrap
if(!escaped){
		centerRadius:= 175  ;175 for slither.io  and 350 for agar.io
		CircleClip(centerRadius)
		MouseGetPos, x, y
			centerX:=x
			centerY:=y
		started=true
		Global escaped=true
	}
Return
^!c::
	Global scrollCount
	if(scrollCount<=15){
		centerRadius+=50
		scrollCount++
	}
return
^!z::
	Global scrollCount
	if(scrollCount>=-2){
		centerRadius-=50
		scrollCount--	
	}
return

Esc::  ;get out of mousetrap
if(escaped){
	CircleClip(0)
	Global escaped=false	
}
return
^!s:: ;Start mousetrap
if(!escaped){
		if(started){
			MouseMove,centerX,centerY,0
			Location=true
			CircleClip(centerRadius)
			Global escaped=true
		}
	}
Return

CircleClip(radius=0, x:="", y:=""){
	global CircleClipRadius, CircleClipX, CircleClipY
	static hHookMouse, _:={base:{__Delete: "CircleClip"}}
	If (radius>0)
		if(!location){
		CircleClipRadius:=radius
		, CircleClipX:=x
		, CircleClipY:=y
		, hHookMouse := DllCall("SetWindowsHookEx", "int", 14, "Uint", RegisterCallback("CircleClip_WH_MOUSE_LL", "Fast"), "Uint", 0, "Uint", 0)
		}
		else{
		Location=false
		CircleClipRadius:=centerRadius
		, CircleClipX:=centerX
		, CircleClipY:=centerY
		, hHookMouse := DllCall("SetWindowsHookEx", "int", 14, "Uint", RegisterCallback("CircleClip_WH_MOUSE_LL", "Fast"), "Uint", 0, "Uint", 0)
		
		}
	Else If (!radius && hHookMouse){
		DllCall("UnhookWindowsHookEx", "Uint", hHookMouse)
		CircleClipX:=CircleClipY:=""
	}
}

CircleClip_WH_MOUSE_LL(nCode, wParam, lParam){
	global CircleClipRadius, CircleClipX, CircleClipY
	Critical
	if !nCode && (wParam = 0x200){ ; WM_MOUSEMOVE 
		nx := NumGet(lParam+0, 0, "Int") ; x-coord
		ny := NumGet(lParam+0, 4, "Int") ; y-coord
		
		If (CircleClipX="" || CircleClipY="")
			CircleClipX:=nx, CircleClipY:=ny
		  
		dx := nx - CircleClipX
		dy := ny - CircleClipY
		dist := sqrt( (dx ** 2) + (dy ** 2) )

if ( dist > CircleClipRadius ) {
			dist := CircleClipRadius / dist
			dx *= dist
			dy *= dist
			
			nx := CircleClipX + dx
			ny := CircleClipY + dy
		}
		else if(dist <(CircleClipRadius-1)){  ;CircleClipRadius-100
			dist := (CircleClipRadius-1) / dist
			dx *= dist
			dy *= dist
			nx := CircleClipX + dx
			ny := CircleClipY + dy		
		}

DllCall("SetCursorPos", "Int", nx, "Int", ny)
		Return 1
		
	}else Return DllCall("CallNextHookEx", "Uint", 0, "int", nCode, "Uint", wParam, "Uint", lParam) 
}

^Esc::ExitApp

If you're wondering how I got the Mouse to trap inside a circle, the code is located in the method CircleClip_WH_MOUSE_LL(nCode, wParam, lParam).

Basically, I needed to detect when the cursor got too far until I could trap it. In this case, a circle is our limiter. So using what my Math teacher taught me, I used the distance equation. After realizing that, its basically just fiddling and learning more about the AutoHotKey programming language. There are tutorials on this and can be found on their website.

Run button in AutoHotKey

Step 5: Start AutoHotKey(AHK)

picture

  • Hit that play button(as shown above) in the sciTe4Autohotkey programmer.
  • Open up Agar.io or cose.io game in a web browser.

Run button in AutoHotKey

  • Now Hit Play and start the Game.

It can be hard to navigate around the sciTe4Autohotkey code editor. Unfortunately, its the best out of the other AutoHotKey code editors. You could use Notepad or Wordpad, but for most of us, that's a hard pass. The reason I like this sciTe4Autohotkey code editor is that it has a "run" button and feels a little bit similar to the Arduino compiler.

Step 6: Mouse Position and Combo

  • Next, place your mouse cursor at the exact center of the player.
  • You know you hit the center when the player stops moving. This part can be tedious so take your time. But when u get it, it'll be worth it. Unfortunately, there is no way for AutoHotKey to know the center of the player.

Run button in AutoHotKey

  • Finally, use The Macro combo as shown below.

Macro Combo: "CTRL+SHIFT+ALT+S"

To escape trap: "ESC"

Stop program: "CTRL+ESC"

I made the macro combo keystroke long because it is rare that any program in the world(other than this one) reacts to it. So there will be no mishap.

Run button in AutoHotKey

Originally I thought that I could forget about AutoHotKey and put all the running code on the Arduino side. But after many months of failure, AutoHotkey was the right direction after all. It turns out that Arduino can't determine the location of the mouse on the computer, it can only move a certain number of pixels. So this would be bad because the Arduino would never know the player's center coordinates.

Also, what does the Macro Combo do?It saves the location of the mouse and starts the program.

Step 7: The Controls

picture

All these controls were shown throughout the video.

So as I said earlier, there is more to this controller other than mouse trapping. There is Agar.io, slither.io, and regular-computer-mouse mode. If you mix these together you get Minecraft mode.

1. Game Modes: While holding the nunchuck upright, make a stabbing movement up and then downward to change game modes. Current two games modes are AGAR.io(default) mode and Slither.io mode.
2. There is also a mouse mode. First, hold the c button on the nunchuck and then perform the *Game Mode from (part a)*.

3. Scroll Mode 1(In Mouse Mode only): tilt the Wii nunchuck sideways to engage scroll mode. In this mode, you move the joystick to scroll across pages.

4. Scroll Mode 2(In Mouse Mode only): tilt the other way and you can scroll even FASTER!

5. While in Mouse mode, shake nunchuck sideways to disable joystick.

6.While in either Game Mode, shake nunchuck sideways to exit out of a game(Similar to typing "ESC")

This(and more updates) can all be found on Github

Thanks for reading my Instructable, don't forget to vote for me in the Arduino and Remote Control Contest.

Share

    Recommendations

    • Oil Contest

      Oil Contest
    • Clocks Contest

      Clocks Contest
    • Creative Misuse Contest

      Creative Misuse Contest

    10 Discussions

    The nunchuck is a neat application, but is there any reason you couldn't use this concept with a normal mouse, or even a trackball?

    4 replies

    Not trying to criticize in any way, just thinking it'd be fun to try with my current equipment :-)

    Nothing stopping you from trying. :)

    If you just want the "trapping part", simply run the AHK code and don't use the arduino pro micro.

    I don't know, yet, how to hack a mouse's output. But it would be great if I could :)

    So I decided to use a nunchuck cause its the simplest since it only uses four wires to connect to arduino pro micro. If i connected to a joystick, and two buttons that would add up to at least 6 wires. An personally, I like the nunchuck's exterior. (I don't have a 3d printer, yet)

    Arduino CAN determine the location of the mouse cursor on the screen, you just need to use the absolute mode.

    3 replies

    OK, it is more of a hack, but it still seems possible:

    https://forum.arduino.cc/index.php?topic=94140.0

    Hehe, I saw that forum two years ago and tried it. But apparently there was an issue with the compiler. I'll give it a shot again. Thx JarosławM5

    Nope still doesn't work, even after I removed "platform.h"

    :(

    Don't forget to vote for me in contests.