[Solved and working] Wii Balance Board?

Hi everyone,



first of all: GREAT Game Engine :wink:



I was wondering if any of you ever tried to implement the Wii balance board as a controller into jMonkeyEngine? Do you think it is possible?



Under   http://code.google.com/p/wiiboard-simple/ is a free Java SourceCode for the balance board!





See you  :)  ,



RapidM

Hi

using the BalanceBoard as an controller within jme should be no problem.

We've used the WiiMote within jme without probs.

I dunno the API you posted, but using e.g. GlovePie should work as well.



2cents…

Imm0

I just want to integrate it directly.



I figured out that it should be able to integrate the WiiRemoteJ.  I was able to compile this Test Application (with balance board) in the src folder (new package mstier.balanceboard) of the jMonkey Project:


package mstier.balanceboard;

import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
import wiiremotej.*;
import wiiremotej.event.*;
import java.lang.Math;

public class BalanceCentre extends BalanceBoardAdapter
{
   private BalanceBoard remote;
  
   private static double horizontal = 400;
   private static double vertical = 300;
  
   private static JFrame graphFrame;
    private static JPanel graph;
    private static int[][] pixels;
  
   private static double totalmass = 0;
  
   private static boolean connected = false;
  
   public static void main(String args[])
   {
      System.setProperty("bluecove.jsr82.psm_minimum_off", "true");
      try
      {

         WiiRemoteJ.setConsoleLoggingAll();
                
         graphFrame = new JFrame();
         graphFrame.setTitle("Center of gravity graph: Balance Board");
         graphFrame.setSize(800, 600);
         graphFrame.setResizable(false);
        
         pixels = new int[800][600];
         graph = new JPanel()
         {
            public void paintComponent(Graphics graphics)
            {
               // draw axis
               graphics.clearRect(0, 0, 800, 600);
               graphics.fillRect(0, 0, 800, 600);
              
               if (totalmass > 20)
               {
                  graphics.setColor(Color.WHITE);
                  graphics.drawLine(0, 300, 800, 300);
                  graphics.drawLine(400, 0, 400, 600);

                  // draw centre of gravity
                  if (horizontal > 390 && horizontal < 410 && vertical > 290 && vertical < 310)
                  {
                     graphics.setColor(Color.BLUE);
                  } else {
                     graphics.setColor(Color.YELLOW);
                  }
                  graphics.fillOval(((int) horizontal) - 10, ((int) vertical - 10), 20, 20);
                
                  // draw mass
                  graphics.setColor(Color.RED);
                  graphics.drawString(Math.round(totalmass) + " kg", 10, 20);
               } else {
                  graphics.setColor(Color.RED);
                
                  if (connected)
                  {
                     graphics.drawString("Please step onto the Balance Board", 300, 300);
                  }
                  else
                  {
                     graphics.drawString("Connecting...", 380, 300);
                  }
               }
            }
         };
         graphFrame.add(graph);
         graphFrame.setVisible(true);
        
         BalanceBoard remote = null;
        
         try
         {
            remote = WiiRemoteJ.connectToBalanceBoard("00233199ddc0");
         }
         catch(java.lang.ArrayIndexOutOfBoundsException e)
         {
            System.out.println("Please parse the Bluetooth address of your board as an argument");
            System.out.println("boardcenter [address]n");
            System.exit(0);
         }
      
         remote.addBalanceBoardListener(new BalanceCentre(remote));
       //requesting for status
         remote.setLEDIlluminated(true);
         remote.requestStatus();
    
      }
      catch(Exception e){e.printStackTrace();}
   }
  
   public BalanceCentre(BalanceBoard remote)
   {
      connected = true;
      this.remote = remote;
   }
  
   public void disconnected()
   {
      System.out.println("Remote disconnected... Please Wii again.");
      System.exit(0);
   }
   public void buttonInputReceived(BBButtonEvent evt){
      if(evt.isPressed())
         remote.disconnect();
   }
   public void statusReported(BBStatusEvent evt){
      //print out the level of Battery
      System.out.println(evt.getBatteryLevel());
   }
   public void massInputReceived(BBMassEvent evt)
   {
      totalmass = evt.getTotalMass();
      System.out.println(totalmass);
      double massRightTop = evt.getMass(MassConstants.TOP, MassConstants.RIGHT);
      double massLeftTop = evt.getMass(MassConstants.TOP, MassConstants.LEFT);
      double massRightBottom = evt.getMass(MassConstants.BOTTOM, MassConstants.RIGHT);
      double massLeftBottom = evt.getMass(MassConstants.BOTTOM, MassConstants.LEFT);
  
      // below 20kg the results aren't very accurate
      if (totalmass > 20)
      {  
         // deltas are +/- how much kg in each direction
         double horizontalDelta = (massRightTop + massRightBottom) - (massLeftTop + massLeftBottom);
         double verticalDelta = (massLeftBottom + massRightBottom) - (massLeftTop + massRightTop);
    
         // we now need to make them relative to mass and work out position
         horizontal = (horizontalDelta / totalmass  * 400) + 400;
         vertical = (verticalDelta / totalmass * 300) + 300;
    
      } else {
         horizontal = 400;
         vertical = 300;
      }
      
        graph.repaint();
   }
}



* Code is from another forum *

The output is:




I controll the ball with my balance on the balance board.
___

But now I want to modify this script with OpenGL functions and with the window from SimpleGame.

Any ideas on how to do that?

It should be the same output as the "original" just with OpenGL+Simple Game Window....


Thanks for helping so far ;)

I hope my text is understandable *g*

RapidM

