Skip to content

Instantly share code, notes, and snippets.

@PseudoSky
Last active November 24, 2015 07:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PseudoSky/04b2d5e350f5dcd55ee8 to your computer and use it in GitHub Desktop.
Save PseudoSky/04b2d5e350f5dcd55ee8 to your computer and use it in GitHub Desktop.
import java.util.ArrayList;
import java.util.Collections;
int index = 0;
int double_tap_threshold=1000;
int press_and_hold_time_threshold=200;
int press_and_hold_movement_threshold=4;
int rotate_speed=1;
boolean mousePressed = true;
//your input code should modify these!!
float screenTransX = 0;
float screenTransY = 0;
float screenRotation = 0;
float screenZ = 50f;
int i=0;
int n=0;
int m=0;
int resizeX=0;
int resizeY=0;
int md_x=0;
int md_y=0;
float resizeZ=0;
double distR=0;
double distZ=0;
double distXY=0;
int action=0;
// designates the blue grab circle size
int grabSize = 30;
int trialCount = 20; //this will be set higher for the bakeoff
float border = 0; //have some padding from the sides
int trialIndex = 0;
int errorCount = 0;
int startTime = 0; // time starts when the first click is captured
int finishTime = 0; //records the time of the final click
boolean userDone = false;
//******************** If you cant autocomplete change this to false
boolean rotating = true;
final int screenPPI = 120; //what is the DPI of the screen you are using
//Many phones listed here: https://en.wikipedia.org/wiki/Comparison_of_high-definition_smartphone_displays
private class Target
{
float x = 0;
float y = 0;
float rotation = 0;
float z = 0;
}
ArrayList<Target> targets = new ArrayList<Target>();
float inchesToPixels(float inch)
{
return inch*screenPPI;
}
void setup() {
//size does not let you use variables, so you have to manually compute this
size(400, 700); //set this, based on your sceen's PPI to be a 2x3.5" area.
rectMode(CENTER);
textFont(createFont("Arial", inchesToPixels(.15f))); //sets the font to Arial that is .3" tall
textAlign(CENTER);
//don't change this!
border = inchesToPixels(.2f); //padding of 0.2 inches
for (int i=0; i<trialCount; i++) //don't change this!
{
Target t = new Target();
t.x = random(-width/2+border, width/2-border); //set a random x with some padding
t.y = random(-height/2+border, height/2-border); //set a random y with some padding
t.rotation = random(0, 360); //random rotation between 0 and 360
t.z = ((i%20)+1)*inchesToPixels(.15f); //increasing size from .15 up to 3.0"
targets.add(t);
println("created target with " + t.x + "," + t.y + "," + t.rotation + "," + t.z);
}
Collections.shuffle(targets); // randomize the order of the button; don't change this.
}
void draw() {
background(60); //background is dark grey
fill(200);
noStroke();
if (startTime == 0)
startTime = millis();
if (userDone)
{
text("User completed " + trialCount + " trials", width/2, inchesToPixels(.2f));
text("User had " + errorCount + " error(s)", width/2, inchesToPixels(.2f)*2);
text("User took " + (finishTime-startTime)/1000f/trialCount + " sec per target", width/2, inchesToPixels(.2f)*3);
return;
}
//===========DRAW TARGET SQUARE=================
pushMatrix();
translate(width/2, height/2); //center the drawing coordinates to the center of the screen
Target t = targets.get(trialIndex);
translate(t.x, t.y); //center the drawing coordinates to the center of the screen
rotate(radians(t.rotation));
fill(0);
ellipse(0, 0, sqrt(2)*t.z + grabSize, sqrt(2)*t.z + grabSize);
fill(255, 0, 0); //set color to red
rect(0, 0, t.z, t.z);
stroke(10);
fill(0);
line(0,0, t.z/2, t.z/2);
//line(t.z/2, t.z/2);
popMatrix();
distR= abs((t.rotation%90)-(screenRotation%90));
distXY=dist(t.x,t.y,screenTransX,screenTransY);
distZ=abs(t.z - screenZ);
println(t.x+" "+t.y+" "+screenTransX+" "+screenTransY+" "+distR+" "+dist(t.x,t.y,screenTransX,screenTransY)+" "+calculateDifferenceBetweenAngles(t.rotation,screenRotation));
boolean closeRotation = distR<=5;
boolean closeXY=distXY<inchesToPixels(.05f);
boolean closeZ = distZ<inchesToPixels(.05f); //has to be within .1"
//===========DRAW TARGETTING SQUARE=================
pushMatrix();
translate(width/2, height/2);
translate(screenTransX,screenTransY); //center the drawing coordinates to the center of the screen
rotate(radians(screenRotation));
fill(0, 255, 255, 20);
if (closeRotation){
fill(0, 200-(float)distXY, 0,70);
}
fill(250-(float)distXY*2,20,0,70);
if (closeXY){
fill(0, 250-(float)distXY*2, 0,70);
}
//draw grab circle
ellipse(0, 0, sqrt(2)*screenZ + grabSize, sqrt(2)*screenZ + grabSize);
fill(60, 128,0,40);
if (closeZ){
fill(0,200, 0,70);
}
ellipse(0, 0, sqrt(2)*screenZ, sqrt(2)*screenZ);
//draw square
rect(0, 0, screenZ, screenZ);
popMatrix();
//===========DRAW TRAFFIC LIGHT=========================
fill(255-(float)distR, 255-(float)distR, 255-(float)distR,30);
if (closeRotation){
fill(0, 255, 0,70);
}
ellipse(60,30,30,30);
fill(255-(float)distZ, 255-(float)distZ, 255-(float)distZ,30);
if (closeZ){
fill(0,255- (float)distZ, 0,70);
}
ellipse(30,30,30,30);
fill(255-(float)distXY, 255-(float)distXY, 255-(float)distXY);
if (closeXY){
fill(0, 255-(float)distXY, 0,70);
}
ellipse(90,30,30,30);
scaffoldControlLogic(); //you are going to want to replace this!
fill(255);
text("Trial " + (trialIndex+1) + " of " +trialCount, width/2, inchesToPixels(.5f));
}
void scaffoldControlLogic()
{
//println("i: "+i + " m "+ (millis()-m)+ " d: "+dist(md_x,md_y,mouseX,mouseY) + " rot " + screenRotation);
if(i==1 && millis()-m>press_and_hold_time_threshold){
if(dist(md_x,md_y,mouseX,mouseY) < press_and_hold_movement_threshold){
action=1;
}else{
action=2;
}
action=2;
i=0;
}
if(!mousePressed){
action=0;
}
// auto progress
if (checkForSuccess())
{
next();
return;
}
if(rotating){
screenRotation+=rotate_speed;
screenRotation=screenRotation%360;
}else{
screenRotation= -atan((mouseX-md_x)/(mouseY-md_y+.01))*180/PI;
}
if (action==0)
{
screenTransX = mouseX-width/2;
screenTransY = mouseY-height/2;
}
if(action==2)
{
screenZ = dist(md_x,md_y,mouseX,mouseY );
}
}
void mousePressed()
{
if(i==0){
m = millis();
}
i++;
if(i==2){
n=millis();
}
md_x=mouseX;
md_y=mouseY;
mousePressed = true;
}
void mouseReleased()
{
if(i==2){
if(n-m < double_tap_threshold){
action=1;
resizeX=mouseX;
resizeY=mouseY;
resizeZ=screenZ;
rotating=!rotating;
}
i=0;
n=0;
m=0;
}
action=0;
mousePressed = false;
}
public boolean checkForSuccess()
{
Target t = targets.get(trialIndex);
boolean closeDist = dist(t.x,t.y,screenTransX,screenTransY)<inchesToPixels(.05f); //has to be within .1"
boolean closeRotation = (abs((t.rotation%90)-(screenRotation%90))<=5)||abs((screenRotation-t.rotation)%90)<=5;
boolean closeZ = abs(t.z - screenZ)<inchesToPixels(.05f); //has to be within .1"
return closeDist && closeRotation && closeZ;
}
double calculateDifferenceBetweenAngles(float a1, float a2)
{
a1+=360;
a2+=360;
if (abs(a1-a2)>45)
return abs(abs(a1-a2)%90-90);
else
return abs(a1-a2)%90;
}
boolean moveBox(){
//mouse pressed outside of resize ring
return (mousePressed && ((dist(mouseX,mouseY, screenTransX, screenTransY) < sqrt(2)*screenZ/2) || ( dist(mouseX,mouseY, screenTransX, screenTransY) > sqrt(2)*screenZ/2 + grabSize)));
}
boolean resizeBox(){
//mouse pressed inside resize ring
return (mousePressed && ((dist(mouseX,mouseY, screenTransX, screenTransY) > sqrt(2)*screenZ/2) && (dist(mouseX,mouseY, screenTransX, screenTransY) < sqrt(2)*screenZ/2 + grabSize)));
}
void next()
{
//called when boxes sucessfully overlapped
if (userDone==false && !checkForSuccess())
errorCount++;
//and move on to next trial
trialIndex++;
screenTransX = 0;
screenTransY = 0;
if (trialIndex==trialCount && userDone==false)
{
userDone = true;
finishTime = millis();
}
screenZ=20;
i=0;
n=0;
m=0;
mousePressed=false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment