Keep the position when not clicking

I’m doing a project that we need to rotate an circular image relativity to the mouse.

The circle only moves when we click and drag the hand (mouse). When we are not dragging the mouse the image doesn’t move, which is good. However, if we stop clicking and start dragging on a different position it does the same as if we were clicking and dragging it.

This is a part of the code we have:

draw():
pushMatrix();
translate(width/2, height/2);
float rotAngle = atan2(dragY - height/2, dragX - width/2);
rotate(rotAngle);
image(abc, 0, 0, ABC_SIZE, ABC_SIZE);
popMatrix();
mouseDragged():
dragX = mouseX;
dragY = mouseY;

images:

Maybe show your entire code please and then we can test

The atan2 line uses dragY.
When this still has its old value, that’s bad.

Maybe update it in function mousePressed when dragging starts

1 Like

Hello,

I changed category to Processing.py. Is that what you are using?

Get to know the resources available to you.
There is a tab on top of page for Processing.py also.

Resources < Click here to expand !

I encourage you to review the resources available here:

:)

Please format your code as a courtesy to others:
https://discourse.processing.org/faq#format-your-code

:)

Hello,

Your code worked in Processing as is with some modification.

I removed mouseDragged() from draw and used it as follows:

int dragX;
int dragY;

void setup()
  {
  size(400, 400);
  }

void draw()
  {
 //Your code
 // I also added circles and did not use image 
  }
  
// Updates only if inside circle (you set limits); this can be adapted for more control.
void mouseDragged()
  {
  //Equation to a circle; limiting mouse update to within circle.
  if (((mouseX-width/2)*(mouseX-width/2)+ (mouseY-width/2)*(mouseY-width/2)) < 110*110)
    {
    dragX = mouseX;
    dragY = mouseY;
    }  
  }

Take a look at the simple example I provided and try to understand it; this can be adapted for your use.

Some references for Processing:
https://processing.org/examples/button.html
https://processing.org/examples/mousefunctions.html

image

:)

import java.util.Arrays;
import java.util.Collections;
import java.util.Random;

// Screen resolution vars;
float PPI, PPCM;
float SCALE_FACTOR;

// Finger parameters
PImage fingerOcclusion;
int FINGER_SIZE;
int FINGER_OFFSET;

// Arm/watch parameters
PImage arm;
int ARM_LENGTH;
int ARM_HEIGHT;

// Abc parameters
PImage abc;
int ABC_SIZE;

// Check parameters
PImage check;
int CHECK_SIZE;

// Study properties
String[] phrases; // contains all the phrases that can be tested
int NUM_REPEATS = 2; // the total number of phrases to be tested
int currTrialNum = 0; // the current trial number (indexes into phrases array above)
String currentPhrase = “”; // the current target phrase
String currentTyped = “”; // what the user has typed so far
char currentLetter = ‘a’;

// Performance variables
float startTime = 0; // time starts when the user clicks for the first time
float finishTime = 0; // records the time of when the final trial ends
float lastTime = 0; // the timestamp of when the last trial was completed
float lettersEnteredTotal = 0; // a running total of the number of letters the user has entered (need this for final WPM computation)
float lettersExpectedTotal = 0; // a running total of the number of letters expected (correct phrases)
float errorsTotal = 0; // a running total of the number of errors (when hitting next)

int dragX = width/2; // the position of the mouse when dragged
int dragY = height/2;

int lastX, lastY;

//Setup window and vars - runs once
void setup()
{
//size(900, 900);
fullScreen();
textFont(createFont(“Arial”, 24)); // set the font to arial 24
noCursor(); // hides the cursor to emulate a watch environment

// Load images
arm = loadImage(“arm_watch.png”);
fingerOcclusion = loadImage(“finger.png”);
abc = loadImage(“abc.png”);
check = loadImage(“check.png”);

// Load phrases
phrases = loadStrings(“phrases.txt”); // load the phrase set into memory
Collections.shuffle(Arrays.asList(phrases), new Random()); // randomize the order of the phrases with no seed

// Scale targets and imagens to match screen resolution
SCALE_FACTOR = 1.0 / displayDensity(); // scale factor for high-density displays
String[] ppi_string = loadStrings(“ppi.txt”); // the text from the file is loaded into an array.
PPI = float(ppi_string[1]); // set PPI, we assume the ppi value is in the second line of the .txt
PPCM = PPI / 2.54 * SCALE_FACTOR; // do not change this!

FINGER_SIZE = (int)(11 * PPCM);
FINGER_OFFSET = (int)(0.8 * PPCM);
ARM_LENGTH = (int)(19 * PPCM);
ARM_HEIGHT = (int)(11.2 * PPCM);
ABC_SIZE = (int) (3.5 * PPCM);
CHECK_SIZE = (int) (1.5 * PPCM);
}

void draw()
{
// Check if we have reached the end of the study
if (finishTime != 0) return;

background(255); // clear background

// Draw arm and watch background
imageMode(CENTER);
image(arm, width/2, height/2, ARM_LENGTH, ARM_HEIGHT);

// Check if we just started the application
if (startTime == 0 && !mousePressed)
{
fill(0);
textAlign(CENTER);
text(“Tap to start time!”, width/2, height/2);
}
else if (startTime == 0 && mousePressed) nextTrial(); // show next sentence

// Check if we are in the middle of a trial
else if (startTime != 0)
{
textAlign(LEFT);
fill(100);
text("Phrase " + (currTrialNum + 1) + " of " + NUM_REPEATS, width/2 - 4.0PPCM, height/2 - 8.1PPCM); // write the trial count
text("Target: " + currentPhrase, width/2 - 4.0PPCM, height/2 - 7.1PPCM); // draw the target string
fill(0);
text("Entered: " + currentTyped + “|”, width/2 - 4.0PPCM, height/2 - 6.1PPCM); // draw what the user has entered thus far

// Draw very basic ACCEPT button - do not change this!
textAlign(CENTER);
noStroke();
fill(0, 250, 0);
rect(width/2 - 2*PPCM, height/2 - 5.1*PPCM, 4.0*PPCM, 2.0*PPCM);
fill(0);
text("ACCEPT >", width/2, height/2 - 4.1*PPCM);

// Draw screen areas    
// THIS IS THE ONLY INTERACTIVE AREA (4cm x 4cm); do not change size
noStroke();
noFill();
rect(width/2 - 2.0*PPCM, height/2 - 1.0*PPCM, 4.0*PPCM, 3.0*PPCM);

// Draw the letters in a circle
//imageMode(CENTER);
//image(abc, width/2, height/2, ABC_SIZE, ABC_SIZE);

// Rotate the letters
pushMatrix();
translate(width/2, height/2);
float rotAngle = atan2(dragY - height/2, dragX - width/2);
rotate(rotAngle);
image(abc, 0, 0, ABC_SIZE, ABC_SIZE);
lastX = dragX;
lastY = dragY;
popMatrix();  

// Draw the area where you put the letter wanted
stroke(0, 255, 0);
strokeWeight(2);
noFill();
rect(width/2 - 0.25*PPCM, height/2 - 1.8*PPCM, 0.5*PPCM, 0.5*PPCM);

// Draw the check
imageMode(CENTER);
image(check, width/2, height/2, CHECK_SIZE, CHECK_SIZE);

int points = 26;
float pointAngle = 360/points;
float radius = (3.5/2)*PPCM;
for(float angle = 0; angle < 360; angle = angle+pointAngle)
{
   float x = cos(radians(angle))*radius;
   float y = sin(radians(angle))*radius;
   
   line(x+width/2, y+height/2, width/2, height/2);
}
circle(width/2, height/2, 3.5*PPCM);

}

// Draw the user finger to illustrate the issues with occlusion (the fat finger problem)
imageMode(CORNER);
image(fingerOcclusion, mouseX - FINGER_OFFSET, mouseY - FINGER_OFFSET, FINGER_SIZE, FINGER_SIZE);
}

// Check if mouse click was within certain bounds
boolean didMouseClick(float x, float y, float w, float h)
{
return (mouseX > x && mouseX < x + w && mouseY > y && mouseY < y + h);
}

void mouseDragged()
{
if(didMouseClick(width/2 - 2.0PPCM, height/2 - 1.0PPCM, 4.0PPCM, 3.0PPCM)) // Test click on ‘keyboard’ area - do not change this condition!
{
dragX = mouseX;
dragY = mouseY;
}
else System.out.println(“debug: CLICK NOT ACCEPTED”);
}

void mousePressed()
{
if (didMouseClick(width/2 - 2PPCM, height/2 - 5.1PPCM, 4.0PPCM, 2.0PPCM)) nextTrial(); // Test click on ‘accept’ button - do not change this!
else if(didMouseClick(width/2 - 2.0PPCM, height/2 - 1.0PPCM, 4.0PPCM, 3.0PPCM)) // Test click on ‘keyboard’ area - do not change this condition!
{
// YOUR KEYBOARD IMPLEMENTATION NEEDS TO BE IN HERE! (inside the condition)

//DELETE Test click on left arrow
//if (didMouseClick(width/2 - ARROW_SIZE, height/2, ARROW_SIZE, ARROW_SIZE))
//{
//  currentLetter--;
//  if (currentLetter < '_') currentLetter = 'z';                  // wrap around to z
//}
// Test click on right arrow
//else if (didMouseClick(width/2, height/2, ARROW_SIZE, ARROW_SIZE))
//{
//  currentLetter++;
//  if (currentLetter > 'z') currentLetter = '_';                  // wrap back to space (aka underscore)
//}
// Test click on keyboard area (to confirm selection)
//else
//{
//  if (currentLetter == '_') currentTyped+=" ";                   // if underscore, consider that a space bar
//  else if (currentLetter == '`' && currentTyped.length() > 0)    // if `, treat that as a delete command
//    currentTyped = currentTyped.substring(0, currentTyped.length() - 1);
//  else if (currentLetter != '`') currentTyped += currentLetter;  // if not any of the above cases, add the current letter to the typed string
//}

}
else System.out.println(“debug: CLICK NOT ACCEPTED”);
}

