Posts Tagged ‘Joystick’

Joystick Simulation with Processing

June 17, 2009

If you’re building a control system for a robot, a new game or even controls in your house you probably need a way to interact with your program. The joystick is a common user input device to work with, however, the variety of types and device drivers can raise a few issues when working with multiple operating system.

In order to introduce joystick interaction for the Windows, Linux, and Mac operating systems we need a cross platform programming environment. The Processing Language gives us a way to simulate the joystick for each computing system.

After working with the Arduino and its programming environment, creating a program with the Processing Language has a familar look and feel.

Create a new Sketch in Processing called: JoystickSimulation

import processing.opengl.*;

/*---->>>
 Program: Joystick

 This program simulates using a joystick by using a mouse and
 the graphics features of Processing.

 Author: Vince Thompson
 http://www.twitter.com/SomeoneKnows

<<<----*/

int displayWidth = 640;
int displayHeight = 480;
int joyOutputRange = 90;  //Maximum value for full horiz or vert position where centered is 0.
int textHorizPos, textVertPos;  //Display positions for text feedback values.
int fontSpace = 12;

float curJoyDisplayWidth;
float curJoyDisplayHeight;

float maxJoyRange=200;     //Maximum joystick range
float curJoyAngle;     //Current joystick angle
float curJoyRange;     //Current joystick range
float joyDisplayCenterX;  //Joystick displayed Center X
float joyDisplayCenterY;  //Joystick displayed Center Y

float surfDisplayCenterX;
float surfDisplayCenterY;

float rSize;

boolean isMouseTracking=false;
color color1;
color color2;

void setup() {
  PFont font;
  size(displayWidth, displayHeight, OPENGL);
  joyDisplayCenterX = displayWidth/2;
  joyDisplayCenterY = 25 + maxJoyRange/2;
  curJoyDisplayWidth = maxJoyRange * .85;
  curJoyDisplayHeight = curJoyDisplayWidth;
  maxJoyRange = curJoyDisplayWidth / 2;

  surfDisplayCenterX=displayWidth/2;
  surfDisplayCenterY=displayHeight* .65;

  smooth();
  strokeWeight(10.0);
  stroke(0, 100);
  color1=color(0);  //Color = Black
  color2=color(150);  

  rSize = displayWidth/2;

  font = loadFont("Monospaced.bold-12.vlw");
  textFont(font);
}

void draw()
{
  float joyHorizontalText, joyVerticalText;

  background(226);

  float dx = mouseX - joyDisplayCenterX;
  float dy = mouseY - joyDisplayCenterY;

  if(mousePressed && (mouseButton == LEFT))
    isMouseTracking = true;

  if(mousePressed && (mouseButton == RIGHT))
    isMouseTracking = false;

  if (isMouseTracking)
  {
    curJoyAngle = atan2(dy, dx);
    curJoyRange = dist(mouseX, mouseY, joyDisplayCenterX, joyDisplayCenterY);
  }
  else
  {
    curJoyRange = 0;
  }

  fill(200);
  noStroke();
  ellipse(joyDisplayCenterX, joyDisplayCenterY, curJoyDisplayHeight, curJoyDisplayWidth);

  stroke(0,100);
  segment(joyDisplayCenterX, joyDisplayCenterY, curJoyAngle);
  ellipse(joyDisplayCenterX, joyDisplayCenterY, 20, 20);

  fill(160,0,0);
  textHorizPos = 50;
  textVertPos = (int)(joyDisplayCenterY - 50);
  text("Horiz:", textHorizPos, textVertPos);
  textHorizPos += (4*fontSpace);
  joyHorizontalText = (joyOutputRange*(cos(curJoyAngle) * curJoyRange)/ maxJoyRange);
  text(nf(joyHorizontalText, 2, 1), textHorizPos, textVertPos);

  textHorizPos = 50;
  textVertPos += 12;  

  text("Vert:", textHorizPos, textVertPos);
  textHorizPos += (4*fontSpace);
  joyVerticalText = (joyOutputRange*(-(sin(curJoyAngle) * curJoyRange)/maxJoyRange));
  text(nf(joyVerticalText, 2, 1), textHorizPos, textVertPos);

  labySurface(joyHorizontalText, joyVerticalText);
}

void segment(float x, float y, float a)
{
  pushMatrix();
  translate(x, y);
  rotate(a);
  if (curJoyRange > maxJoyRange)
    curJoyRange = maxJoyRange;

  line(0, 0, curJoyRange, 0);
  popMatrix();
}

void labySurface(float angleHoriz, float angleVert)
{
  float radHoriz;
  float radVert;

  radHoriz = radians(angleHoriz) * .15;
  radVert = radians(angleVert-60) * .15;
  noFill();
  stroke(200);
  pushMatrix();
  translate(surfDisplayCenterX, surfDisplayCenterY, 0);
  rotateX(HALF_PI+ (radians(-60) * .15));
  box(rSize+5, rSize+5, 1);
  popMatrix();

  pushMatrix();
  stroke(0);
  translate(surfDisplayCenterX, surfDisplayCenterY, 0);
  rotateX(HALF_PI+radVert);
  rotateY(radHoriz);
  fill(0,20,240);
  box(rSize, rSize, 8);
  popMatrix();

}

Line 58 Error

Chances are you tried running the sketch and get the following error message:

java.lang.NullPointerException
at java.io.DataInputStream.readInt(DataInputStream.java:370)
at processing.core.PFont.<init>(PFont.java:128)
at processing.core.PApplet.loadFont(PApplet.java:3517)
at Joystick.setup(Joystick.java:77)
at processing.core.PApplet.handleDraw(PApplet.java:1400)
at processing.core.PApplet.run(PApplet.java:1328)
at java.lang.Thread.run(Thread.java:619)
Exception in thread “Animation Thread” java.lang.RuntimeException: Could not load font Monospaced.bold-12.vlw. Make sure that the font has been copied to the data folder of your sketch.
at processing.core.PApplet.die(PApplet.java:2186)
at processing.core.PApplet.die(PApplet.java:2195)
at processing.core.PApplet.loadFont(PApplet.java:3520)
at Joystick.setup(Joystick.java:77)
at processing.core.PApplet.handleDraw(PApplet.java:1400)
at processing.core.PApplet.run(PApplet.java:1328)
at java.lang.Thread.run(Thread.java:619)

If this happens, the compiler is complaining because it doesn’t find the specified font. When you create a new Processing sketch it places it in a new folder. The font needs to be added to the data folder.

Creating the font file is accomplished by selecting Tools -> Create Font … from the Processing Menu.

Processings Tools-Create Font... selection

Processing's Tools->Create Font... selection

This brings up a dialog box to make your font selection.

Selecting the Monospaced.bold font

Selecting the Monospaced.bold font

Locate the Monospaced.bold font type then change the font size selection to 12, when done press the OK button.

(c) 2009 – Vince Thompson
Advertisements