But now I want to modify this script with OpenGL functions and with the window from SimpleGame.

Any ideas on how to do that?

It should be the same output as the "original" just with OpenGL+Simple Game Window....

Learn OpenGL? Or do you want to use jME for this? The code for doing this with jME is not the same as doing it with pure OpenGL..

Hi,



No I want to use jME because of future work. Just trying to get the best out of it. Sorry that I didnt know that OpenGL doesnt work like OpenGL in jME.



I tried this:




import wiiremotej.*;
import wiiremotej.event.*;
import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingBox;
import com.jme.bounding.BoundingSphere;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Sphere;
import com.jme.scene.state.LightState;



public class GameManager extends SimpleGame{

   //Variables for the balance board
    private BalanceBoard remote;
    private static double horizontal = 400;
    private static double vertical = 300;
    private static double totalmass = 0;
    private static boolean connected = false;
   
   
   public static void main (String[] args){
      
      //Windows from Simple Game
      GameManager app = new GameManager();
      app.setConfigShowMode(ConfigShowMode.NeverShow);
      app.start();
      
   
      
      //Workaround out of bounds bluesoleil error
       System.setProperty("bluecove.jsr82.psm_minimum_off", "true");
      
       try{
          WiiRemoteJ.setConsoleLoggingAll();
      
       BalanceBoard remote = null;
      
         try
         {
            remote = WiiRemoteJ.connectToBalanceBoard("00233199ddc0");
         }
         catch(java.lang.ArrayIndexOutOfBoundsException e)
         {
            System.out.println("Please parse the Bluetooth address of your board as an argument");
            System.out.println("boardcenter [address]n");
            System.exit(0);
         }
       
         remote.addBalanceBoardListener(new BalanceCentre(remote));
       //requesting for status
         remote.setLEDIlluminated(true);
         remote.requestStatus();
     
      }
      catch(Exception e){e.printStackTrace();}

   }

       //Main functions of the balance board
       public GameManager(BalanceBoard remote)
         {
            connected = true;
            this.remote = remote;
         }
         
         public GameManager() {
         // TODO Auto-generated constructor stub
      }

      public void disconnected()
         {
            System.out.println("Remote disconnected... Please Wii again.");
            System.exit(0);
         }
         public void buttonInputReceived(BBButtonEvent evt){
            if(evt.isPressed())
               remote.disconnect();
         }
         public void statusReported(BBStatusEvent evt){
            //print out the level of Battery
            System.out.println(evt.getBatteryLevel());
         }
         public void massInputReceived(BBMassEvent evt)
         {
            totalmass = evt.getTotalMass();
            System.out.println(totalmass);
            double massRightTop = evt.getMass(MassConstants.TOP, MassConstants.RIGHT);
            double massLeftTop = evt.getMass(MassConstants.TOP, MassConstants.LEFT);
            double massRightBottom = evt.getMass(MassConstants.BOTTOM, MassConstants.RIGHT);
            double massLeftBottom = evt.getMass(MassConstants.BOTTOM, MassConstants.LEFT);
         
            // below 20kg the results aren't very accurate
            if (totalmass > 20)
            {   
               // deltas are +/- how much kg in each direction
               double horizontalDelta = (massRightTop + massRightBottom) - (massLeftTop + massLeftBottom);
               double verticalDelta = (massLeftBottom + massRightBottom) - (massLeftTop + massRightTop);
           
               // we now need to make them relative to mass and work out position
               horizontal = (horizontalDelta / totalmass  * 400) + 400;
               vertical = (verticalDelta / totalmass * 300) + 300;
           
            } else {
               horizontal = 400;
               vertical = 300;
            }
            simpleInitGame();
         }
   
   
   protected void simpleInitGame(){
      
      Sphere s = new Sphere("My Sphere",10,10,1f);
      
       Node n=new Node("My Node");
      n.attachChild(s);
      n.setLocalScale(5);
      
      rootNode.attachChild(n);
   }
   
}



As you can figure out I am pretty new to this. Any help would be great!

I want to control this little "Sphere" with the balance of my balance board like in the TestApp.  Am I heading in the total wrong direction?

Thanks ;)

Rapidm

As you can see this really bugs me g



Is it possible to write a GameController with the WiiRemoteJ balance board functions? Then I could use this even better! I read something about someone who integrated the Wiimote with WiiRemoteJ…



What do you think is better? Integrating it directly for each game or central with a GameController…?



Anyone out here who already managed to integrate the balance board with WiiRemoteJ and JME?





Thanks again, Rapidm

It should be really simple to write a custom GameControl in jME to leverage the values received from WiiRemoteJ

Thanks fot the quick response. Then I'll try that and share my results when I am finished :wink:

Well a few hints of experiances i made with custom GameControllers as the WiiMote or the GameTrak…

What you get are some float values from the controller. In case of the balanceboard you should get 4 values between 0 and 1, right?



Well, by using the Gametrak i get values between -1 and 1 for the x/y/z position of each hand… means 6 values over all.



What iam doing is:



1. Initialize the Controller

In my case the Gametrak gets recognized as a 6-Axis Joystick by JInput.

In your case you would have to initialize it by the WiimoteJ API.



2. Write an Controller-Thread

Write a simple class, which is a Thread and reads the values from the Balanceboard periodically and returns values (maybe as events or simple getterMethods) to you. So add a constant for the desired UpdateRate - e.g. 30-60 values a second.



2.1 Write an InputBuffer for the Values

I dunno if this is really neccessary in case of the BalanceBoard.

