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.
Pages: 1 2 
nested matrices (Read 1855 times)
nested matrices
Mar 6th, 2010, 12:01pm
 
Hello,
I'm working on a simple program where at the bottom there is a target that you want to hit with a swinging pendulum. The end of the pendulum has an ellipse at the end as does the target at the bottom, so the goal is to make the two circles touch. I have a boolean to detect the collision of the two circles, but the issue that I'm having now is that because of multiple matrices, the coordinates of the two circles aren't correct. I'm pretty sure that is what the problem is, but I think I'm just looking over where the mistake is. Thanks for any help!
Code:


int yval = 200;
int sx = 0;
int tx = 50;
int ty = 435;
int erads = 10;
int bulb = 50;

float cord = (yval * .5); //line with fixed point @ top of screen

float theta = 0.0;
float psi = 0.0;

void setup() {
 size(320, 480);
 smooth();
 
 ellipseMode(RADIUS);
}

void draw() {
 
 background(225);
 //println(frameRate);
 println(sx);

 translate(width/2, 0);

 float angle = (2 + sin(theta)) * PI * .25;

 float x = cord * cos(angle);
 float y = cord * sin(angle);
 
 float sangle = (cos(psi)) * HALF_PI;
 
 //float x2 = (cord) * cos(sangle);
 //float y2 = (cord) * sin(sangle);
 
 theta += 0.05;
 psi += 0.035;
 
 // Draw the ellipse at x,y
 fill(0);
 stroke(0);
 pushMatrix();
 rotate(angle);
 strokeWeight(2);
 line(0, 0, 100, 0);// top cord
 
 pushMatrix();
 
 translate(100, 0);
 strokeWeight(1);
 rotate(sangle);  //change angle to make it move differently(independently)
  if ((mousePressed == true)&&(mouseButton == LEFT)){
    sx += 1;
  }else if ((mousePressed == true)&&(mouseButton == RIGHT)){
    sx -= 1;
  }
 line(0, 0, bulb, sx);   //second/smaller arm  
  if (sx == -1){
    sx *= -1;
  }
 ellipse(bulb, sx, erads, erads);
 popMatrix();
 
 popMatrix();
 
 
 //bottom target
 //pushMatrix();
 strokeWeight(2);
 line(tx, ty, tx, height); //line(x, y, a, b); y = length
                            //x&a = end of line
                            //if y = 480; it's off screen
 //popMatrix();

  if (circleCircleIntersect(bulb, sx,
      erads, tx, ty, erads) == true) {
   fill(14, 39, 173);
   //delay(2000);  
   noLoop();
 } else {
   fill(0);  
 }
 ellipse(bulb, sx, erads, erads);
 ellipse(tx, ty, erads, erads);
 
 
}
 
 
 boolean circleCircleIntersect(float cx1, float cy1, float cr1, float cx2, float cy2, float cr2) {
   if (dist(cx1, cy1, cx2, cy2) < cr1 + cr2) {
     return true;
   } else {
     return false;
   }
 }

Re: nested matrices
Reply #1 - Mar 6th, 2010, 12:51pm
 
Can you put some more comments in.... like labelling what the variables are: sx, tx, ty, etc. Then I will have a look at it and see if I can see anything.
Re: nested matrices
Reply #2 - Mar 6th, 2010, 3:13pm
 
Sure, sorry, here is another version with some comments:

Code:


int yval = 200;
int sx = 0; //incrementing variable for length of second 'arm' (extends y length)
int tx = 50; //coordinate for line @ bottom of screen
int ty = 435; // coordinate for line @ bottom of screen
int erads = 10; //radii of circles
int bulb = 50; //end of second 'arm' with circle swinging on it

float cord = (yval * .5); //line with fixed point @ top of screen

float theta = 0.0; //angular motion
float psi = 0.0; //angular motion

void setup() {
 size(320, 480);
 smooth();
 
 ellipseMode(RADIUS);
}

