Last active
February 27, 2019 05:38
-
-
Save Sam-Belliveau/1f0065fa40caf119343d0ea8619caa16 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| static final float PROGRAM_SPEED = 0.1; | |
| final int BALL_COUNT = 100; | |
| final int MAX_SIZE = 25; | |
| final int MIN_SIZE = 5; | |
| Object[] ballList = new Object[BALL_COUNT]; | |
| void setup() { | |
| size(1280, 720); | |
| for(int i = 0; i < BALL_COUNT; ++i) { | |
| float size = random(MIN_SIZE,MAX_SIZE); | |
| PVector pos = new PVector(i*width/(float)BALL_COUNT, (i*MAX_SIZE*2)%height); | |
| ballList[i] = new Object(pos, size); | |
| ballList[i].vel.x = PROGRAM_SPEED*random(-5, 5); | |
| } | |
| } | |
| void draw() { | |
| for(int i = 0; i < BALL_COUNT; ++i) { | |
| for(int j = i + 1; j < BALL_COUNT; ++j) { | |
| ballList[i].bounce(ballList[j]); | |
| } | |
| } | |
| clear(); | |
| for(int i = 0; i < BALL_COUNT; ++i) { | |
| ballList[i].updatePos(); | |
| ballList[i].updateGravity(width, height); | |
| ballList[i].drawObject(); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class Object { | |
| public static final float GRAVITY_VAL = 0.1*PROGRAM_SPEED; | |
| public static final float BOUNCE_VAL = 1; | |
| public static final boolean ROOF = false; | |
| public PVector pos, vel; | |
| public float size; | |
| Object(PVector pos, float size) { | |
| this.size = size; | |
| this.pos = pos; | |
| vel = new PVector(0,0); | |
| } | |
| public void drawObject() { | |
| ellipse(pos.x, pos.y, size*2, size*2); | |
| } | |
| public void updatePos() { | |
| pos.x += vel.x; | |
| pos.y += vel.y; | |
| } | |
| public void updateGravity(float winWidth, float winHeight) { | |
| vel.y += GRAVITY_VAL; | |
| if(vel.y > 0 && pos.y + size >= winHeight) { | |
| vel.y *= -BOUNCE_VAL; | |
| pos.y = winHeight - size; | |
| } else if(ROOF && vel.y < 0 && pos.y - size <= 0) { | |
| vel.y *= -BOUNCE_VAL; | |
| pos.y = size; | |
| } | |
| if(vel.x > 0 && pos.x + size >= winWidth) { | |
| vel.x *= -BOUNCE_VAL; | |
| pos.x = winWidth - size; | |
| } else if(vel.x < 0 && pos.x - size <= 0) { | |
| vel.x *= -BOUNCE_VAL; | |
| pos.x = size; | |
| } | |
| } | |
| public void bounce(Object other) { | |
| if(isTouching(other)) { | |
| // WARNING! STOLEN CODE | |
| // PHYSICS IS COMPLICATED | |
| // WE STOLE THIS!!! | |
| float mass = size*size; | |
| float otherMass = other.size*other.size; | |
| PVector distanceVect = PVector.sub(other.pos, pos); | |
| float distanceVectMag = distanceVect.mag(); | |
| float minDistance = size + other.size; | |
| float distanceCorrection = (minDistance-distanceVectMag)/2.0; | |
| PVector d = distanceVect.copy(); | |
| PVector correctionVector = d.normalize().mult(distanceCorrection); | |
| other.pos.add(correctionVector); | |
| pos.sub(correctionVector); | |
| float theta = distanceVect.heading(); | |
| float sine = sin(theta); | |
| float cosine = cos(theta); | |
| PVector[] bTemp = { new PVector(), new PVector() }; | |
| PVector[] vTemp = { new PVector(), new PVector() }; | |
| bTemp[1].x = cosine * distanceVect.x + sine * distanceVect.y; | |
| bTemp[1].y = cosine * distanceVect.y - sine * distanceVect.x; | |
| vTemp[0].x = cosine * vel.x + sine * vel.y; | |
| vTemp[0].y = cosine * vel.y - sine * vel.x; | |
| vTemp[1].x = cosine * other.vel.x + sine * other.vel.y; | |
| vTemp[1].y = cosine * other.vel.y - sine * other.vel.x; | |
| PVector[] vFinal = { new PVector(), new PVector() }; | |
| PVector[] bFinal = { new PVector(), new PVector() }; | |
| vFinal[0].x = ((mass - otherMass) * vTemp[0].x + 2 * otherMass * vTemp[1].x) / (mass + otherMass); | |
| vFinal[0].y = vTemp[0].y; | |
| vFinal[1].x = ((otherMass - mass) * vTemp[1].x + 2 * mass * vTemp[0].x) / (mass + otherMass); | |
| vFinal[1].y = vTemp[1].y; | |
| bTemp[0].x += vFinal[0].x; | |
| bTemp[1].x += vFinal[1].x; | |
| bFinal[0].x = cosine * bTemp[0].x - sine * bTemp[0].y; | |
| bFinal[0].y = cosine * bTemp[0].y + sine * bTemp[0].x; | |
| bFinal[1].x = cosine * bTemp[1].x - sine * bTemp[1].y; | |
| bFinal[1].y = cosine * bTemp[1].y + sine * bTemp[1].x; | |
| other.pos.x = pos.x + bFinal[1].x; | |
| other.pos.y = pos.y + bFinal[1].y; | |
| pos.add(bFinal[0]); | |
| vel.x = cosine * vFinal[0].x - sine * vFinal[0].y; | |
| vel.y = cosine * vFinal[0].y + sine * vFinal[0].x; | |
| other.vel.x = cosine * vFinal[1].x - sine * vFinal[1].y; | |
| other.vel.y = cosine * vFinal[1].y + sine * vFinal[1].x; | |
| } | |
| } | |
| public boolean isTouching(Object other) { | |
| float distance = getDistance(pos, other.pos); | |
| boolean touching = distance <= size + other.size; | |
| // Prevent balls getting stuck | |
| // TODO: Explain this part to newbies | |
| // it took a lot of time to figure this part out | |
| // so I did it in my free time. | |
| boolean xCheck, yCheck; | |
| if(pos.x < other.pos.x) xCheck = vel.x > other.vel.x; | |
| else xCheck = vel.x < other.vel.x; | |
| if(pos.y < other.pos.y) yCheck = vel.y > other.vel.y; | |
| else yCheck = vel.y < other.vel.y; | |
| return touching && (xCheck || yCheck); | |
| } | |
| private float getDistance(PVector a, PVector b) { | |
| float xDis = a.x - b.x; | |
| float yDis = a.y - b.y; | |
| return (float)Math.sqrt(xDis*xDis + yDis*yDis); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
epic