Using a Wii Remote

Is it possible to get a Wii Remote and Nunchuck working with a JME Game as a Joystick? Or at least with Analog control. I’ve heard of things like PPJoy being used, but I have Windows 7 64 bit, which makes a lot of things an enormous pain. I’d also seen something about wiiremotej, but I have no idea if that can even work with 64-bit either. Not to mention the download links for half of these programs seem to be either broken, nonexistent, or virus-ridden (I only assume on that last one). And any discussions here on it were quite some time ago, so I’m unsure if there are better ways, or no ways now.

I thought I’d seen something about Wii Remotes being used in JME before, but I have no idea how it was done.

Any sort of guidance would be appreciated, even if it’s simply to give up because it’s not worth the hassle.

Thanks.

I had the Wii Remote and Wii Motion Plus working before with jME3. I used GlovePIE and PPJoy (on Windows 7) and then accessed the joystick via jME3’s joystick input. It worked fine but the setup itself is a bit cumbersome, it works if you just want to get the data…

There are many C/C++ libraries, so a more integrated solution can be achieved by using JNI to access these libraries.

Do you know of any that you’d recommend? I tried something called WiiuseJ (the Java wrapper of a C library, Wiiuse), but I have no idea how to get it to actually work. It’d be nice if there was just a driver or something for it. I need to find something that supports the MS Bluetooth Stack, because I can’t manage to get anything else.

This seems to be beyond my abilities, but it would certainly be a nice addition for players. :confused:

I haven’t tried any of them actually. My objective was to get the gyroscope in the Wii Motion Plus to work and at that time only GlovePIE and one C++ library supported it.

Ah, alright. Would you happen to know anyone who’s tried it and succeeded? I only really need button support, because the motion stuff isn’t really what I’m looking for (as for why it’s a Wiimote rather than something easier, it’s because the game is similar to SSB, so it seems like a decent match).

I managed to get the WiiuseJ thing to work, but you have to include a couple .dll/.so files into it. Is there a way to get the Build to automatically add them, or do I manually put them in the dist folder? Another downside is that it doesn’t support Mac OSs, so I’d either have to find another library that does support it (probably one I’d have to use JNI for, which I don’t actually know how to use :P), or just say the feature isn’t supported.

There’s also the option of just having people use GlovePIE stuff (which works well for digital input), or whatever alternatives there may be for other OSs. I’m discussing it with the main programmer on the project, as well.

@Inferno630 said: Ah, alright. Would you happen to know anyone who's tried it and succeeded? I only really need button support, because the motion stuff isn't really what I'm looking for (as for why it's a Wiimote rather than something easier, it's because the game is similar to SSB, so it seems like a decent match).
Some people on the forum used the various Java libraries for interacting with the Wii Remote. I don't know of any that went far enough though.
@Inferno630 said: I managed to get the WiiuseJ thing to work, but you have to include a couple .dll/.so files into it. Is there a way to get the Build to automatically add them, or do I manually put them in the dist folder?
jME3 supports automatic native extraction, but only for the libraries it is using ... We never got around to making that system flexible enough for users to customize. If you're willing to go through the effort, look into the Natives class in jME3.
@Inferno630 said: There's also the option of just having people use GlovePIE stuff (which works well for digital input), or whatever alternatives there may be for other OSs. I'm discussing it with the main programmer on the project, as well.
Is it really critical to support Wii remotes for this? With USB gamepads it is much easier, you just plug and go, and it works right out of the box with jME3.

Yeah, I’ve (for the time being, at least), decided to drop it for now. Too many compatibility requirements and too little documentation for most of the libraries. It’s not critical, and no one has any real reason to expect compatibility. Besides, if they manage to get something like PPJoy working with their computer, they can use it as a Joystick anyway, which I was hoping to support (and working on).

Although I’m having some issues working on getting the menu to work with a Joystick (which could always just be required to use a mouse, I suppose), although that’s an unrelated issue.

Either way, thanks for your help.

@Inferno630 said: Yeah, I've (for the time being, at least), decided to drop it for now. Too many compatibility requirements and too little documentation for most of the libraries. It's not critical, and no one has any real reason to expect compatibility. Besides, if they manage to get something like PPJoy working with their computer, they can use it as a Joystick anyway, which I was hoping to support (and working on).

Although I’m having some issues working on getting the menu to work with a Joystick (which could always just be required to use a mouse, I suppose), although that’s an unrelated issue.

Either way, thanks for your help.

Is your menu using nifty? You may have to forward joystick events as key events to the nifty instance.

Yeah, I’m using Nifty; I have a few ideas on how I might be able to do it. Although if there’s some way to control the cursor using keys or a joystick, it would be a lot simpler in some parts. :stuck_out_tongue:

