//
// Supawat Vitoorapakorn
// Svitoora@andrew.cmu.edu
// Section E
//
// Gravity 2.0 is a point mass dynamic drawing inspired
// from physics, nature, and falling off a skateboard.
// f = G (m1*m2)/d^2
// f = G sum(m)/(d from avg)^2
// World Model Setup /////////////////////////////////////
var max_curves = 4; //Limit amount of drawings
var w = 300;
var h = 400;
var t = 1; // time variable
var g = 12; // gravity
var ball;
var balls = []; // Local Objects
var ballz = []; // Global Object
var ball_size = w * .010 // Default object size
var max_count = 35;
var auto_every = 40;
var auto_create = 125;
var max_line = 1000; // Prevents crash
// Control ///////////////////////////////////////////////
// Creates new object in system given (x,y)
function ball_create(x, y) {
this.x = x;
this.y = y;
this.vx = 0;
this.vy = 0;
this.r = ball_size;
this.m = 1;
this.ALPHA = 255
}
function mousePressed() {
ballz.push([]);
// print("Added Yo");
}
// Add new object and delete oldest object
function mouseDragged() {
if (t % 10) {
ballz[ballz.length - 1].push(new ball_create(mouseX, mouseY));
}
if (ballz[ballz.length - 1].length >= max_count) {
ballz[ballz.length - 1].splice(0, 1)
}
}
// World /////////////////////////////////////////////////
// Maintain global mass of system
function sum_mass(balls) {
sum_m = 0;
for (i in balls) {
sum_m += balls[i].m;
}
return sum_m;
}
// Determines the system's average position X
function average_posX(balls) {
if (balls.length == 0) {
return w / 2;
};
var sum_x = 0;
for (i in balls) {
sum_x += balls[i].x;
}
avg = sum_x / balls.length
return avg;
}
// Determines the system's average position Y
function average_posY(balls) {
if (balls.length == 0) {
return h / 2;
};
var sum_y = 0;
for (i in balls) {
sum_y += balls[i].y;
}
avg = sum_y / balls.length;
return avg
}
// Apply gravity for all objects in the system
function gravity(balls) {
var avg_x = average_posX(balls);
var avg_y = average_posY(balls);
var speed = .005 //0-1 Multuplier for controlling velocity of attratction
for (i in balls) {
d = dist(balls[i].x, balls[i].y, avg_x, avg_y);
ds = map(d, 0, w / 2, 1, 0); // used to simulate d^2
// Gravity X
if (balls[i].x > avg_x) {
balls[i].x *= 1 - (g * (balls.length * speed));
} else {
balls[i].x *= 1 + (g * (balls.length * speed + ds));
}
// Gravity Y
if (balls[i].y > avg_y) {
balls[i].y *= 1 - (g * (balls.length * speed))
} else {
balls[i].y *= 1 + (g * (balls.length * speed + ds));
}
}
}
// Add object to system in the middle; // Used at setup()
function add_ball(balls) {
balls.push(new ball_create(w / 2, h / 2));
}
// Connects all the object in the system via a line
function draw_line(balls) {
lines = 0
opacity = 255 * .1
if (lines < max_line) {
for (i in balls) {
var x_1 = balls[i].x;
var y_1 = balls[i].y;
for (i in balls) {
var x_2 = balls[i].x;
var y_2 = balls[i].y;
stroke(255, 255, 255, opacity);
line(x_1, y_1, x_2, y_2);
lines += 1;
}
}
}
}
// SETUP
function setup() {
createCanvas(w, h);
g = .0025;
background(50);
balls.length = 0; // Kill all objects in system
}
// Refreshes the systems with new objects
// Removes old objects and add new objects
function auto_refresh(balls, t) {
// Starts refreshing system at 5 objects
// every auto_every interval.
if (t % auto_every == 0 & balls.length > 5) {
balls.splice(0, 1);
}
X = constrain(mouseX, 1, w);
Y = constrain(mouseY, 1, h)
if (t % auto_every == 0) {
balls.push(new ball_create(X, Y));
}
// Resets the system to 8 objects once every 500 ms
// This prevents overload; Array starts at [0]
if (t % 500 == 0 & balls.length > 8) {
balls.length = 7;
}
}
// Draw ////////////////////////////////////////////////////
// Draw all objects in systems mapped by distance from avg
function draw_balls(BALLS) {
// print("BALLS.length" + BALLS.length)
for (i in BALLS) {
var avg_x = average_posX(BALLS);
var avg_y = average_posY(BALLS);
var d = dist(BALLS[i].x, BALLS[i].y, avg_x, avg_y);
var SIZE = map(d, 0, w / 2, -2, 3) //max to min
print(i + " : " + SIZE)
noStroke();
fill(255, 255, 255, 255 * .5);
ellipse(BALLS[i].x, BALLS[i].y,
BALLS[i].r * (2 * SIZE),
BALLS[i].r * (2 * SIZE));
}
}
function local_gravity(ballz) {
for (i in ballz) {
if (ballz[i].length > 1) {
gravity(ballz[i]);
}
}
}
function DIE(BALLS) {
BALLS.splice(0, 1);
}
function death_ballz(ballz) {
var populated = 0;
for (i in ballz) {
if (ballz[i].length != 0) {
populated++;
}
}
if (populated > max_curves) {
DIE(ballz[0]);
}
}
function refresh_ballz(ballz) {
if (ballz.length > 4) {
for (i in ballz) {
if (ballz[i].length == 0) {
ballz.splice(i, i + 1);
ballz.push([]);
}
}
}
}
function draw_ballz(ballz) {
for (i in ballz) {
draw_balls(ballz[i]);
}
}
function draw_lines(balls) {
for (i in ballz) {
draw_line(ballz[i]);
}
}
// Creates Trail
function guider1() {
stroke(255, 255, 255, 255 * .75)
line(mouseX, mouseY, pmouseX, pmouseY)
}
// Prompt user to drag via random generation
function guider2() {
ran1 = random(4, 12);
if (t % auto_create == 0) {
ballz.push([])
ballz[ballz.length - 1].push(new ball_create(mouseX, mouseY));
ballz[ballz.length - 1].push(new ball_create(pmouseX, pmouseY));
for (var i = 0; i < ran1; i++) {
ballz[ballz.length - 1].push(new ball_create(mouseX * random(.75,
1.25), mouseY * random(.75, 1.25)));
}
}
}
// Execute /////////////////////////////////////////////////
function draw() {
background(50);
noStroke();
// Update World
t = t + 1;
local_gravity(ballz);
death_ballz(ballz);
refresh_ballz(ballz);
// LOL();
// // Draw World
draw_lines(ballz);
guider1();
guider2();
// draw_ballz(ballz); // For Some reason this doesn't work
// Maybe it ran out of memory allocation
}
Click and drag to draw shapes. Try writing your name. I struggle with array in arrays. Eventually figured I figured it out.