void draw() {
 
 background(225);
 //println(frameRate);
 println(sx);

 translate(width/2, 0);

 float angle = (2 + sin(theta)) * PI * .25;

 float x = cord * cos(angle);
 float y = cord * sin(angle);
 
 float sangle = (cos(psi)) * HALF_PI;
 
 //float x2 = (cord) * cos(sangle);
 //float y2 = (cord) * sin(sangle);
 
 theta += 0.05;
 psi += 0.035;
 
 // Draw the ellipse at x,y
 fill(0);
 stroke(0);
 pushMatrix();
 rotate(angle);
 strokeWeight(2);
 line(0, 0, 100, 0);// top cord
 
 pushMatrix();
 
 translate(100, 0);
 strokeWeight(1);
 rotate(sangle);  //change angle to make it move differently(independently)
  if ((mousePressed == true)&&(mouseButton == LEFT)){
    sx += 1;
  }else if ((mousePressed == true)&&(mouseButton == RIGHT)){
    sx -= 1;
  }
 line(0, 0, bulb, sx);   //second/smaller arm  
  if (sx == -1){
    sx *= -1;
  }
 ellipse(bulb, sx, erads, erads);
 popMatrix();
 
 popMatrix();
 
 
 //bottom target
 //pushMatrix();
 strokeWeight(2);
 line(tx, ty, tx, height); //line(x, y, a, b); y = length
                            //x&a = end of line
                            //if y = 480; it's off screen
 //popMatrix();

  if (circleCircleIntersect(bulb, sx, //checking if the swinging circle touches the target @ bottom
      erads, tx, ty, erads) == true) {
   fill(14, 39, 173);
   //delay(2000);  
   noLoop();
 } else {
   fill(0);  
 }
 ellipse(bulb, sx, erads, erads);
 ellipse(tx, ty, erads, erads);
 
 
}
 
 
 boolean circleCircleIntersect(float cx1, float cy1, float cr1, float cx2, float cy2, float cr2) {
   if (dist(cx1, cy1, cx2, cy2) < cr1 + cr2) {
     return true;
   } else {
     return false;
   }
 }
Re: nested matrices
Reply #3 - Mar 6th, 2010, 11:18pm
 
Have a look at the reference for screenX() and screenY(). After a series of transformations (translate, scale, rotate) you can use screenX() and screenY() to get screen (pixel) coordinates, save these in some variable(s) and compare them to other screen coordinates later.

-spxl
Re: nested matrices
Reply #4 - Mar 7th, 2010, 2:54pm
 
ah okay, i didn't actually know about those functions. so i can just call those X and Y coordinates, then draw the two ellipses after the if statement to check the boolean?
Re: nested matrices
Reply #5 - Mar 8th, 2010, 1:54am
 
Generic note, as I haven't analyzed the code:
Are you sure you want to nest the matrices?
When you push the second matrix, the current translate/rotate transformations are still in effect, so still apply to next drawings and cumulate with subsequent transformations. Since you pop out the two matrices at once, I am not sure if that's your goal.
Perhaps you want to wrap one set of transforms in a pushMatrix/popMatrix pair, then do the same in the second set of transforms, instead. Thus the second transforms start on original state.
Re: nested matrices
Reply #6 - Mar 8th, 2010, 6:48am
 
rpw029 wrote on Mar 7th, 2010, 2:54pm:
so i can just call those X and Y coordinates, then draw the two ellipses after the if statement to check the boolean

You have probably answered your own question. I haven't examined your code. I just gave you a way to find consistent coordinates to relate positions arrived at from different transformations.. what you do with that information is up to you!  Smiley
Re: nested matrices
Reply #7 - Mar 9th, 2010, 11:40am
 
hi,
i had another question; i got it so that when the two ellipses touch they change color and the screen pauses using delay(); but is there a way to go about making it so that once they touch the pendulum would continue on it's path with the two circles stuck to each other?
Re: nested matrices
Reply #8 - Mar 10th, 2010, 8:22am
 
You can draw the circles wherever you like. If you want one circle to "stick" to another, you only need to work out what its (possibly relative) position is and draw it there. If it started as "not stuck" and is later "stuck", you might like to use a boolean variable to remember what state you are in; put that variable at the top of your program (so that it is remembered from frame to frame).

eg (pseuocode): Code:
boolean isStuck = false;
...
draw() {
...
 if (collision) {
   isStuck = true;
   do some other stuff;
 }
}
...
if (isStuck) {
 draw circle in special place
} else {
 draw circle in usual place
}


-spxl
Re: nested matrices
Reply #9 - Mar 10th, 2010, 3:32pm
 
awesome, thanks, it works perfectly, just working out a few other errors, but so far so god! thanks a lot guys =]
Re: nested matrices
Reply #10 - Mar 14th, 2010, 5:39pm
 
