import processing.opengl.*; /* //import com.cycling74.io.*; //import com.cycling74.net.*; //import com.cycling74.util.*; //import maxlink.*; //import com.cycling74.msp.*; //import com.cycling74.max.*; //import com.cycling74.mxjedit.*; */ //import java.util.LinkedList; //Color Conventions // -- endpoints - red // -- velocity vectors - blue // -- Normals - green // -- balls - white (nostroke) // -- physical lines - yellow // -- paddles - purple public class MyDemo18 extends PApplet { //Max input //MaxLink link = new MaxLink(this,"MyDemo4"); public int RED_X,RED_Y,GREEN_X,GREEN_Y,YELLOW_X,YELLOW_Y; //LineSeg2D ls; int fps = 30; //this should be adequate, I think float LogicFrameLength = 1.0f/((float)fps); Circ2D c1; int BballNum = 1; Ball Bball; float BballA; // Angle of Blue Ball Rotation float BballRotRate = .009; // Rate of Blue Ball Rotation Ball ball,ball2; Paddle padR1,padR2,padG1,padG2,padY1,padY2; Paddle PadArray[]; Target tar1,tar2,tar3,tar4,tar5,tar6; Vector2D sizeVec; //Holds the size our Window Circ2D cb; //Outer Circle Boundary RotaryBarrier rb; float rbTheta; BlueBallRing blueRing; //the set of outer balls //Holds instances of stuff for us LinkedList circList; LinkedList lineList; LinkedList BballList; LinkedList ballList; LinkedList padList; LinkedList tarList; Vector2D lastMouseClick; //contains the coordinates of the previous mouse click boolean noMouseClick; //just used as a simple state variable boolean drawdebug; //when this is true, we draw debug information void setup() { //X Y variables for Paddles from color tracking input from Max /* link.declareInlet("RED_X"); link.declareInlet("RED_Y"); link.declareInlet("GREEN_X"); link.declareInlet("GREEN_Y"); link.declareInlet("YELLOW_X"); link.declareInlet("YELLOW_Y"); */ //My Java monkeying around drawdebug = false; noMouseClick = true; lastMouseClick = new Vector2D(); c1 = new Circ2D(); c1.Pos = new Vector2D(300,300); c1.r = 20; circList = new LinkedList(); lineList = new LinkedList(); BballList = new LinkedList(); ballList = new LinkedList(); padList = new LinkedList(); tarList = new LinkedList(); blueRing = new BlueBallRing(); // Paddle padR1,padR2,padG1,padG2,padY1,padY2; PadArray = new Paddle[6]; PadArray[0] = padR1; PadArray[1] = padR2; PadArray[2] = padG1; PadArray[3] = padG2; PadArray[4] = padY1; PadArray[5] = padY2; //White Balls ball = new Ball(); ball.r = 5; ball.Pos.Set(600,600); ball.Vel.Set(-70,-70); ball.Elasticity = 0.9f; ball2 = new Ball(); ball2.r = 5; ball2.Pos.Set(200,200); ball2.Vel.Set(60,60); ball2.Elasticity = 0.99f; ballList.add(ball); ballList.add(ball2); rbTheta = 0; rb = new RotaryBarrier(); rb.SetNumSides(3); rb.SetPosition(300, 300); rb.SetOrientation(rbTheta); padR1 = new Paddle(); padR2 = new Paddle(); padG1 = new Paddle(); padG2 = new Paddle(); padY1 = new Paddle(); padY2 = new Paddle(); padR1.rVal = 255; padR1.gVal = 0; padR1.bVal = 0; padR1.rValOrig = 255; padR1.gValOrig = 0; padR1.bValOrig = 0; padR2.rVal = 255; padR2.gVal = 0; padR2.bVal = 0; padR2.rValOrig = 255; padR2.gValOrig = 0; padR2.bValOrig = 0; padG1.rVal = 0; padG1.gVal = 255; padG1.bVal = 0; padG1.rValOrig = 0; padG1.gValOrig = 255; padG1.bValOrig = 0; padG2.rVal = 0; padG2.gVal = 255; padG2.bVal = 0; padG2.rValOrig = 0; padG2.gValOrig = 255; padG2.bValOrig = 0; padY1.rVal = 255; padY1.gVal = 255; padY1.bVal = 0; padY1.rValOrig = 255; padY1.gValOrig = 255; padY1.bValOrig = 0; padY2.rVal = 255; padY2.gVal = 255; padY2.bVal = 0; padY2.rValOrig = 255; padY2.gValOrig = 255; padY2.bValOrig = 0; padList.add(padR1); padList.add(padR2); padList.add(padG1); padList.add(padG2); padList.add(padY1); padList.add(padY2); InstantiateTargets(); /* tar1 = new Target(); tar2 = new Target(); tar3 = new Target(); tar4 = new Target(); tar5 = new Target(); tar6 = new Target(); tarList.add(tar1); tar1.r = 10; tarList.add(tar2); tar2.r = 20; tarList.add(tar3); tar3.r = 30; tarList.add(tar4); tar4.r = 40; tarList.add(tar5); tar5.r = 50; tarList.add(tar6); tar6.r = 60; tar6.SetPosition(width/2, height/2, LogicFrameLength); tar5.SetPosition(width/2, height/2, LogicFrameLength); tar4.SetPosition(width/2, height/2, LogicFrameLength); tar3.SetPosition(width/2, height/2, LogicFrameLength); tar2.SetPosition(width/2, height/2, LogicFrameLength); tar1.SetPosition(width/2, height/2, LogicFrameLength); */ sizeVec = new Vector2D(600,600); cb = new Circ2D(); cb.Pos = new Vector2D(width/2,height/2); cb.r = 290; //Init Processing environment stuff ellipseMode(CENTER); size(600,600,OPENGL); //for some reason, when I put these last, they behave better framerate(fps); } void draw() { //clear the screen background(0); // mouse control //pad.SetPosition(mouseX, mouseY, LogicFrameLength); // LED control padR1.SetPosition(mouseX, mouseY, LogicFrameLength); padR2.SetPosition(200, 450, LogicFrameLength); padG1.SetPosition(150, 250, LogicFrameLength); padG2.SetPosition(250, 150, LogicFrameLength); padY1.SetPosition(400, 150, LogicFrameLength); padY2.SetPosition(450, 250, LogicFrameLength); //Update Simulation UpdateBallPhysics(); TestBallsAgainstLineSegs(); TestBallsAgainstPaddles(); TestBallsAgainstTargets(); TestBallsAgainstBlueRing(); TestBallsAgainstCircBound(); TestPaddle2Paddles(); //Total hack to see if all the targets have been hit, but it should work if (tar1.killMe) { tarList.clear(); BballList.clear(); InstantiateTargets(); } CleanUpDeadObjects(); //If anything has been destroyed, eliminate it before we render //update rbTheta rbTheta += LogicFrameLength * 0.5; rb.SetOrientation(rbTheta); blueRing.SetOrientation(-rbTheta*0.3); //Render RenderScene(); //Draw Circular Outer Boundary DrawCircBound(); DrawBlueBallRing(); //Draw the Paddle DrawPaddle(padR1); DrawPaddle(padR2); DrawPaddle(padG1); DrawPaddle(padG2); DrawPaddle(padY1); DrawPaddle(padY2); // Draw Targets /* DrawTarget(tar6,100,100,100); DrawTarget(tar5,155,155,155); DrawTarget(tar4,175,175,175); DrawTarget(tar3,200,200,200); DrawTarget(tar2,225,225,225); DrawTarget(tar1,255,255,255); */ //Quick Test of the Rotary Barrier rendering for (int i=0; i= sizeVec.y) { bi.remove(); //get rid of the ball } } //Blue balls ListIterator bbi = BballList.listIterator(); while (bi.hasNext()) { Ball b = (Ball)bbi.next(); //current Circ if (b.killMe || b.Pos.y >= sizeVec.y || b.Pos.y < 0.0f || b.Pos.x < 0.0f || b.Pos.x >= sizeVec.x) { bbi.remove(); //get rid of the ball } } ListIterator li = lineList.listIterator(); while (li.hasNext()) { LineSeg2D l = (LineSeg2D)li.next(); //current Circ if (l.killMe) { li.remove(); //get rid of the ball } } ListIterator ti = tarList.listIterator(); while (ti.hasNext()) { Target t = (Target)ti.next(); //current Circ if (t.killMe) { //println("kill target"); ti.remove(); //get rid of the ball } } } //Pos = Pos + Vel*Delta_t on all the balls public void UpdateBallPhysics() { ListIterator bi = ballList.listIterator(); while (bi.hasNext()) { Ball b = (Ball)bi.next(); //current Ball //b.AddForce(new Vector2D(0, 200)); //Add Gravity force //Vector2D gVec = new Vector2D(); //gVec.Add(cb.Pos,b.Pos); ///gVec.Normalize(); ///gVec.Times(500.0); //b.AddForce(gVec); //Add Gravity force //Apply sum forces to the ball - assumes all balls have mass 1.0 b.Vel.PlusEquals(b.Force.Times(LogicFrameLength)); b.Force.Set(0,0); b.Pos.PlusEquals(b.Vel.Times(LogicFrameLength)); b.LimitMaxVel(); } ListIterator Bbi = BballList.listIterator(); while (Bbi.hasNext()) { Ball b = (Ball)Bbi.next(); //current Ball //b.AddForce(new Vector2D(0, 200)); //Add Gravity force //Vector2D gVec = new Vector2D(); //gVec.Add(cb.Pos,b.Pos); ///gVec.Normalize(); ///gVec.Times(500.0); //b.AddForce(gVec); //Add Gravity force //Apply sum forces to the ball - assumes all balls have mass 1.0 b.Vel.PlusEquals(b.Force.Times(LogicFrameLength)); b.Force.Set(0,0); b.Pos.PlusEquals(b.Vel.Times(LogicFrameLength)); b.LimitMaxVel(); } } //Will cause the White balls to crash through and destroy any blue balls they come into contact with public void TestBallsAgainstBlueRing() { ListIterator bi = ballList.listIterator(); while (bi.hasNext()) { Ball b = (Ball)bi.next(); //current Circ //just a direct test against the ball from the slice int Slice = blueRing.GetSliceNum(b.Pos); if (blueRing.ActiveFlags[Slice]) { float sqrDist = (b.Pos.x-blueRing.points[Slice].x)*(b.Pos.x-blueRing.points[Slice].x) + (b.Pos.y-blueRing.points[Slice].y)*(b.Pos.y-blueRing.points[Slice].y); float radSqr = (b.r+blueRing.ball_radius)*(b.r+blueRing.ball_radius); if (sqrDist < radSqr) { blueRing.DeactivateBall(Slice); } } } } //Iterates through all balls and line segs and performs tests public void TestBallsAgainstLineSegs() { ListIterator bi = ballList.listIterator(); while (bi.hasNext()) { Ball b = (Ball)bi.next(); //current Circ ListIterator li = lineList.listIterator(); while (li.hasNext()) { LineSeg2D l = (LineSeg2D)li.next(); if (TestBallAgainstLineSeg(b,l)) { l.killMe = true; } else if (TestBallAgainstLineSeg(b,l.retReverse())) { l.killMe = true; } } //Test balls against rotary barrier for (int i=0; i 0 && tstrike < LogicFrameLength) { //Figure out where on the infinite line of the segment we would actually hit Vector2D colPoint = b.Pos.Plus(b.Vel.Times(tstrike)); Vector2D VecToColPoint = colPoint.Minus(ls.p1); //println("PING 2\n"); float distToAnchor = VecToColPoint.Dot(ls.RayVector()); if (distToAnchor < ls.LengthSquared() && distToAnchor > -.0001) { b.CollideWithLineSeg(ls); return true; } } } return false; } //This function will need to be edited later, when the details of storing all the // paddles are known public void TestBallsAgainstCircBound() { ListIterator bi = ballList.listIterator(); //ListIterator pi = padList.listIterator(); while (bi.hasNext()) { Ball b = (Ball)bi.next(); //current Circ //Paddle cb = circBound; TestBallAgainstCircBound(b, cb); //Test against the one known paddle } /* ListIterator Bbi = BballList.listIterator(); //ListIterator pi = padList.listIterator(); while (Bbi.hasNext()) { Ball b = (Ball)Bbi.next(); //current Circ //Paddle cb = circBound; TestBallAgainstCircBound(b, cb); //Test against the one known paddle } */ } public void TestBallAgainstCircBound(Ball b, Circ2D cb) { Vector2D CBPos = cb.Pos; //Vector2D CBVel = cb.GetVelocity(); Vector2D CB2Ball = b.Pos.Minus(CBPos); //Dumb collision detection to start with if (CB2Ball.Dot(CB2Ball) > ((b.r+cb.r)*(b.r+cb.r))) { //Ok, we have a collision! Now we need to figure out at which point the collision occurred CB2Ball.Normalize(); Vector2D ColPoint = CBPos.Plus(CB2Ball.Times(cb.r)); //Now that we have the point of collision, we need to get a normal to the circle at the point - //However, that normal is simply the vector from the center of the circle to that point, which //we already calculated up above - It's Pad2Ball, which we also conveniently have already normalized. //ok, let's also prevent ball penetration into the paddle by moving the ball to the point of collision b.Pos.Set(ColPoint.Plus(CB2Ball.Times(b.r))); //Vector2D NewBallLoc = Vector2D.add(Point_Col, Vector2D.mult(Targ2Ball, radius)); //loc = NewBallLoc; //Now, we need to reflect the ball's velocity across that normal. b.Vel.Set(Vector2D.Reflect(b.Vel.Negative(), CB2Ball)); Vector2D circBoundDamp = b.Vel; circBoundDamp.TimesEquals(.7); b.SubForce(circBoundDamp); b.LimitMinVel(); } } //This function will need to be edited later, when the details of storing all the // paddles are known public void TestBallsAgainstPaddles() { ListIterator bi = ballList.listIterator(); while (bi.hasNext()) { Ball b = (Ball)bi.next(); //current Circ ListIterator pi = padList.listIterator(); while (pi.hasNext()) { Paddle p = (Paddle)pi.next(); TestBallAgainstPaddle(b, p); //Test against the one known paddle } } } public void TestBallAgainstPaddle(Ball b, Paddle p) { Vector2D PPos = p.GetPosition(); Vector2D PVel = p.GetVelocity(); Vector2D Targ2Ball = b.Pos.Minus(PPos); //Dumb collision detection to start with if (Targ2Ball.Dot(Targ2Ball) < ((b.r+p.r)*(b.r+p.r))) { //Ok, we have a collision! /* - Check the ID of the Paddle - Check array values in Ball to see if the ID is true or not - If it's false, set to true, else nothing - Add values in array, if they are >= 3, kill ball. */ //Now we need to figure out at which point the collision occurred Targ2Ball.Normalize(); Vector2D ColPoint = PPos.Plus(Targ2Ball.Times(p.r)); //Now that we have the point of collision, we need to get a normal to the circle at the point - //However, that normal is simply the vector from the center of the circle to that point, which //we already calculated up above - It's Pad2Ball, which we also conveniently have already normalized. //ok, let's also prevent ball penetration into the paddle by moving the ball to the point of collision b.Pos.Set(ColPoint.Plus(Targ2Ball.Times(b.r))); //Vector2D NewBallLoc = Vector2D.add(Point_Col, Vector2D.mult(Targ2Ball, radius)); //loc = NewBallLoc; //Now, we need to reflect the ball's velocity across that normal. b.Vel.Set(Vector2D.Reflect(b.Vel.Negative(), Targ2Ball)); //New stuff - trying to add more impact stuff to ball, so we can strike the ball with the // the paddle, and thereby cause the ball to accelerate float RelPadVel = (PVel.Dot(Targ2Ball)); if (RelPadVel > 80) { b.AddForce(Targ2Ball.Times(RelPadVel*20)); //println("Ping"); } // println(p.ID); //t.collision(); //Add Paddle vector to ball vector //b.add_force(t.vel); //*/ } } //This function will need to be edited later, when the details of storing all the // Targets are known public void TestBallsAgainstTargets() { ListIterator Bbi = BballList.listIterator(); while (Bbi.hasNext()) { Ball b = (Ball)Bbi.next(); //current Circ ListIterator ti = tarList.listIterator(); while (ti.hasNext()) { Target t = (Target)ti.next(); if (TestBallAgainstTarget(b,t)) { //println("t.killMe = true"); t.killMe = true; //hack to get rid of the resetting bug if (t == tar1) { b.killMe = true; } } //TestBallAgainstTarget(b, t); //Test against the one known Target } } } public boolean TestBallAgainstTarget(Ball b, Target t) { Vector2D tPos = t.GetPosition(); Vector2D tVel = t.GetVelocity(); Vector2D Targ2Ball = b.Pos.Minus(tPos); //Dumb collision detection to start with if (Targ2Ball.Dot(Targ2Ball) < ((b.r+t.r)*(b.r+t.r))) { //Ok, we have a collision! /* - Check the ID of the Target - Check array values in Ball to see if the ID is true or not - If it's false, set to true, else nothing - Add values in array, if they are >= 3, kill ball. */ //Now we need to figure out at which point the collision occurred Targ2Ball.Normalize(); Vector2D ColPoint = tPos.Plus(Targ2Ball.Times(t.r)); //Now that we have the point of collision, we need to get a normal to the circle at the point - //However, that normal is simply the vector from the center of the circle to that point, which //we already calculated up above - It's Pad2Ball, which we also conveniently have already normalized. //ok, let's also prevent ball penetration into the Target by moving the ball to the point of collision b.Pos.Set(ColPoint.Plus(Targ2Ball.Times(b.r))); //Vector2D NewBallLoc = Vector2D.add(Point_Col, Vector2D.mult(Targ2Ball, radius)); //loc = NewBallLoc; //Now, we need to reflect the ball's velocity across that normal. b.Vel.Set(Vector2D.Reflect(b.Vel.Negative(), Targ2Ball)); //New stuff - trying to add more impact stuff to ball, so we can strike the ball with the // the Target, and thereby cause the ball to accelerate float RelTarVel = (tVel.Dot(Targ2Ball)); //println("return true"); return true; } return false; } public boolean TestBetweenPaddles(Paddle p1, Paddle p2) { float dist_Between_paddles = (p1.r+p2.r); float TestdistSqr = dist_Between_paddles * dist_Between_paddles; float dx,dy; dx = p1.GetPosition().x - p2.GetPosition().x; dy = p1.GetPosition().y - p2.GetPosition().y; float curDist = dx*dx+dy*dy; if (curDist < TestdistSqr) { p1.blueSwitch = true; p2.blueSwitch = true; } if (p1.blueSwitch && !p1.bsPrevFrame || p2.blueSwitch && !p2.bsPrevFrame) { if (!p1.FiredThisFrame && !p2.FiredThisFrame) { p1.FiredThisFrame = true; p2.FiredThisFrame = true; FireBlueBall(p1,p2); return true; } } return false; } public void FireBlueBall(Paddle p1, Paddle p2) { //Get the closest point to the midpoint of the collision Vector2D contact = new Vector2D((p1.GetPosition().x + p2.GetPosition().x)*0.5f, (p1.GetPosition().y + p2.GetPosition().y)*0.5f); int ballNum = blueRing.GetClosestPoint(contact); if (blueRing.ActiveFlags[ballNum] == true) { //ok, now launch this ball float speed = 1000.0f; //blueRing.ActiveFlags[ballNum] = false; blueRing.DeactivateBall(ballNum); Vector2D newVel = new Vector2D(width*0.5f-blueRing.points[ballNum].x, height*0.5f-blueRing.points[ballNum].y); newVel.Normalize(); newVel.TimesEquals(speed); ball = new Ball(); ball.r = blueRing.ball_radius; ball.Pos.Set(blueRing.points[ballNum]); ball.Vel.Set(newVel); ball.Elasticity = 0.99f; BballList.add(ball); } } public void TestPaddle2Paddles() { //Assume all blue switches are off to begin with padR1.blueSwitch = false; padR2.blueSwitch = false; padG1.blueSwitch = false; padG2.blueSwitch = false; padY1.blueSwitch = false; padY2.blueSwitch = false; padR1.FiredThisFrame = false; padR2.FiredThisFrame = false; padG1.FiredThisFrame = false; padG2.FiredThisFrame = false; padY1.FiredThisFrame = false; padY2.FiredThisFrame = false; //Test RPad against YPad TestBetweenPaddles(padR1,padY1); TestBetweenPaddles(padR1,padY2); TestBetweenPaddles(padR2,padY1); TestBetweenPaddles(padR2,padY2); //Test RPad against GPad TestBetweenPaddles(padR1,padG1); TestBetweenPaddles(padR1,padG2); TestBetweenPaddles(padR2,padG1); TestBetweenPaddles(padR2,padG2); //Test YPad against GPad TestBetweenPaddles(padY1,padG1); TestBetweenPaddles(padY1,padG2); TestBetweenPaddles(padY2,padG1); TestBetweenPaddles(padY2,padG2); //Signals.. //Store the results for the next frame padR1.bsPrevFrame = padR1.blueSwitch; padR2.bsPrevFrame = padR2.blueSwitch; padG1.bsPrevFrame = padG1.blueSwitch; padG2.bsPrevFrame = padG2.blueSwitch; padY1.bsPrevFrame = padY1.blueSwitch; padY2.bsPrevFrame = padY2.blueSwitch; } public void RenderScene() { ListIterator bi = ballList.listIterator(); //White Balls while (bi.hasNext()) { Ball b = (Ball)bi.next(); //current Circ DrawBall(b,255,255,255); } ListIterator Bbi = BballList.listIterator(); //Blue Balls while (Bbi.hasNext()) { Ball b = (Ball)Bbi.next(); //current Circ DrawBall(b,75,175,255); //DrawBball(b,75,175,255); commenting out } /* ListIterator ci = circList.listIterator(); while (ci.hasNext()) { Circ2D c = (Circ2D)ci.next(); //current Circ DrawCirc(c); } */ ListIterator li = lineList.listIterator(); while (li.hasNext()) { LineSeg2D l = (LineSeg2D)li.next(); //current Circ DrawLineSeg(l); } /* //Paddle render code here ListIterator pi = padList.listIterator(); while (pi.hasNext()) { Paddle p = (Paddle)pi.next(); //current Circ DrawPaddle(p); } */ ListIterator ti = tarList.listIterator(tarList.size()); //start at the end of the list while (ti.hasPrevious()) { Target t = (Target)ti.previous(); //go backwards in list of targets DrawTarget(t,200,200,200); } } public void DrawBlueBallRing() { for (int i=0; i