Commit 2ef77714 authored by Aapeli's avatar Aapeli

Added pendulum and made some cool stuff

parent de346dd6
......@@ -8,20 +8,13 @@ class Board {
bPixels = new Colour[w][h];
for (int y = 0; y < bHeight; y++) {
for (int x = 0; x < bWidth; x++) {
if (x == 50 && y == 50) {
println("created 50 50");
println(bPixels[x][y]);
}
bPixels[x][y] = new Colour(bg);
if (x == 50 && y == 50) {
println(bPixels[x][y]);
}
}
}
}
Colour getPixel(int x, int y) {
return bPixels[x][y];
return bPixels[x-1][y-1];
}
void Draw() {
......
......@@ -2,26 +2,42 @@ float penX, penY;
Board board;
Colour penColour;
Pendulum pnd1, pnd2, pnd3, pnd4;
float simTime, timeStep, timeDilation;
float startTime, oldTime, curTime;
void setup() {
size(800, 500);
size(1200, 700);
board = new Board(width, height, new Colour(0, 0, 0, 1));
penColour = new Colour(0, 0, 1, 1);
penColour = new Colour(1, 0, 1, 1);
noSmooth();
penX = 50;
penY = 50;
}
void mouseMoved() {
penX = mouseX;
penY = mouseY;
drawCurrentPixel();
timeStep = 0.002;
timeDilation = 0.01;
pnd1 = new Pendulum(0.25, 1.8, 500, 0.3, 0.0, 0, 0.6);
pnd2 = new Pendulum(0.26, 1.9, 500, 0.4, 1.6, 0, 0.3);
pnd3 = new Pendulum(0.24, 2.2, 10, 0.32, 0.1, 0, 0.2);
pnd4 = new Pendulum(0.23, 2.1, 0, 0.27, 5, 0, -1.0);
startTime = millis();
oldTime = startTime;
simTime = startTime;
}
void draw () {
curTime = millis();
while ((simTime - startTime) < (curTime - startTime) * timeDilation) {
pnd1.simulate(timeStep);
pnd2.simulate(timeStep);
pnd3.simulate(timeStep);
pnd4.simulate(timeStep);
penX = width / 2 + pnd1.getX() + pnd2.getX() + pnd3.getX() + pnd4.getX();
penY = height / 2 + pnd1.getY() + pnd2.getY() + pnd3.getY() + pnd4.getY();
drawCurrentPixel();
simTime += timeStep;
}
board.Draw();
}
void drawCurrentPixel() {
board.getPixel(round(penX), round(penY)).darken(penColour.multiply(0.5));
board.getPixel(min(max(round(penX), 1), width), min(max(round(penY), 1), height)).darken(penColour.multiply(0.05));
}
\ No newline at end of file
float A_GRAVITY = 9.81;
float A_EPSILON = 0.00001;
// Basically E_k = 1/2 * m * v^2, and E_p = m * g * h, but E_k + E_p is constant in time
class Pendulum {
// obvious things, outputMultiplier is how much I multiply the motion by to for the output
float mass, armLength, outputMultiplier, maxRad, angle;
// max potential energy relative to being stationaryy
float maxEp;
float curRad;
// This is the sign of the movement true means it's going towards the max point where it started from
boolean positiveDir;
// We'll just pretend dampening of energy is exponential
float dampening;
Pendulum(float mass, float armLength, float outputMultiplier, float maxRad, float angle, float dampening, float p) {
this.mass = mass;
this.armLength = armLength;
this.outputMultiplier = outputMultiplier;
this.maxRad = maxRad;
this.angle = angle;
this.dampening = dampening;
this.maxEp = mass * A_GRAVITY * (armLength - sqrt(armLength * armLength - maxRad * maxRad));
this.curRad = maxRad * p - A_EPSILON ;
this.positiveDir = false;
}
void simulate(float dt) {
// Current height from stationary point
float curHeight = (armLength - sqrt(armLength * armLength - curRad * curRad));
// Current potential energy
float curEp = mass * A_GRAVITY * curHeight;
// Current kinetic energy
float curEk = maxEp - curEp;
// Current speed (note that the velocity vector isn't in the plane)
float curSpd = sqrt(2 * mass * abs(curEk));
// Projection of velocity vector onto the line spanned by the initial position vector
// I'm doing this via similar triangles, it's easy if you draw a diagram
float curPlaneSpd = curSpd * (armLength - curHeight) / armLength;
float movement = dt * curPlaneSpd;
//println(curHeight, maxEp, curEp, curEk, curSpd, curPlaneSpd, movement);
if (positiveDir) {
// If we are epsilon close to the max point, turn around
// note that curRad is always larger than positiveDir
// the sign of the difference is important
if (maxRad - curRad < A_EPSILON) {
curRad -= movement;
positiveDir = false;
} else {
curRad += movement;
}
} else {
if (maxRad + curRad < A_EPSILON) {
curRad += movement;
positiveDir = true;
} else {
curRad -= movement;
}
}
maxEp *= 1 - dampening * dt;
maxRad = sqrt(armLength * armLength - (armLength - maxEp / (mass * A_GRAVITY)) * (armLength - maxEp / (mass * A_GRAVITY)));
}
float getX() {
return outputMultiplier * curRad * cos(angle);
}
float getY() {
return outputMultiplier * curRad * sin(angle);
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment