We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › repel a shape from the mouse position
Page Index Toggle Pages: 1
repel a shape from the mouse position (Read 3019 times)
repel a shape from the mouse position
Jan 4th, 2007, 6:40am
 
Hi all,

as a beginner, I am expanding the bounce example, and I simply just want the red ball to stay inside the screen while it is repelled by the green ball that follows the mouse. It seems like the repell code for the mouse overwrites the screen edge code ...

import processing.opengl.*;

float x1, y1, x2, y2;
float Esize1 = 20; float Esize2 = 30;
float xspeed, yspeed, xdirection, ydirection;


void setup() {
 size(300,300);
 background(0);
 noStroke();
 
 xspeed = 1.0;
 yspeed = 1.0;
 x2=280; y2=280;
 xdirection = 1;  // Left or Right
 ydirection = 1;  // Top to Bottom

}

void draw() {
 background(0);
 
 
 ellipseOne();
 ellipseTwo();


}

void ellipseOne() {
 // Update the position of the shape
 x1 = x1 + ( xspeed * xdirection );
 y1 = y1 + ( yspeed * ydirection );
 // Test to see if the shape exceeds the boundaries of the screen
 // If it does, reverse its direction by multiplying by -1
 if (x1 > width-Esize1 || x1 < 0) {
   xdirection *= -1;
 }
 if (y1 > height-Esize1 || y1 < 0) {
   ydirection *= -1;
 }
 
 if (x1 > x2-Esize2 || x1 < 0) {
   xdirection *= -1;
 }
 if (y1 > y2-Esize2 || y1 < 0) {
   ydirection *= -1;
 }
 
 fill(255, 0, 0);
 ellipse(x1+Esize1/2, y1+Esize1/2, Esize1, Esize1);
}


void ellipseTwo() {
 x2=mouseX;
 y2=mouseY;
 fill(100, 255, 54);
 ellipse(x2, y2, Esize2, Esize2);
}
Re: repel a shape from the mouse position
Reply #1 - Jan 6th, 2007, 8:15pm
 
Here's a basic example that handles both boundary and object-object collisions. Hope it helps.

ira

Code:

// basic collision example
float x1, y1, x2, y2;
float r1 = 20, r2 = 30;
float rSum = r1+r2;
float speed = 1.5, directionX = .4, directionY = .75, velocityX, velocityY;

void setup() {
size(300, 300);
noStroke();
smooth();
x1 = width/2;
y1 = height/2;
}

void draw() {
background(0);
// ellipse 1
velocityX = directionX*speed;
velocityY = directionY*speed;
x1+=velocityX;
y1+=velocityY;
ellipse(x1, y1, r1*2, r1*2);

//ellipse 2
x2 = mouseX;
y2 = mouseY;
ellipse(x2, y2, r2*2, r2*2);

// object collision
float d = dist(x1, y1, x2, y2);
if (d < rSum){
directionX = (x1-x2)/d;
directionY = (y1-y2)/d;
// keep ellipses from overlapping
x1 = x2+(rSum)*directionX;
y1 = y2+(rSum)*directionY;
}

// boundary collision
if (x1 > width-r1) {
// keep ellipse against boundary
x1 = width-r1;
directionX *= -1;
}
else if (x1 < r1) {
// keep ellipse against boundary
x1 = r1;
directionX *= -1;
}
else if (y1 > height-r1) {
// keep ellipse against boundary
y1 = height-r1;
directionY *= -1;
}
else if (y1 < r1) {
// keep ellipse against boundary
y1 = r1;
directionY *= -1;
}
}
Re: repel a shape from the mouse position
Reply #2 - Jan 15th, 2007, 5:51pm
 
In my initial (basic collision example) posting above, the ball reflection was not really accurate, as it followed the normal vector–not the true reflection vector. I thought it might be helpful for (someone) to see an example of a more accurate reflection, using the equation: R = 2N(N•L)-L, where R is the reflection vector, N is the normal vector (really perpendicular vector in 2D), and L is the incidence vector (incoming vector). The (N•L) part of the equation is a dot product (also referred to as scaler product) calculation, which is solved simply by (N.x*L.x + N.y*L.y). What's not evident in the equation is that the vectors N and L need to be normalized, which simply means dividing each of them by their own length. the length of a vector can be found by: sqrt(v.x*v.x + v.y*v.y). The example is procedural, and if I get a minute I'll post a more "classy" OOP one - or (someone) else can Wink
-ira

Code:

/* Example of reflection off a
non-orthogonal surface using
the equation: R = 2N(N•L)-L */

float x1, x2, y1, y2;
// arbitrary direction and speed values to begin
float directionX = .78, directionY = .83;
float speed = 2.5;
float velocityX, velocityY;
float r = 5, r2 = 50;
float startX = 100, startY = 100;

void setup(){
size(400, 400);
x1 = startX;
y1 = startY;
x2 = 200;
y2 = 200;
smooth();
}

void draw(){
fill(0, 10);
rect(0, 0, width, height);
stroke(255);

// calc ball's velocity as vector
velocityX = directionX*speed;
velocityY = directionY*speed;

// move ball
x1+=velocityX;
y1+=velocityY;

// create ball 1
ellipse(x1, y1, r*2, r*2);

// ball 2 - under mouse control
x2 = mouseX;
y2 = mouseY;
ellipse(x2, y2, r2*2, r2*2);

// collision between balls
float ballDist = dist(x1, y1, x2, y2);
if (ballDist < r+r2){

/* reflection calculations below
based on the equation R = 2N(N•L)-L */

/********** incidence vector **********/
float incidenceVectorDist = dist(startX, startY, x1, y1);
// calculate vector
float incidenceVectorX = (startX-x1);
float incidenceVectorY = (startY-y1);
// normalize vector
incidenceVectorX /= incidenceVectorDist;
incidenceVectorY /= incidenceVectorDist;

/********** normal vector **********/
// (in 2D really a perpendicular)
float normalVectorX = (x1-x2);
float normalVectorY = (y1-y2);
// normalize vector
normalVectorX /= ballDist;
normalVectorY /= ballDist;

/* draw normal just to illustrate how the
angle of incidence = angle of reflection */
stroke(255, 128, 0);
line(x1, y1, x2, y2);

// dot product calcuation part of the equation (N•L)
float dot = incidenceVectorX*normalVectorX + incidenceVectorY*normalVectorY;

// finish equation calcs
float reflectionVectorX = normalVectorX*2*dot - incidenceVectorX;
float reflectionVectorY = normalVectorY*2*dot - incidenceVectorY;

// reflection assignment
directionX = reflectionVectorX;
directionY = reflectionVectorY;

// keep balls from overlapping
x1 = x2+(r+r2)*normalVectorX;
y1 = y2+(r+r2)*normalVectorY;

/* resets incidence vector's starting point
(sort of a necessary hack to avoid more
complicated collision detection */
resetIncidenceVector();
}

// detect boundary collision
if (x1>width-r){
x1=width-r;
directionX*=-1;
resetIncidenceVector();
}

if (x1<r){
x1=r;
directionX*=-1;
resetIncidenceVector();
}

if (y1>height-r){
y1=height-r;
directionY*=-1;
resetIncidenceVector();
}

if (y1<r){
y1=r;
directionY*=-1;
resetIncidenceVector();
}
}

/* resets ball's start position each collision-
used in incidence vector calculation */
void resetIncidenceVector(){
startX = x1;
startY = y1;
}

Page Index Toggle Pages: 1