void nextTrial()
{
if (currTrialNum >= NUM_REPEATS) return; // check to see if experiment is done

// Check if we’re in the middle of the tests
else if (startTime != 0 && finishTime == 0)
{
System.out.println("==================");
System.out.println("Phrase " + (currTrialNum+1) + " of " + NUM_REPEATS);
System.out.println("Target phrase: " + currentPhrase);
System.out.println("Phrase length: " + currentPhrase.length());
System.out.println("User typed: " + currentTyped);
System.out.println("User typed length: " + currentTyped.length());
System.out.println("Number of errors: " + computeLevenshteinDistance(currentTyped.trim(), currentPhrase.trim()));
System.out.println(“Time taken on this trial: " + (millis() - lastTime));
System.out.println(“Time taken since beginning: " + (millis() - startTime));
System.out.println(”==================”);
lettersExpectedTotal += currentPhrase.trim().length();
lettersEnteredTotal += currentTyped.trim().length();
errorsTotal += computeLevenshteinDistance(currentTyped.trim(), currentPhrase.trim());
}

// Check to see if experiment just finished
if (currTrialNum == NUM_REPEATS - 1)
{
finishTime = millis();
System.out.println("==================");
System.out.println(“Trials complete!”); //output
System.out.println("Total time taken: " + (finishTime - startTime));
System.out.println("Total letters entered: " + lettersEnteredTotal);
System.out.println("Total letters expected: " + lettersExpectedTotal);
System.out.println("Total errors entered: " + errorsTotal);

float wpm = (lettersEnteredTotal / 5.0f) / ((finishTime - startTime) / 60000f);   // FYI - 60K is number of milliseconds in minute
float freebieErrors = lettersExpectedTotal * .05;                                 // no penalty if errors are under 5% of chars
float penalty = max(errorsTotal - freebieErrors, 0) * .5f;

System.out.println("Raw WPM: " + wpm);
System.out.println("Freebie errors: " + freebieErrors);
System.out.println("Penalty: " + penalty);
System.out.println("WPM w/ penalty: " + (wpm - penalty));                         // yes, minus, because higher WPM is better
System.out.println("==================");

printResults(wpm, freebieErrors, penalty);

currTrialNum++;                                                                   // increment by one so this mesage only appears once when all trials are done
return;

}

else if (startTime == 0) // first trial starting now
{
System.out.println(“Trials beginning! Starting timer…”);
startTime = millis(); // start the timer!
}
else currTrialNum++; // increment trial number

lastTime = millis(); // record the time of when this trial ended
currentTyped = “”; // clear what is currently typed preparing for next trial
currentPhrase = phrases[currTrialNum]; // load the next phrase!
}

// Print results at the end of the study
void printResults(float wpm, float freebieErrors, float penalty)
{
background(0); // clears screen

textFont(createFont(“Arial”, 16)); // sets the font to Arial size 16
fill(255); //set text fill color to white
text(day() + “/” + month() + “/” + year() + " " + hour() + “:” + minute() + “:” + second(), 100, 20); // display time on screen

text(“Finished!”, width / 2, height / 2);
text("Raw WPM: " + wpm, width / 2, height / 2 + 20);
text("Freebie errors: " + freebieErrors, width / 2, height / 2 + 40);
text("Penalty: " + penalty, width / 2, height / 2 + 60);
text("WPM with penalty: " + (wpm - penalty), width / 2, height / 2 + 80);

saveFrame(“results-######.png”); // saves screenshot in current folder
}

// This computes the error between two strings (i.e., original phrase and user input)
int computeLevenshteinDistance(String phrase1, String phrase2)
{
int[][] distance = new int[phrase1.length() + 1][phrase2.length() + 1];

for (int i = 0; i <= phrase1.length(); i++) distance[i][0] = i;
for (int j = 1; j <= phrase2.length(); j++) distance[0][j] = j;

for (int i = 1; i <= phrase1.length(); i++)
for (int j = 1; j <= phrase2.length(); j++)
distance[i][j] = min(min(distance[i - 1][j] + 1, distance[i][j - 1] + 1), distance[i - 1][j - 1] + ((phrase1.charAt(i - 1) == phrase2.charAt(j - 1)) ? 0 : 1));

return distance[phrase1.length()][phrase2.length()];
}

below is the entire code

Please format your code as a courtesy to this community:
https://discourse.processing.org/faq#format-your-code

Try to cut and paste your code into Processing and you will understand why.