In my case it helped a lot. The values i got were too accurate, which means that even the slightest movement let shiver the cursor. So i wrote an simple BufferClass, which stores the last 10 values and calculates the average.

The ControllerClass has one Buffer for each Axis of the GameTrak. So at each update i get the interpolated values from the ControllerClass. This made the movement of the cursor much better.



3.Use the ControllerClass within your jmeApplication

After having the desired interpolated values available, you just have to use them within your App.

Therefore just call the ControllerClass.getXvalue() during your simpleUpdate() to update the cursors postion.



All in all it should be pretty simple, and i hope these hints help you out!



Greets

Imm0


Thanks .:emp…immo0|82 :slight_smile:



I think I am almost done…  I tried working with the basic GameControl Tutorial files:



So I got this modified:


package gamecontrols;
 
import wiiremotej.BalanceBoard;

import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.light.PointLight;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;
import com.jme.scene.state.LightState;
import com.jme.scene.state.MaterialState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jmex.game.state.BasicGameState;
 
/**
 *
 * @author Gronau
 */
public class CubeGameState extends BasicGameState {
 
    private static String texture = "jmetest/data/images/Monkey.jpg";
   public      WiiRemoteProxy         remote;

   
    public CubeGameState() {
        super("cubeGameState");
        final Box box = new Box("MonkeyBox", new Vector3f(0, 0, 0), 5, 5, 5);
 
        //Material: gray
        final MaterialState ms = DisplaySystem.getDisplaySystem().getRenderer().createMaterialState();
        ms.setEmissive(new ColorRGBA(0.5f, 0.5f, 0.5f, 1));
        box.setRenderState(ms);
 
        //Texture: the Monkey
        final TextureState ts = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
        final Texture t = TextureManager.loadTexture(
                BasicGameState.class.getClassLoader().getResource(texture),
                Texture.MinificationFilter.BilinearNoMipMaps,
                Texture.MagnificationFilter.Bilinear);
        ts.setTexture(t);
        box.setRenderState(ts);
        box.setModelBound(new BoundingBox());
        box.updateModelBound();
        Node boxNode = new Node("MonkeyBoxNode");
        boxNode.attachChild(box);
        getRootNode().attachChild(boxNode);
 
        //Spot on!
        final PointLight light = new PointLight();
        light.setDiffuse(new ColorRGBA(0.75f, 0.75f, 0.75f, 0.75f));
        light.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
        light.setLocation(new Vector3f(100, 100, 100));
        light.setEnabled(true);
 
        final LightState lightState = DisplaySystem.getDisplaySystem().getRenderer().createLightState();
        lightState.setEnabled(true);
        lightState.attach(light);
        getRootNode().setRenderState(lightState);
 
        getRootNode().updateRenderState();
        //Oh, and don't forget the controller...
        getRootNode().addController(new CubeController(boxNode));
    }
}



This is my CubeGameState.java  Nothing really changed here, just added the puclic WiiRemoteProxy...

package gamecontrols;
 
import com.jme.input.controls.GameControl;
import com.jme.input.controls.GameControlManager;
import com.jme.input.controls.binding.KeyboardBinding;
import com.jme.input.controls.binding.MouseButtonBinding;
import com.jme.scene.Controller;
import com.jme.scene.Node;
import static gamecontrols.CubeController.CubeAction.*;
import static com.jme.input.KeyInput.*;
import static com.jme.input.controls.binding.MouseButtonBinding.*;

import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
import wiiremotej.*;
import wiiremotej.event.*;
import java.lang.Math;
 
public class CubeController extends Controller{
   
   public      WiiRemoteProxy         remote;
   
    enum CubeAction {LEFT, RIGHT, UP, DOWN, EXIT};
 
    private final static float SPEED = 2F;
 
    private final Node node;
    private final GameControlManager manager;
    private float vAngle = 0F;
    private float hAngle = 0F;
 
    public CubeController(Node node) {
        this.node = node;
        this.manager = new GameControlManager();
       
              
 
        //create all actions
        for (CubeAction action : CubeAction.values()) {
            manager.addControl(action.name());
        }
        //bind keys
        bindKey(EXIT, KEY_X);
        bindKey(UP, MassConstants.TOP);
        bindKey(DOWN, MassConstants.BOTTOM);
        bindKey(LEFT, MassConstants.LEFT);
        bindKey(RIGHT, MassConstants.RIGHT);
 
        //bind mouse buttons
        bindMouseButton(LEFT, LEFT_BUTTON);
        bindMouseButton(RIGHT, RIGHT_BUTTON);
    }
 
 
    private void bindKey(CubeAction action, int... keys) {
        final GameControl control = manager.getControl(action.name());
        for (int key : keys) {
          control.addBinding(new KeyboardBinding(key));
        }
    }
 
    private void bindMouseButton(CubeAction action, int mouseButton) {
        final GameControl control = manager.getControl(action.name());
        control.addBinding(new MouseButtonBinding(mouseButton));
    }
 
    private float value(CubeAction action) {
        return manager.getControl(action.name()).getValue();
    }
 
    @Override
    public void update(float time) {
        if (value(EXIT) > 0) {
            System.exit(0); //OK, this is just a demo...
        }
        hAngle += SPEED * time * (value(RIGHT) - value(LEFT));
        vAngle += SPEED * time * (value(DOWN) - value(UP));
        node.getLocalRotation().fromAngles(vAngle, hAngle, 0f);
    }

}



This is my CubeController.java!! Here I changed the bindKex with the Constants of my Wii.

package gamecontrols;

import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
import wiiremotej.*;
import wiiremotej.event.*;
import java.lang.Math;
import com.jme.math.Vector3f;