@Inferno630 said: Yeah, I'm using Nifty; I have a few ideas on how I might be able to do it. Although if there's some way to control the cursor using keys or a joystick, it would be a lot simpler in some parts. :P

You can already move through clickable things with the cursor keys. To get this to work with the joystick, you just have to register a listener and forward your own key events to this method: http://hub.jmonkeyengine.org/javadoc/com/jme3/niftygui/NiftyJmeDisplay.html#simulateKeyEvent(com.jme3.input.event.KeyInputEvent)

Alright, thanks for the information. I’ll probably have to do a few things in a less orthodox way than usual due to how I’ve set things up, but that’s incredibly valuable information.

I’d attempted to create a fake cursor (controlled with a RawInputListener), but the Joystick control was really glitchy for some reason; like it would randomly snap back if I went left, but would move normally if I moved right. I’m not expecting anyone to know how without the code; I simply want to know, are joysticks usually glitchy at all, or was it probably just something weird in my code?

Joysticks are not usually glitchy. You can run JME’s joystick test app if you want to see if you are somehow getting jitter from your joysticks or something.

I have a working cross-input main menu now. The “glitch” I was mentioning earlier was actually me being an idiot and continuing to listen to move the joystick left to start the game (it was on the previous screen, so I didn’t realize it still had an effect). Therefore, every time I moved left, it reloaded the menu. Whoops.

However, it’s still not particularly smooth movement, so I still probably won’t use the fake cursor. Is there any way to make it move more smoothly?

