Newton's cradle
in
Programming Questions
•
2 years ago
alt = "HELP purleeze, oldie needs help"
Hi
I've slogging away at this in varying forms for quite some time, and have finally got close. The balls are swinging - mimicking SHM*. The collisions are working the best ever. But I've been staring at it so long that I can't figure out how to drag the balls to the side to start it all off.
*Note that I say mimicking SHM, though I got that to work and have left in the code for it. Because the movement is frame-based it played hell with the collisions.
Note also that there's a lot of testing stuff in the code that I'd normally strip out before posting. And there's lots more to do that I can't test until I get the dragging to work.
Thanks
string
main tab
- int numBobs = 5;
int[] swingDegrees;
float[] swingAngles;
Pendulum[] bobs;
float stringLength = 100;
float bobSize = 30;
color[] colours;
int frameSpeed = 32; //don't change this! 25-32
float xoffset;
float closestAngle = 100;
int closestAngleCount = 100;
void setup()
{
size(300, 300);
background(255);
smooth();
frameRate(frameSpeed);
// noLoop();
swingAngles = new float[17]; //magic number and angles found by experiment and observation
int[] swingDegrees = {38, 37, 34, 31, 26, 20, 14, 7, 0, -7, -14, -20, -26, -31, -34, -37, -38};
for(int a = 0; a < swingDegrees.length; a++)
{
swingAngles[a] = radians(swingDegrees[a]);
}
// println(swingAngles);
xoffset = (width - (numBobs - 1) * bobSize) / 2;
bobs = new Pendulum[numBobs];
colours = new color[numBobs];
// color[] colours = {color(201, 58, 18), color(190, 96, 24), color(191, 170, 87), color(149, 130, 68), color(141, 171, 173)};
for(int b = 0; b < numBobs; b++)
{
colours[b] = color(b * 255 / numBobs); // greyscale for testing
bobs[b] = new Pendulum(swingAngles, stringLength, bobSize, colours[b]);
// bobs[b] = new Pendulum(swingAngles, stringLength, bobSize, colours[(int)random(0, colours.length)]);
bobs[b].setVertical();
}
// setStartPositions();
autoStartLeft();
// autoStartRight();
}
//void setStartPositions()
//{
// for(int b = 0; b < numBobs; b++)
// {
// bobs[b].swinging = false;
// bobs[b].count = 8;
// }
//}
void autoStartLeft()
{
bobs[0].count = 0;
bobs[0].swinging = true;
}
void autoStartRight()
{
bobs[numBobs - 1].count = 15;
bobs[numBobs - 1].swinging = true;
}
void draw()
{
background(255, 200);
if(numBobs > 1)
{
click(bobs);
}
for(int b = 0; b < numBobs; b++)
{
pushMatrix();
translate(xoffset + b * bobSize, 100);
bobs[b].display();
popMatrix();
}
//}
//
//void mouseDragged()
//{
if(mousePressed)
{
for(int b = 0; b < numBobs; b++)
{
float bobX = xoffset + b * bobSize + bobs[b].getBobCentre().x;
float bobY = 100 + bobs[b].getBobCentre().y;
if(dist(mouseX, mouseY, bobX, bobY) < bobSize / 2)
{
println("GRAB " + b);
float dragX = (xoffset + b * bobSize) - mouseX;
float dragAngle = asin(dragX / stringLength);
println(dragX +" "+ degrees(dragAngle));
if(pmouseX > mouseX) // drag clockwise
{
closestAngle = 100;
closestAngleCount = 100;
println("CLOCK");
for(int a = 8; a < 17; a++) //swingAngles array is 17 long
{
float compareAngle = abs(swingAngles[a] - dragAngle);
if(compareAngle < closestAngle)
{
closestAngle = compareAngle;
closestAngleCount = a;
}
}
for(int c = 0; c <= b; c++) // drag all those to left too
{
bobs[c].setCount(closestAngleCount);
}
}
else if(pmouseX < mouseX) //drag anticlockwise
{
closestAngle = 100;
closestAngleCount = 100;
println("ANTI");
for(int a = 0; a <= 8; a++) //swingAngles array is 17 long
{
float compareAngle = abs(swingAngles[a] - dragAngle);
println(compareAngle);
if(compareAngle < closestAngle)
{
closestAngle = compareAngle;
closestAngleCount = a;
println("a= " + a);
}
}
for(int c = b; c < numBobs; c++) // drag all those to right too
{
bobs[c].count = closestAngleCount;
}
}
}
}
}
}
void keyPressed()
{
if(keyCode == 32) //spacebar
{
for(int b = 0; b < numBobs; b++) bobs[b].setVertical();
}
if(key == 'l' || key == 'L')
{
autoStartLeft();
}
if(key == 'r' || key == 'R')
{
autoStartRight();
}
}
Pendulum class
- //comments #1 - uncomment these to see correct swinging motion (SHM)
// comments #2 - uncomment for good enough swinging motion
// neither will work with the other tabs here (the code has since evolved)
// for sensible results set framerate to 25-32, and stringLength to 100
// I've moved on to a fixed swing as the collision wasn't working well
class Pendulum
{
float angle;
float stringLength;
float bobSize;
color colour;
// float velocity = 0; //#1
// float gravity = 100;//98 //#1
// float swingGravity = gravity / frameSpeed; //#1
float[] swingAngles;
float friction = 0.99;
int count = 8;
Boolean swinging = false;
String swingDirection = "ANTICLOCK";
Pendulum(float[] swingAngles, float stringLength, float bobSize, color colour)
{
this.stringLength = stringLength;
this.bobSize = bobSize;
this.colour = colour;
this.swingAngles = swingAngles;
this.angle = angle;
this.count = count;
}
void display()
{
float bobxpos = getBobCentre().x;
float bobypos = getBobCentre().y;
stroke(0);
strokeWeight(2);
line(0, 0, bobxpos, bobypos);
noStroke();
fill(colour);
ellipse(bobxpos, bobypos, bobSize, bobSize);
if(swinging)
{
angle = swingAngles[count];
if(count == 0)
{
swingDirection = "ANTICLOCK";
}
if(count == 16)
{
swingDirection = "CLOCK";
}
if(swingDirection == "ANTICLOCK")
{
count++;
}
if(swingDirection == "CLOCK")
{
count--;
}
}
}
void setCount(int newCount)
{
count = newCount;
}
void setVertical()
{
setCount(8);
swinging = false;
}
void setSwingLeft()
{
swinging = true;
swingDirection = "CLOCK";
}
void setSwingRight()
{
swinging = true;
swingDirection = "ANTICLOCK";
}
PVector getBobCentre()
{
float bobCentreX = cos(angle + HALF_PI) * stringLength;
float bobCentreY = sin(angle + HALF_PI) * stringLength;
return new PVector(bobCentreX, bobCentreY);
}
}
// void swing()
// {
// velocity += (swingGravity / stringLength) * sin(angle); //#1
// velocity *= friction; //#1
// angle -= velocity; //#1
// velocity += (sin(angle) / frameRate); //#2
// angle -= velocity; //#2
// }
click function
- void click(Pendulum[] bobs)
{
for(int b = 0; b < numBobs - 1; b++)
{
if(bobs[b].count > bobs[b+1].count)
{
// if both swinging
if((bobs[b].swinging == true) && (bobs[b+1].swinging == true))
{
// println("both");
int tempCount = bobs[b].count;
bobs[b].count = bobs[b+1].count;
bobs[b+1].count = tempCount;
bobs[b].setSwingLeft();
bobs[b+1].setSwingRight();
} else
// if left one swinging, right one still and so vertical
if((bobs[b].swinging == true) && (bobs[b+1].swinging == false))
{
// println("left swinging");
bobs[b].setVertical();
bobs[b+1].setSwingRight();
} else
// if left one still and so vertical, right one swinging
if((bobs[b+1].swinging == true) && (bobs[b].swinging == false))
{
// println("right swinging");
bobs[b+1].setVertical();
bobs[b].setSwingLeft();
}
}
}
}
1