public class WiiRemoteProxy extends BalanceBoardAdapter implements BalanceBoardListener{

   private WiiRemote      mcl_remotee;
   public Vector3f         mcl_wiiTx = new Vector3f();
   private BalanceBoard    remote;
   private static double   totalmass = 0;
   private static boolean   connected = false;
   
   private static double horizontal = 400;
   private static double vertical = 300;
   
      
   public void findWii(){
   
      BalanceBoard remote = null;
      
      try
      {
      
      remote = WiiRemoteJ.connectToBalanceBoard("00233199ddc0");
      remote.addBalanceBoardListener(this);
        //requesting for status
       remote.setLEDIlluminated(true);
       remote.requestStatus();
      
      }
       catch(Exception e)
       {
          e.printStackTrace();
       }
   }
   
   public WiiRemoteProxy(BalanceBoard remote)
   {
      connected = true;
      this.remote = remote;
   }
   
   public void disconnected()
   {
      System.out.println("Remote disconnected... Please Wii again.");
      System.exit(0);
   }
   
   
   public void buttonInputReceived(BBButtonEvent evt)
   {
      if(evt.isPressed())
         remote.disconnect();
   }
   
   
   public void statusReported(BBStatusEvent evt)
   {
      //Print out the level of battery
      System.out.println(evt.getBatteryLevel());
   }
   
   
   public void massInputReceived(BBMassEvent evt)
   {
      totalmass = evt.getTotalMass();
      System.out.println(totalmass);
      
      double massRightTop = evt.getMass(MassConstants.TOP, MassConstants.RIGHT);
       double massLeftTop = evt.getMass(MassConstants.TOP, MassConstants.LEFT);
       double massRightBottom = evt.getMass(MassConstants.BOTTOM, MassConstants.RIGHT);
       double massLeftBottom = evt.getMass(MassConstants.BOTTOM, MassConstants.LEFT);      
   
   
   //if bellow 20kg
   if (totalmass < 20)
   {// deltas are +/- how much kg in each direction
        double horizontalDelta = (massRightTop + massRightBottom) - (massLeftTop + massLeftBottom);
        double verticalDelta = (massLeftBottom + massRightBottom) - (massLeftTop + massRightTop);
   
        // we now need to make them relative to mass and work out position
        horizontal = (horizontalDelta / totalmass  * 400) + 400;
        vertical = (verticalDelta / totalmass * 300) + 300;
   
     } else {
        horizontal = 400;
        vertical = 300;
     }
   }
}



This is my WiiRemoteProxy.java!  It checks the connections and got a lot of information (more than I need at the moment... dont mind that *g*)

Now I come to the problem:

In the Main.java I have to make the test if the balanceboard is logged on and then log it on. So I have to get a connection to the WiiRemoteProcy.java

package gamecontrols;

import wiiremotej.BalanceBoard;

import com.jmex.game.StandardGame;
import com.jmex.game.state.GameState;
import com.jmex.game.state.GameStateManager;


public class Main{
   public      WiiRemoteProxy         remote;
   private static StandardGame standardGame;

   
   public static void main(String[]args){
      
      
      standardGame = new StandardGame("GameControl", StandardGame.GameType.GRAPHICAL, null);
      standardGame.start();
      
      GameState cubeState = new CubeGameState();
      
   //   cubeState.remote = new WiiRemoteProxy();
   //   cubeState.remote.findWii();
      
        GameStateManager.getInstance().attachChild(cubeState);
        cubeState.setActive(true);
   }
}



I thought I could do whats behind the comment lines at the end. Bind it somehow to the WiiRemoteProxy.java for the check. But I get an error saying The contructor WiiRemoteProxy() is undefined, and cubeState.remote cannt be resoled or is no field...

Any ideas?

PS: I wanna thanks ncomp for sharing his code...

RapidM

You probably need a default constructor in your WiiRemoteProxy class…





For the un-resovled object you are creating a GameState object not a CubeGameState object, try:


CubeGameState cubeState = new CubeGameState();
cubeState.remote = new WiiRemoteProxy();

Hi…



Changed it to


GameState cubeState = new CubeGameState();
      
      cubeState.remote = new WiiRemoteProxy(null);
      cubeState.remote.findWii();



Now it tests correctly and shows me the binary datas on the console.

