[BETA] P5 Verlet Integration (Ragdoll/Vehicle physics)
For those of you who've checked out Processing, I've converted the framework of my (much props to Metanet) VI engine into p5 to take advantage of its power. I'm still relatively new to Java so my syntax may seem a tad strange, but it works :) (P5 v0.91)
Code:
Point[] pL;
Segment[] sL;
Circle[] cL;
void setup() {
size(600, 400);
framerate(60);
stroke(20, 60, 40);
ellipseMode(CENTER);
noSmooth();
noFill();
pL = new Point[4];
pL[0] = new Point(0, 0);
pL[1] = new Point(50, 0);
pL[2] = new Point(50, 50);
pL[3] = new Point(0, 50);
sL = new Segment[6];
sL[0] = new Segment(0, 1, true);
sL[1] = new Segment(1, 2, true);
sL[2] = new Segment(2, 3, true);
sL[3] = new Segment(3, 0, true);
sL[4] = new Segment(0, 2, true);
sL[5] = new Segment(1, 3, true);
cL = new Circle[4];
cL[0] = new Circle(100, 100, 50);
cL[1] = new Circle(175, 200, 75);
cL[2] = new Circle(275, 275, 50);
cL[3] = new Circle(350, 350, 25);
}
float getDistance(int p0, int p1) {
return sqrt(sq(pL[p0].x-pL[p1].x)+sq(pL[p0].y-pL[p1].y));
}
float initX = 100;
float initY = 0;
float drag = .9;
float grav = 1;
float cx, cy, cr, a, a0, a1, px, py, dx, dy, d0, d1, d;
int p0, p1;
void draw() {
background(120, 140, 100);
if (mousePressed) {
pL[0].x += (mouseX-pL[0].x)/25;
pL[0].y += (mouseY-pL[0].y)/25;
}
for (int i=0; i<pL.length; i++) {
px = pL[i].oX;
py = pL[i].oY;
pL[i].oX = pL[i].x;
pL[i].oY = pL[i].y;
pL[i].x += drag*(pL[i].oX-px);
pL[i].y += drag*(pL[i].oY-py)+grav;
}
for (int i=0; i<sL.length; i++) {
p0 = int(sL[i].p0);
p1 = int(sL[i].p1);
dx = pL[p0].x-pL[p1].x;
dy = pL[p0].y-pL[p1].y;
d = getDistance(p0, p1);
d0 = d1 = (d-sL[i].rL)/d;
d0 *= 0.5;
d1 *= 0.5;
pL[p0].x -= dx*d0;
pL[p0].y -= dy*d0;
pL[p1].x += dx*d1;
pL[p1].y += dy*d1;
}
for (int i=0; i<sL.length; i++) {
if (!sL[i].collide) {
continue;
}
p0 = int(sL[i].p0);
p1 = int(sL[i].p1);
for (int j=0; j<cL.length; j++) {
cx = cL[j].x;
cy = cL[j].y;
cr = cL[j].r;
d0 = sqrt(sq(pL[p0].x-cx)+sq(pL[p0].y-cy));
d1 = sqrt(sq(pL[p1].x-cx)+sq(pL[p1].y-cy));
a0 = abs(atan2(pL[p0].y-cy, pL[p0].x-cx)*180/PI-atan2(pL[p0].y-pL[p1].y, pL[p0].x-pL[p1].x)*180/PI);
a1 = abs(atan2(pL[p1].y-cy, pL[p1].x-cx)*180/PI-atan2(pL[p1].y-pL[p0].y, pL[p1].x-pL[p0].x)*180/PI);
a0 = a0 <= 180 ? a0 : 360-a0;
a1 = a1 <= 180 ? a1 : 360-a1;
if (a0>90) {
if (d0<cr) {
d0 = cr-d0;
dx = pL[p0].x-cx;
dy = pL[p0].y-cy;
pL[p0].x += d0*(dx/cr);
pL[p0].y += d0*(dy/cr);
}
}
else if (a1>90) {
if (d1 < cr) {
d1 = cr-d1;
dx = pL[p1].x-cx;
dy = pL[p1].y-cy;
pL[p1].x += d1*(dx/cr);
pL[p1].y += d1*(dy/cr);
}
}
else {
if (d0>d1) {
a = (45-(a1-a0))/90;
px = pL[p1].x+(pL[p0].x-pL[p1].x)*a;
py = pL[p1].y+(pL[p0].y-pL[p1].y)*a;
}
else {
a = (45-(a0-a1))/90;
px = pL[p0].x+(pL[p1].x-pL[p0].x)*a;
py = pL[p0].y+(pL[p1].y-pL[p0].y)*a;
}
d = sqrt(sq(px-cx)+sq(py-cy));
if (d < cr) {
d = cr-d;
dx = (px-cx)/cr;
dy = (py-cy)/cr;
pL[p0].x += d*dx;
pL[p0].y += d*dy;
pL[p1].x += d*dx;
pL[p1].y += d*dy;
}
}
}
if (pL[p0].x < 0) {
pL[p0].x = 0;
}
else if (pL[p0].x > width) {
pL[p0].x = width;
}
if (pL[p0].y < 0) {
pL[p0].y = 0;
}
else if (pL[p0].y > height) {
pL[p0].y = height;
}
if (pL[p1].x < 0) {
pL[p1].x = 0;
}
else if (pL[p1].x > width) {
pL[p1].x = width;
}
if (pL[p1].y < 0) {
pL[p1].y = 0;
}
else if (pL[p1].y > height) {
pL[p1].y = height;
}
}
for (int i=0; i<cL.length; i++) {
ellipse(cL[i].x, cL[i].y, cL[i].r*2, cL[i].r*2);
}
for (int i=0; i<sL.length; i++) {
p0 = int(sL[i].p0);
p1 = int(sL[i].p1);
line(pL[p0].x, pL[p0].y, pL[p1].x, pL[p1].y);
}
}
class Point {
float x, y, oX, oY;
Point (float Tx, float Ty) {
x = Tx+initX;
y = Ty+initY;
oX = x;
oY = y;
}
}
class Segment {
int p0, p1;
float rL;
boolean collide;
Segment (int Tp0, int Tp1, boolean Tcollide) {
p0 = int(Tp0);
p1 = int(Tp1);
rL = getDistance(p0, p1);
collide = Tcollide;
}
}
class Circle {
float x, y, r;
Circle (float Tx, float Ty, float Tr) {
x = Tx;
y = Ty;
r = Tr;
}
}
EDIT: As of now there is only line/circle collision (took me a few hours to figure it out :rolleyes: ) and point/window collision. Also wanted to show off my "Modern Art" generator :D
Code:
void setup() {
size(600, 400);
smooth();
background(255);
}
int r = 0;
int g = 0;
int b = 0;
int ranC = 5;
float ranM = 5;//random(5, 100);
float x = 300;
float y = 200;
float nx, ny;
void draw() {
stroke(r, g, b);
nx = x+random(-ranM, ranM);
nx = nx<0?abs(nx):nx;
nx = nx>width?width*2-nx:nx;
ny = y+random(-ranM, ranM);
ny = ny<0?abs(ny):ny;
ny = ny>height?height*2-ny:ny;
line(x, y, nx, ny);
x = nx;
y = ny;
r += random(-ranC, ranC);
r = r<0?255+r:r;
r = r>255?r-255:r;
g += random(-ranC, ranC);
g = g<0?255+g:g;
g = g>255?g-255:g;
b += random(-ranC, ranC);
b = b<0?255+b:b;
b = b>255?b-255:b;
}
EDIT2: If you're confused, http://www.processing.org/