@Inferno630 said: I have a working cross-input main menu now. The "glitch" I was mentioning earlier was actually me being an idiot and continuing to listen to move the joystick left to start the game (it was on the previous screen, so I didn't realize it still had an effect). Therefore, every time I moved left, it reloaded the menu. Whoops.

However, it’s still not particularly smooth movement, so I still probably won’t use the fake cursor. Is there any way to make it move more smoothly?

I have no idea how you are doing it now… so I can’t really comment.

Good point.

This is in the onStartScreen Method
[java]
Element cursorElement = screen.findElementByName(“Cursor”);
//cursorElement.hide();

    CursorMoveListener cursor = new CursorMoveListener(cursorElement, settings);
    
    float startX = inputManager.getCursorPosition().x;
    float startY = settings.getHeight() - inputManager.getCursorPosition().y;
    
    cursorElement.setConstraintX(new SizeValue((int) startX + "px"));
    cursorElement.getParent().layoutElements();
    cursorElement.setConstraintY(new SizeValue((int) startY + "px"));
    cursorElement.getParent().layoutElements();
    
    inputManager.addRawInputListener(cursor);

[/java]

And here’s the class’s own personal listener:
[java]
private class CursorMoveListener implements RawInputListener
{
private Element cursor;
private AppSettings settings;
private float x=0, y=0;

    public CursorMoveListener()
    {
        
    }
    
    public CursorMoveListener(Element cursor, AppSettings settings)
    {
        this.cursor = cursor;
        this.settings = settings;
    }

    public void beginInput() 
    {
        
    }

    public void endInput() 
    {
        
    }

    public void onJoyAxisEvent(JoyAxisEvent evt) 
    {
        float deadzone = inputManager.getAxisDeadZone();
        System.out.println("Axis Deadzones: " + inputManager.getAxisDeadZone());
        System.out.println("Moved Joystick");
        if (evt.getAxis().getName().equalsIgnoreCase("x"))
        {
            System.out.println("X Value: " + evt.getValue());
            if (evt.getValue() >= deadzone)
            {
                x += 5;
            }
            else if (evt.getValue() <= -deadzone)
            {
                x -= 5;
            }
        }
        if (evt.getAxis().getName().equalsIgnoreCase("y"))
        {
            System.out.println("Y Value: " + evt.getValue());
            if (evt.getValue() >= deadzone)
            {
                y += 10;
            }
            else if (evt.getValue() <= -deadzone)
            {
                y -= 10;
            }
        }
        
        x = FastMath.clamp(x, 0, settings.getWidth() - 12);
        y = FastMath.clamp(y, 0, settings.getHeight() - 19);
        
        System.out.println(x + ", " + y);
        
        cursor.setConstraintX(new SizeValue((int) x + "px"));
        cursor.getParent().layoutElements();
        cursor.setConstraintY(new SizeValue((int) y + "px"));
        cursor.getParent().layoutElements();
        
        fightButtonControl(fightButton.isClickable((int) x, (int) y), false);
    }

    public void onJoyButtonEvent(JoyButtonEvent evt) 
    {
        
    }

    public void onMouseMotionEvent(MouseMotionEvent evt) 
    {
        System.out.println("Moved Mouse");
        x = evt.getX();
        y = settings.getHeight() - evt.getY();
        System.out.println(x + ", " + y);
    
        x = FastMath.clamp(x, 0, settings.getWidth() - 12);
        y = FastMath.clamp(y, 0, settings.getHeight() - 19);
    
        cursor.setConstraintX(new SizeValue((int) x + "px"));
        cursor.getParent().layoutElements();
        cursor.setConstraintY(new SizeValue((int) y + "px"));
        cursor.getParent().layoutElements();
        
        fightButtonControl(fightButton.isClickable((int) x, (int) y), false);

// trainingButtonControl(trainingButton.isClickable(x, y), wasClick);
// extrasButtonControl(extrasButton.isClickable(x, y), wasClick);
// optionsButtonControl(optionsButton.isClickable(x, y), wasClick);
}

    public void onMouseButtonEvent(MouseButtonEvent evt) 
    {
        x = evt.getX();
        y = settings.getHeight() - evt.getY();
        System.out.println("Clicked Mouse");
        System.out.println(fightButton.isClickable((int) x, (int) y));
        fightButtonControl(fightButton.isClickable((int) x, (int) y), true);
    }

    public void onKeyEvent(KeyInputEvent evt) 
    {
        if (evt.getKeyCode() == KeyInput.KEY_A)
        {
            x -= 10;
        }
        if (evt.getKeyCode() == KeyInput.KEY_D)
        {
            x += 10;
        }
        if (evt.getKeyCode() == KeyInput.KEY_W)
        {
            y -= 10;
        }
        if (evt.getKeyCode() == KeyInput.KEY_S)
        {
            y += 10;
        }
        
        x = FastMath.clamp(x, 0, settings.getWidth() - 12);
        y = FastMath.clamp(y, 0, settings.getHeight() - 19);
    
        cursor.setConstraintX(new SizeValue((int) x + "px"));
        cursor.getParent().layoutElements();
        cursor.setConstraintY(new SizeValue((int) y + "px"));
        cursor.getParent().layoutElements();
        
        fightButtonControl(fightButton.isClickable((int) x, (int) y), false);
    }

    public void onTouchEvent(TouchEvent evt) 
    {
        
    }
};[/java] 

I don’t believe any other parts of the code are necessary to know for this, but let me know if you think you need to see more.

Well, there are a few potential things that can cause issue but the biggest one in my opinion is that you aren’t using the values of the joystick or factoring in tpf at all (this is included in the joystick values). So your values may look jerky as frame rate changes… and anyway you are increasing x by 5 and y by 10 always so that’s the smallest resolution you’d ever have.

As an aside, you shouldn’t have to do things like this:
evt.getAxis().getName().equalsIgnoreCase(“x”)

as:
evt.getAxis().getLogicalId() == JoyStickAxis.X_AXIS

…will be better and will work with more joysticks. The name could be anything but the logical ID is normalized inside the joystick layer.

For your original problem, I’d personally just do x += evt.getValue()

…add a constant multiplier if that’s too slow.

Ah, alright; I’d had it use the actual values at one point; I think I changed it because I thought it might be smoother, but never bothered getting around to changing it back. I have no idea why I have 10 going up and 5 going across. That doesn’t even make sense. :stuck_out_tongue:

As for the ID stuff; yeah that makes sense; I probably would’ve found that out when it didn’t work for someone; so it’s good to know that ahead of time. Thanks. :slight_smile:

The movement is relatively smooth now, but there’s one thing that I think is causing an issue; does the Joystick Axis only publish the event the first time it happens (same for Keys), because when I’m using it, when you push the key, it only moves once (same for the joystick). Is this just something the RawInputListener does? In that case, should I just try using the regular Action/Analog Listeners?

@Inferno630 said: Ah, alright; I'd had it use the actual values at one point; I think I changed it because I thought it might be smoother, but never bothered getting around to changing it back. I have no idea why I have 10 going up and 5 going across. That doesn't even make sense. :P

As for the ID stuff; yeah that makes sense; I probably would’ve found that out when it didn’t work for someone; so it’s good to know that ahead of time. Thanks. :slight_smile:

The movement is relatively smooth now, but there’s one thing that I think is causing an issue; does the Joystick Axis only publish the event the first time it happens (same for Keys), because when I’m using it, when you push the key, it only moves once (same for the joystick). Is this just something the RawInputListener does? In that case, should I just try using the regular Action/Analog Listeners?

Ah, it only sends events for changes. So you may need to use it to set a cursor velocity which you then use to update the cursor position during update().

Ah, alright. Does it do the same for the ActionListener/AnalogListener? It doesn’t seem like it does, but I could just be imagining something. If so, do you know if there’s any way to make it not? (like if you want a joystick to scroll down a menu, but only one item per joy-down)

Analog listeners are called every frame that the source is active. So I guess you could use that too.