## Screen

http://cmuems.com/2013/a/wp-content/uploads/sites/2/2013/10/frame-0070.pdf

Confetti Screen 1

http://cmuems.com/2013/a/wp-content/uploads/sites/2/2013/10/frame-0082.pdf

Confetti Screen 2

### Description

This screen design was mostly just an interesting mistake that came about while I was working on my original screen concept. The basic way that the sketch works is that a set of uniform particles are placed at random locations in the window. Then, a repulsive force between the particles gradually pushes them apart. The particles draw their own trails as paths, and the stroke outliner helper function turns those paths into wider strokes. The sketch stops when the user presses ‘d’ and is recorded when the user presses ‘r’.

## Code

### Main

```
import oscP5.*;
import netP5.*;
import processing.pdf.*;
ArrayList myParticles;
boolean doneDrawing = false;
int margin;
boolean record = false;
void setup() {
size(864, 864);
myParticles = new ArrayList();
margin = 50;
for (int i=0; i<900; i++) {
float rx = random(margin, width-margin);
float ry = random(margin, height-margin);
myParticles.add( new Particle(rx, ry));
}
smooth();
}
void mousePressed() {
noLoop();
}
void mouseReleased() {
loop();
}
void keyPressed() {
if (key == 'd') {
doneDrawing = true;
}
if (key == 'r') {
record = true;
}
}
void draw() {
if (record) {
// Note that #### will be replaced with the frame number. Fancy!
beginRecord(PDF, "frame-####.pdf");
}
// background (255);
float gravityForcex = 0;
float gravityForcey = 0.02;
float mutualRepulsionAmount = 3.0;
if (doneDrawing == false) {
// calculating repulsion and updating particles
for (int i=0; i 1.0) {
float componentInX = dx/dh;
float componentInY = dy/dh;
float proportionToDistanceSquared = 1.0/(dh*dh);
float repulsionForcex = mutualRepulsionAmount * componentInX * proportionToDistanceSquared;
float repulsionForcey = mutualRepulsionAmount * componentInY * proportionToDistanceSquared;
ithParticle.addForce( repulsionForcex, repulsionForcey); // add in forces
jthParticle.addForce(-repulsionForcex, -repulsionForcey); // add in forces
}
}
}
for (int i=0; i
```

### Particle

```
class Particle {
//float px;
//float py;
float vx;
float vy;
PVector currentPosition;
ArrayList trail;
int trailWidth;
float damping;
float mass;
boolean bLimitVelocities = true;
boolean bPeriodicBoundaries = false;
// Constructor for the Particle
Particle (float x, float y) {
currentPosition = new PVector(x, y);
vx = vy = 0;
damping = 0.96;
mass = 1.0;
trail = new ArrayList();
trailWidth = 5;
}
// Add a force in. One step of Euler integration.
void addForce (float fx, float fy) {
float ax = fx / mass;
float ay = fy / mass;
vx += ax;
vy += ay;
}
// Update the position. Another step of Euler integration.
void update() {
vx *= damping;
vy *= damping;
limitVelocities();
handleBoundaries();
currentPosition.x += vx;
currentPosition.y += vy;
PVector logPosition = new PVector(currentPosition.x, currentPosition.y);
trail.add(logPosition);
println(trail.size());
}
void limitVelocities(){
if (bLimitVelocities){
float speed = sqrt(vx*vx + vy*vy);
float maxSpeed = 10;
if (speed > maxSpeed){
vx *= maxSpeed/speed;
vy *= maxSpeed/speed;
}
}
}
void handleBoundaries() {
// wraparound
if (bPeriodicBoundaries) {
if (currentPosition.x > width - margin ) currentPosition.x -= width;
if (currentPosition.x < margin ) currentPosition.x += width;
if (currentPosition.y > height - margin) currentPosition.y -= height;
if (currentPosition.y < margin ) currentPosition.y += height;
}
// bounce
else {
if (currentPosition.x > width - margin ) vx = -vx;
if (currentPosition.x < margin ) vx = -vx;
if (currentPosition.y > height - margin) vy = -vy;
if (currentPosition.y < margin ) vy = -vy;
}
}
/* I want my particles to draw their trails but can't figure out how. Thoughts? */
void render() {
drawStrokeOutline(trail, trailWidth);
}
}
```

### Simple Stroke Outliner

```
void drawStrokeOutline(ArrayList points, int strokeWidth) {
noFill();
stroke(0);
strokeWeight(1);
beginShape();
// iterate over points in array going from to back, drawing shape
for (int i=0; i < points.size(); i++) {
PVector currentPoint = points.get(i);
vertex(currentPoint.x, currentPoint.y);
}
endShape();
beginShape();
// then go backwards, and shift all points down by strokeWidth,
// continuing the same shape
int lastIndex = points.size() - 1;
for (int i=lastIndex; i >=0; i--) {
PVector currentPoint = points.get(i);
vertex(currentPoint.x - strokeWidth, currentPoint.y + (strokeWidth*0.5));
}
endShape();
/* delete later
stroke(0);
PVector sPoint = points.get(points.size() - 1);
line(sPoint.x, sPoint.y, sPoint.x - strokeWidth, sPoint.y + (strokeWidth*0.5));
*/
if (doneDrawing) { // draw start cap
stroke(0);
PVector startPoint = points.get(0);
line(startPoint.x, startPoint.y, startPoint.x - strokeWidth, startPoint.y + (strokeWidth*0.5));
// close line by drawing caps
PVector endPoint = points.get(lastIndex);
line(endPoint.x, endPoint.y, endPoint.x - strokeWidth, endPoint.y + (strokeWidth*0.5));
}
}
```