hi, i'm continuing this game, and i'm adding in some stages to progress through. Right now the error that I keep running into but don't really see is a stack overflow, or pushMatrix comes up more than 32 times? i'm trying to make it so that after you get to stage two.. which works fine for me.. it draws out the game playing as though you just ran the program again. I have the top cord and bottom cords as voids, just for ease, and the target at the bottom is as well. When I add in the target once I go to the second stage, it is drawn just fine, yet adding in the oscillating cords, is what is causing the error. Here is the code so far:

Code:

int yval = 200;
int sx = 50; //end of second 'arm' with circle swinging on it
int sy = 0; //incrementing variable for length of second 'arm' (extends y length)
int tx = 50; //coordinate for line @ bottom of screen
int ty = 435; // coordinate for line @ bottom of screen
int erads = 15; //radii of circles
int timer = 255;
int stagetime = 0;

PFont font;

boolean isStuck = false;

float cord = (yval * .5); //line with fixed point @ top of screen
float theta = 0.0; //angular motion
float psi = 0.0; //angular motion
float scalar = 1.0;

void setup() {
 size(320, 480);
 smooth();

 font = loadFont("Helvetica-24.vlw");

 ellipseMode(RADIUS);
}

void draw() {

 textFont(font);
 background(225);
 //println(frameRate);
 //println(sy);

 translate(width/2, 0);

 float angle = (2 + sin(theta)) * QUARTER_PI;

//  float x = cord * cos(angle);
//  float y = cord * sin(angle);

 float sangle = (2 + scalar * cos(psi)) * HALF_PI;

 float x2 = (cord) * cos(sangle);
 float y2 = (cord) * sin(sangle);

 theta += 0.06;
 psi += 0.02;

 //top line
 topCord();
 
 //bottom arm
 bottomCord();



 float theX = screenX(x2, y2);  //grab coords for 'wrecking-ball'
 float theY = screenY(x2, y2);

 //println(theX + " " + theY);

 popMatrix();

 popMatrix();


 //bottom target
 target();


 //balls after collision
 if (isStuck == true){
   noStroke();
   fill(39, 148, 201);
   ellipse(theX-width/2, theY, erads, erads);
   ellipse(theX-width/2 + 12, theY + 12, erads, erads);
   
   scalar -= 0.005; //change decrement
   
   if (scalar <= 0){
     scalar = 0;
   }
   
 }else{
   ellipse(theX-width/2, theY, erads, erads);
   ellipse(tx, ty, erads, erads);
 }
 
 if(scalar == 0){
   //delay(500);
   timer -= 10;
   background(timer);
   
   if(timer <= 15){
     timer = 20;
   }    
 }
 
 if((scalar == 0)&&(timer == 20)){
   stage2();
 }

 if (circleCircleIntersect(tx, ty,   //checking if the swinging circle touches the target @ bottom
 erads, theX-width/2, theY, erads) == true){
   
   isStuck = true;
   //stage2();
   

 }
 else {
   fill(0);
 }
 
 
}


boolean circleCircleIntersect(float cx1, float cy1, float cr1, float cx2, float cy2, float cr2) {
 if (dist(cx1, cy1, cx2, cy2) < (cr1 + cr2)) {
   return true;
 }
 else {
   return false;
 }
}

void bottomCord(){
 
 float sangle = (2 + scalar * cos(psi)) * HALF_PI;
 float x2 = (cord) * cos(sangle);
 float y2 = (cord) * sin(sangle);
 
 pushMatrix();
 translate(100, 0);
 strokeWeight(1);
 rotate(sangle*scalar + (1-scalar) * 0.65 * PI);  //change angle to make it move differently(independently)
 
 if ((mousePressed == true)&&(mouseButton == LEFT)){
   cord += 2;
 }
 else if (!(mousePressed == true)&&(cord >= 100)){
   cord -= 2;
 }
 line(0, 0, x2, y2);   //second/smaller arm  
}


void topCord(){
 
 float angle = (2 + sin(theta)) * QUARTER_PI;
 fill(0);
 stroke(0);
 pushMatrix();
 rotate(angle*scalar + (1-scalar) * 0.5 * PI);
 strokeWeight(2);
 line(0, 0, 100, 0); // top cord
}