I got one more (think it's the last) question:

In the cubeController I used this contants from the balanceboard to bind the keys:

   //bind keys
        bindKey(EXIT, KEY_X);
        bindKey(UP, MassConstants.TOP);
        bindKey(DOWN, MassConstants.BOTTOM);
        bindKey(LEFT, MassConstants.LEFT);
        bindKey(RIGHT, MassConstants.RIGHT);



But when standing on the balanceboard it just shows me the binary data on the console like:

0.06028368794326241
0.06028368794326241
0.11052009456264775
0.11052009456264775



So it has a motion but it can't use this constants in the bind key function.

Next thing I tried using the

public void massInputReceived(BBMassEvent evt)
   {
      totalmass = evt.getTotalMass();
      System.out.println(totalmass);
      
      double massRightTop = evt.getMass(MassConstants.TOP, MassConstants.RIGHT);
       double massLeftTop = evt.getMass(MassConstants.TOP, MassConstants.LEFT);
       double massRightBottom = evt.getMass(MassConstants.BOTTOM, MassConstants.RIGHT);
       double massLeftBottom = evt.getMass(MassConstants.BOTTOM, MassConstants.LEFT);      
   
   



from the WiiRemoteProxy.java !

How can I for example use the value of massRightTop at the keybinding function?

Thanks Rapidm

:?

So it seems to me as you would like to just get a single keycommand when there is action on the balanceboard??

So you have to add some code which defines which values should trigger the event.

By using bindKey(EXIT, KEY_X) you are binding a double-value (which is changing constantly) as a trigger for the event.



But what you would need to do is something you're allready using in you update()

if (value(EXIT) > 0) { // alter the condition that it fits your needs

            System.exit(0); //OK, this is just a demo…

        }



Just a thought, i haven't taken a closer look onto your code 'til now… so maybe i'm totaly wrong.


some progress?

Still trying to figure it out :wink:

I am still trying to manage one problem:



The result of my balanceboard code are

double horizontal and double vertical

. As you can figure out it means the vertical and horizontal axis.



Now I just have to bind it as a controller. What do I have to use? With keyboards I have the problem that I am only allowed to uses int - values. 

 bindKey(EXIT, KEY_X);





Is it easier with joysticks?



Thanks Rapidm


And one more question:



Hoe do I get the actual window size? I need it in order to make the math right…





THANKS

I tried my own controller class  BalanceBoardBinding  (changed it from MouseAxisBinding)…



But I got baaad errors:


21.02.2009 11:52:01 com.jme.input.joystick.DummyJoystickInput <init>
INFO: Joystick support is disabled
21.02.2009 11:52:01 com.jme.system.lwjgl.LWJGLDisplaySystem <init>
INFO: LWJGL Display System created.
21.02.2009 11:52:02 com.jme.renderer.lwjgl.LWJGLRenderer <init>
INFO: LWJGLRenderer created. W:  640H: 480   Version: 2.0.1
21.02.2009 11:52:02 com.jme.renderer.AbstractCamera <init>
INFO: Camera created.
21.02.2009 11:52:02 com.jmex.audio.openal.OpenALSystem setupSourcePool
INFO: max source channels: 64
21.02.2009 11:52:02 com.jmex.game.state.GameStateManager create
INFO: Created GameStateManager
21.02.2009 11:52:02 com.jme.util.lwjgl.LWJGLTimer <init>
INFO: Timer resolution: 1000 ticks per second
21.02.2009 11:52:02 com.jme.scene.Node <init>
INFO: Node created.
21.02.2009 11:52:03 com.jme.scene.Node <init>
INFO: Node created.
21.02.2009 11:52:03 com.jme.scene.Node attachChild
INFO: Child (MonkeyBox) attached to this node (MonkeyBoxNode)
21.02.2009 11:52:03 com.jme.scene.Node attachChild
INFO: Child (MonkeyBoxNode) attached to this node (cubeGameState: RootNode)
BlueCove version 2.1.0 on widcomm

21.02.2009 11:52:05 com.jmex.game.DefaultUncaughtExceptionHandler uncaughtException
SCHWERWIEGEND: Main game loop broken by uncaught exception
java.lang.NullPointerException
   at com.jme.input.controls.binding.BalanceBoardBinding.getValue(BalanceBoardBinding.java:87)
   at com.jme.input.controls.GameControl.getValue(GameControl.java:104)
   at gamecontrols.CubeController.value(CubeController.java:96)
   at gamecontrols.CubeController.update(CubeController.java:104)
   at com.jme.scene.Spatial.updateWorldData(Spatial.java:541)
   at com.jme.scene.Node.updateWorldData(Node.java:383)
   at com.jme.scene.Spatial.updateGeometricState(Spatial.java:517)
   at com.jmex.game.state.BasicGameState.update(BasicGameState.java:71)
   at com.jmex.game.state.GameStateNode.update(GameStateNode.java:71)
   at com.jmex.game.StandardGame.update(StandardGame.java:381)
   at com.jmex.game.StandardGame.run(StandardGame.java:250)
   at java.lang.Thread.run(Unknown Source)
BlueCove stack shutdown completed



So maybe someone could look over my code:

BalanceBoardBinding.java:

/*
 * Copyright (c) 2003-2009 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.jme.input.controls.binding;

import com.jme.input.MouseInput;
import com.jme.input.controls.Binding;

import gamecontrols.WiiRemoteProxy;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
import wiiremotej.*;
import wiiremotej.event.*;
import java.lang.Math;

/**
 * @author Matthew D. Hicks
 */
public class BalanceBoardBinding implements Binding {
   
    private static final long serialVersionUID = 1L;
   public      WiiRemoteProxy         remote;

    public static final int AXIS_X = 1;
    public static final int AXIS_Y = 2;
    public static final int AXIS_W = 3;
   
    private int axis;
    public boolean reverse;
   
    public BalanceBoardBinding(int axis, boolean reverse) {
        this.axis = axis;
        this.reverse = reverse;
    }
   
   public String getName() {
      if (reverse) {
            return "Mouse" + getAxisString(axis) + "(-)";
        } else {
            return "Mouse" + getAxisString(axis) + "(+)";
        }
   }
   
    public double getHorizontal(){
      double control_horizontal = remote.getHorizontal();
      return control_horizontal;
      }
   

    public double getVerticall(){
      double control_vertical = remote.getVertical();
      return control_vertical;
      }
   
   public float getValue() {
        float value;
      if (axis == AXIS_X) {
          value = convert(remote.getHorizontal());
        } else if (axis == AXIS_Y) {
            value = convert(remote.getVertical());
        } else {
            value = convert(MouseInput.get().getWheelDelta());
        }
        return value;
   }
   
    private float convert(double value) {
        if ((value < 0) && (!reverse)) return 0.0f;
        if ((value > 0) && (reverse)) return 0.0f;
        return Math.abs((float)value * 0.1f);
    }

    public String toString() {
      return getName();
   }
   
    private static final String getAxisString(int axis) {
        if (AXIS_X == axis) return "X";
        else if (AXIS_Y == axis) return "Y";
        else if (AXIS_W == axis) return "W";
        return "Unknown";
    }
}



CubeController.java

package gamecontrols;
 
import com.jme.input.controls.GameControl;
import com.jme.input.controls.GameControlManager;
import com.jme.input.controls.binding.KeyboardBinding;
import com.jme.input.controls.binding.MouseButtonBinding;
import com.jme.input.controls.binding.MouseAxisBinding;
import com.jme.scene.Controller;
import com.jme.scene.Node;
import static gamecontrols.CubeController.CubeAction.*;
import static com.jme.input.KeyInput.*;
import static com.jme.input.controls.binding.MouseButtonBinding.*;
import static com.jme.input.controls.binding.MouseAxisBinding.*;
import com.jme.input.controls.binding.BalanceBoardBinding;
import static com.jme.input.controls.binding.BalanceBoardBinding.*;

import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
import wiiremotej.*;
import wiiremotej.event.*;
import java.lang.Math;

import gamecontrols.WiiRemoteProxy;
 
public class CubeController extends Controller{
   
   public      WiiRemoteProxy         remote;
   
    enum CubeAction {LEFT, RIGHT, UP, DOWN, EXIT};
 
    private final static float SPEED = 2F;
 
    private final Node node;
    private final GameControlManager manager;
    private float vAngle = 0F;
    private float hAngle = 0F;
 
    
   
    public CubeController(Node node) {
        this.node = node;
        this.manager = new GameControlManager();
       
       
              
 
        //create all actions
        for (CubeAction action : CubeAction.values()) {
            manager.addControl(action.name());
        }
       
  //     double getMassRightTop2 = remote.getMassRightTop();
               
        //bind keys
        bindKey(EXIT, KEY_X);
        bindKey(UP, KEY_UP);
        bindKey(DOWN, KEY_DOWN);
        bindKey(LEFT, KEY_LEFT);
        bindKey(RIGHT, KEY_RIGHT);
 
        //bind mouse buttons
        bindMouseButton(LEFT, LEFT_BUTTON);
        bindMouseButton(RIGHT, RIGHT_BUTTON);
       
       
        //BalanceBoard binding
        bindBalanceBoard(LEFT, 1);
        bindBalanceBoard(UP, 2);
      
    }
 
 
    private void bindKey(CubeAction action, int... keys) {
        final GameControl control = manager.getControl(action.name());
        for (int key : keys) {
          control.addBinding(new KeyboardBinding(key));
        }
    }
   
    private void bindBalanceBoard(CubeAction action, int axis){
        final GameControl control = manager.getControl(action.name());
        control.addBinding(new BalanceBoardBinding(axis, active));
    }
   
   

 
    private void bindMouseButton(CubeAction action, int mouseButton) {
        final GameControl control = manager.getControl(action.name());
        control.addBinding(new MouseButtonBinding(mouseButton));
    }
 
  
    private float value(CubeAction action) {
        return manager.getControl(action.name()).getValue();
    }
 
    @Override
    public void update(float time) {
        if (value(EXIT) > 0) {
            System.exit(0); //OK, this is just a demo...
        }
        hAngle += SPEED * time * (value(RIGHT) - value(LEFT));
        vAngle += SPEED * time * (value(DOWN) - value(UP));
        node.getLocalRotation().fromAngles(vAngle, hAngle, 0f);
    }

}



and WiiMoteProxy.java

package gamecontrols;

import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
import wiiremotej.*;
import wiiremotej.event.*;
import java.lang.Math;
import com.jme.math.Vector3f;

public class WiiRemoteProxy extends BalanceBoardAdapter implements BalanceBoardListener{

   private WiiRemote      mcl_remotee;
   public Vector3f         mcl_wiiTx = new Vector3f();
   private BalanceBoard    remote;
   private static double   totalmass = 0;
   private static boolean   connected = false;
   
   private static double horizontal = 400;
   private static double vertical = 300;
   
      
   public void findWii(){
   
      BalanceBoard remote = null;
      
      try
      {
      
      remote = WiiRemoteJ.connectToBalanceBoard("00233199ddc0");
      remote.addBalanceBoardListener(this);
        //requesting for status
       remote.setLEDIlluminated(true);
       remote.requestStatus();
      
      }
       catch(Exception e)
       {
          e.printStackTrace();
       }
   }
   
   public WiiRemoteProxy(BalanceBoard remote)
   {
      connected = true;
      this.remote = remote;
   }
   
   public void disconnected()
   {
      System.out.println("Remote disconnected... Please Wii again.");
      System.exit(0);
   }
   
   
   public void buttonInputReceived(BBButtonEvent evt)
   {
      if(evt.isPressed())
         remote.disconnect();
   }
   
   
   public void statusReported(BBStatusEvent evt)
   {
      //Print out the level of battery
      System.out.println(evt.getBatteryLevel());
   }
   
   
   
   public void massInputReceived(BBMassEvent evt)
   {
      totalmass = evt.getTotalMass();
      System.out.println(totalmass);
      

      double massRightTop = evt.getMass(MassConstants.TOP, MassConstants.RIGHT);
       double massLeftTop = evt.getMass(MassConstants.TOP, MassConstants.LEFT);
       double massRightBottom = evt.getMass(MassConstants.BOTTOM, MassConstants.RIGHT);
       double massLeftBottom = evt.getMass(MassConstants.BOTTOM, MassConstants.LEFT);      
   
   
   //if bellow 20kg
   if (totalmass > 20)
   {// deltas are +/- how much kg in each direction
        double horizontalDelta = (massRightTop + massRightBottom) - (massLeftTop + massLeftBottom);
        double verticalDelta = (massLeftBottom + massRightBottom) - (massLeftTop + massRightTop);
   
        // we now need to make them relative to mass and work out position
        horizontal = (horizontalDelta / totalmass  * 400) + 400;
        vertical = (verticalDelta / totalmass * 300) + 300;
   
     } else {
        horizontal = 400;
        vertical = 300;
     }
   }
   public double getHorizontal(){
       return horizontal;
      }
   
   public double getVertical(){
       return vertical;
      }

   
}



At the WiimoteProxy.java I wrote two new function  getHorizontal() and getVertical() which I needed for the Controller Axis. The double horizontal is for AXIS_X  and the double vertical for AXIS_Y

Could you look over the code and maybe find my problem(S)?

Thanks
java.lang.NullPointerException
at com.jme.input.controls.binding.BalanceBoardBinding.getValue(BalanceBoardBinding.java:87)

The exception means, that a variable in line 87 in the BalanceBoardBinding.java is null.
So you have to initlialize it.

Thanks to a good friend of mine it works :wink:



Want to share the code real quick:



WiiRemoteProxy.java


package gamecontrols;

import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
import wiiremotej.*;
import wiiremotej.event.*;
import java.lang.Math;
import com.jme.math.Vector3f;

public class WiiRemoteProxy extends BalanceBoardAdapter implements BalanceBoardListener{

   public Vector3f         mcl_wiiTx = new Vector3f();
   private BalanceBoard    remote = null;
   private static double   totalmass = 0;
   private static boolean   connected = false;
   
   private static double horizontal = 0.0;
   private static double vertical = 0.0;
   
      
   public void findWii(){
   
      remote = null;
      
      try
      {
      
      remote = WiiRemoteJ.connectToBalanceBoard("00233199ddc0");
      remote.addBalanceBoardListener(this);
        //requesting for status
       remote.setLEDIlluminated(true);
       remote.requestStatus();
      
      }
       catch(Exception e)
       {
          e.printStackTrace();
       }
   }
   
   public WiiRemoteProxy()
   {
      findWii();
      connected = true;
      System.out.println("SUCCESFULLY CONNECTED BB");
   }   
   
   public void buttonInputReceived(BBButtonEvent evt)
   {
      if(evt.isPressed()) {
         remote.disconnect();
         System.out.println("DISCONNECTED BB");
      }
   }
   
   
   public void statusReported(BBStatusEvent evt)
   {
      //Print out the level of battery
      System.out.println("Battery: " + evt.getBatteryLevel());
   }
   
   
   
   public void massInputReceived(BBMassEvent evt)
   {
      totalmass = evt.getTotalMass();

      

      double massRightTop = evt.getMass(MassConstants.TOP, MassConstants.RIGHT);
       double massLeftTop = evt.getMass(MassConstants.TOP, MassConstants.LEFT);
       double massRightBottom = evt.getMass(MassConstants.BOTTOM, MassConstants.RIGHT);
       double massLeftBottom = evt.getMass(MassConstants.BOTTOM, MassConstants.LEFT);      
   
   
   //if bellow 20kg
   if (totalmass > 20)
   {// deltas are +/- how much kg in each direction
        double horizontalDelta = (massRightTop + massRightBottom) - (massLeftTop + massLeftBottom);
        double verticalDelta = (massLeftBottom + massRightBottom) - (massLeftTop + massRightTop);
   
        // we now need to make them relative to mass and work out position
        horizontal = horizontalDelta / totalmass;
        vertical = verticalDelta / totalmass;
   
     } else {
        horizontal = 0.0;
        vertical = 0.0;
     }
   }
   public double getHorizontal(){
       return horizontal;
      }
   
   public double getVertical(){
       return vertical;
      }

   
}



CubeGameState.java

package gamecontrols;
 
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.light.PointLight;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;
import com.jme.scene.state.LightState;
import com.jme.scene.state.MaterialState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jmex.game.state.BasicGameState;
 
/**
 *
 * @author Gronau
 */
public class CubeGameState extends BasicGameState {
 
    private static String texture = "jmetest/data/images/Monkey.jpg";
   public      WiiRemoteProxy         remote;

   
    public CubeGameState() {
        super("cubeGameState");
        final Box box = new Box("MonkeyBox", new Vector3f(0, 0, 0), 5, 5, 5);
 
        //Material: gray
        final MaterialState ms = DisplaySystem.getDisplaySystem().getRenderer().createMaterialState();
        ms.setEmissive(new ColorRGBA(0.5f, 0.5f, 0.5f, 1));
        box.setRenderState(ms);
 
        //Texture: the Monkey
        final TextureState ts = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
        final Texture t = TextureManager.loadTexture(
                BasicGameState.class.getClassLoader().getResource(texture),
                Texture.MinificationFilter.BilinearNoMipMaps,
                Texture.MagnificationFilter.Bilinear);
        ts.setTexture(t);
        box.setRenderState(ts);
        box.setModelBound(new BoundingBox());
        box.updateModelBound();
        Node boxNode = new Node("MonkeyBoxNode");
        boxNode.attachChild(box);
        getRootNode().attachChild(boxNode);
 
        //Spot on!
        final PointLight light = new PointLight();
        light.setDiffuse(new ColorRGBA(0.75f, 0.75f, 0.75f, 0.75f));
        light.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
        light.setLocation(new Vector3f(100, 100, 100));
        light.setEnabled(true);
 
        final LightState lightState = DisplaySystem.getDisplaySystem().getRenderer().createLightState();
        lightState.setEnabled(true);
        lightState.attach(light);
        getRootNode().setRenderState(lightState);
 
        getRootNode().updateRenderState();
        //Oh, and don't forget the controller...
        getRootNode().addController(new CubeController(boxNode));
    }
}



CubeController.java

package gamecontrols;
 
import com.jme.input.controls.GameControl;
import com.jme.input.controls.GameControlManager;
import com.jme.input.controls.binding.KeyboardBinding;
import com.jme.input.controls.binding.MouseButtonBinding;
import com.jme.input.controls.binding.MouseAxisBinding;
import com.jme.scene.Controller;
import com.jme.scene.Node;
import static gamecontrols.CubeController.CubeAction.*;
import static com.jme.input.KeyInput.*;
import static com.jme.input.controls.binding.MouseButtonBinding.*;
import static com.jme.input.controls.binding.MouseAxisBinding.*;
import com.jme.input.controls.binding.BalanceBoardBinding;
import static com.jme.input.controls.binding.BalanceBoardBinding.*;

import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
import wiiremotej.*;
import wiiremotej.event.*;
import java.lang.Math;

import gamecontrols.WiiRemoteProxy;
 
public class CubeController extends Controller{
   
   public      WiiRemoteProxy         balanceBoard;
   
    enum CubeAction {LEFT, RIGHT, UP, DOWN, EXIT, TURN, TILT};
 
    private final static float SPEED = 2F;
 
    private final Node node;
    private final GameControlManager manager;
    private float vAngle = 0F;
    private float hAngle = 0F;
 
     
   
    public CubeController(Node node) {
        this.node = node;
        this.manager = new GameControlManager();
       
       
              
 
        //create all actions
        for (CubeAction action : CubeAction.values()) {
            manager.addControl(action.name());
        }
       
  //     double getMassRightTop2 = remote.getMassRightTop();
               
        //bind keys
        bindKey(EXIT, KEY_X);
        bindKey(UP, KEY_UP);
        bindKey(DOWN, KEY_DOWN);
        bindKey(LEFT, KEY_LEFT);
        bindKey(RIGHT, KEY_RIGHT);
 
        //bind mouse buttons
        bindMouseButton(LEFT, LEFT_BUTTON);
        bindMouseButton(RIGHT, RIGHT_BUTTON);
       
       
        balanceBoard = new WiiRemoteProxy();
        //BalanceBoard binding
        bindBalanceBoardAxis(TURN, BalanceBoardBinding.AXIS_X);
        bindBalanceBoardAxis(TILT, BalanceBoardBinding.AXIS_Y);
       
    }
 
 
    private void bindKey(CubeAction action, int... keys) {
        final GameControl control = manager.getControl(action.name());
        for (int key : keys) {
          control.addBinding(new KeyboardBinding(key));
        }
    }
   
    private void bindBalanceBoardAxis(CubeAction action, int axis){
        final GameControl control = manager.getControl(action.name());
        control.addBinding(new BalanceBoardBinding(balanceBoard, axis));
    }
     
    private void bindMouseButton(CubeAction action, int mouseButton) {
        final GameControl control = manager.getControl(action.name());
        control.addBinding(new MouseButtonBinding(mouseButton));
    }
 
   
    private float value(CubeAction action) {
        return manager.getControl(action.name()).getValue();
    }
 
    @Override
    public void update(float time) {
        if (value(EXIT) > 0) {
            System.exit(0); //OK, this is just a demo...
        }
        float turn = value(TURN); //value(RIGHT) - value(LEFT);
        float tilt = value(TILT); //value(DOWN) - value(UP);
       
        hAngle += SPEED * time * turn;
        vAngle += SPEED * time * tilt;
        node.getLocalRotation().fromAngles(vAngle, hAngle, 0f);
    }

}



BalanceBoardBinding.java

package com.jme.input.controls.binding;

import gamecontrols.WiiRemoteProxy;

import com.jme.input.controls.Binding;

public class BalanceBoardBinding implements Binding {
   
   public static final int AXIS_X = 1;
    public static final int AXIS_Y = 2;
   private      WiiRemoteProxy         balanceBoard;

    private static final long serialVersionUID = 1L;
    private int axis;
   
    public BalanceBoardBinding(WiiRemoteProxy balanceBoard, int axis) {
        this.balanceBoard = balanceBoard;
        this.axis = axis;
    }
   
   public float getValue() {
      float value = 0.0f;
      if(axis == AXIS_X){
      value = (float) balanceBoard.getHorizontal();
      }else {
         value = (float) balanceBoard.getVertical();
      }
      //System.out.println("BB:val: " + value);
        return value;
   }
   
   public String getName() {
        return "BB:X" + axis;
   }

}



and Main.java

package gamecontrols;

import com.jmex.game.StandardGame;
import com.jmex.game.state.GameState;
import com.jmex.game.state.GameStateManager;

public class Main{
   private static StandardGame standardGame;
   
   public static void main(String[]args){
      System.setProperty("bluecove.jsr82.psm_minimum_off", "true");
      
      standardGame = new StandardGame("GameControl", StandardGame.GameType.GRAPHICAL, null);
      standardGame.start();
      
      GameState cubeState = new CubeGameState();      

        GameStateManager.getInstance().attachChild(cubeState);
        cubeState.setActive(true);      
   }
}



Thanks for all the helpers