void target(){
 //bottom target
 strokeWeight(2);
 stroke(0);
 line(tx, ty, tx, height); //line(x, y, a, b); y = length
 //x&a = end of line
 //if y = 480; it's off screen
 println(timer);
 
}


void stage2(){

     stagetime++;
     fill(255);
     textSize(24);
     text("Stage 2!", -50, height/2);
     
     if (stagetime >= 100){
       background(225);
       erads = 10;
       //change other aspects of gameplay for second stage here
       target();
       //topCord();
       //bottomCord();
     }
     
     
     
}


That is what is being run so far, and i see that the two pop matrices are outside of the void, but is there something I can do to leave it like that and not have an error when I just want to redraw everything as it was in the first stage? Thanks for any help!
Re: nested matrices
Reply #11 - Mar 15th, 2010, 9:45am
 
It is not a good idea to have 'unmatched' pushMatrix() calls (that is, without corresponding popMatrix() calls) in topCord() and bottomCord().

Every time you call one of these methods, you need to pop the matrix pushed by them.

If the reason you don't pop the matrix inside those methods is so you can set "theX" and "theY" in your main draw() method, perhaps you should instead set those variables inside the method you are calling. I've noticed you have the same calculations code repeated in draw() as in the other methods - ideally you only want to do such things in one place.

Might I suggest you arrange your code so that the wrecking arm is drawn by calling a single method from draw() instead of two, where that method does both parts.

Something like (pseudocode, ignoring other functionality):

Code:
// Sketch-level variables to store screen coordinates
// of the wrecking ball. I suggest renaming to ballX, ballY or
// similar to indicate what they are for
float theX, theY;

draw() {
 // Don't need angle, sangle, x2, y2
 // Do want to have cord, so cord control only happens once
 // Insert mouse-control for cord here!
 drawWreckingArms();
}

void drawWreckingArms()
{
 pushMatrix();
 // calculations for upper arm
 // drawing upper arm

 pushMatrix();
 // calculations for lower arm
 // drawing lower arm

 // Store screen coordinates for wrecking ball
 theX = screenX(x2, y2);
 theY = screenY(x2, y2);

 popMatrix();
 popMatrix();
}


It seems to me that you are struggling with ideas about how to structure your program. I think you would benefit from taking a step back from your game mission for the moment and taking a look at some (more) tutorials.

Have a look at Objects in the Learning section of this website. Objects give you a place to store your variables (in a hierarchical way, such as the wrecking ball having X and Y coordinates instead of you using unassociated "theX" and "theY" variables in your draw() method), and a way to group behaviours for the "things" you have in your program.

-spxl
Re: nested matrices
Reply #12 - Mar 15th, 2010, 10:01am
 
Ah, thanks, subpix..I didn't notice that I had ungrouped matrices, but after I went back to look over it I noticed that the popMatrices were outside of the void for the arm. I think I'm going to go with making the entire wrecking ball one function like you said, and take it from there so as to make producing stages more fluid.

Yeah, that has definitely been the main issue with this code.. I haven't been very consistent or efficient for that matter with its organization. But thanks, I am going over more tutorials, or just reading up on topics anyway. I started on Java, and Processing is a bit different..I am kinda debating whether or not to just load this library into Eclipse instead of Processing, as that is more what I'm accustomed to.

Thanks for the help though, I really appreciate it =]
Re: nested matrices
Reply #13 - Mar 15th, 2010, 11:35am
 
Processing _is_ Java. Your sketch is a class. The "color" type in Processing is translated to "int". Virtually everything else is the same (with some exceptions on later features of Java such as enums).

What you're referring to is the functionality of the Processing libraries. They are all just Java methods and classes and so on.

-spxl
Re: nested matrices
Reply #14 - Mar 15th, 2010, 12:16pm
 
Well what's different between the two, is the syntax that they use respectively also. Am I able to use the same syntax that I use in Java, in Processing? Such as:
Code:

g.setColor(Color.black)
fillRect(0, 0, x, y);


x and y just random variables. I've never actually tried implementing it straight into the Processing IDE, but that's an example of Java, yet in Processing you're basically using a simplified version that has its foundation over Java, right? So you can still call things like 'private static void' and all, but the Processing library is more or less designed to make the user's interaction less tedious. For example, the code above in Processing would just be:
Code:

background(0);

If x and y were the screen dimension variables.
Pages: 1 2