Lab Week 9 – Particles with Size and Color
Problem 1
Modify the “Mouse Particles” particle system (the last example in Week 9 notes) so that particles have a variety of colors and sizes. For convenience, here’s a copy of the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
var gravity = 0.3; // downward acceleration var springy = 0.7; // how much velocity is retained after bounce var drag = 0.0001; // drag causes particles to slow down var np = 100; // how many particles function particleStep() { this.age++; this.x += this.dx; this.y += this.dy; if (this.x > width) { // bounce off right wall this.x = width - (this.x - width); this.dx = -this.dx * springy; } else if (this.x < 0) { // bounce off left wall this.x = -this.x; this.dx = -this.dx * springy; } if (this.y > height) { // bounce off bottom this.y = height - (this.y - height); this.dy = -this.dy * springy; } else if (this.y < 0) { // bounce off top this.y = -this.y; this.dy = -this.dy * springy; } this.dy = this.dy + gravity; // force of gravity // drag is proportional to velocity squared // which is the sum of the squares of dy and dy var vs = Math.pow(this.dx, 2) + Math.pow(this.dy, 2); // d is the ratio of old velocty to new velocity var d = vs * drag; // d goes up with velocity squared but can never be // so high that the velocity reverses, so limit d to 1 d = min(d, 1); // scale dx and dy to include drag effect this.dx *= (1 - d); this.dy *= (1 - d); } function particleDraw() { point(this.x, this.y); } // create a "Particle" object with position and velocity function makeParticle(px, py, pdx, pdy) { p = {x: px, y: py, dx: pdx, dy: pdy, age: 0, step: particleStep, draw: particleDraw } return p; } var particles = []; function setup() { createCanvas(400, 400); for (var i = 0; i < np; i++) { // make a particle var p = makeParticle(200, 200, random(-50, 50), random(-50, 50)); // push the particle onto particles array particles.push(p); } frameRate(10); } // draw all particles in the particles array // function draw() { background(230); stroke(0); strokeWeight(10); if (mouseIsPressed) { var newp = makeParticle(mouseX, mouseY, random(-10, 10), random(-10, 0)); particles.push(newp); } // newParticles will hold all the particles that we want to // retain for the next call to draw() -- we will retain particles // if the age is < 200 (frames). Initially, newParticle is empty // because we have not found any "young" particles yet. newParticles = []; for (var i = 0; i < particles.length; i++) { // for each particle var p = particles[i]; p.step(); p.draw(); // since we are "looking" at every particle in order to // draw it, let's use the opportunity to see if particle[i] // is younger than 200 frames. If so, we'll push it onto the // end of newParticles. if (p.age < 200) { newParticles.push(p); } } // now, newParticles has EVERY particle with an age < 200 frames. // these are the particles we want to draw next time, so assign // particles to this new array. The old value of particles, i.e. // the entire array, is simply "lost" -- Javascript will reclaim // and reuse the memory since that array is no longer needed. particles = newParticles; } |
You will need to modify the code so that particle objects have new properties to indicate size and color. In the specifications (below), “previous behavior” means what is already in the code which you are free to use, and “new behavior” is behavior that you create by modifying the code.
You should modify the particleDraw
function to use the color and size. Remember that you access properties by writing this.color
and this.size
rather than simply color
and size
, which would access local or global variables by the same names.
You can set the color and size by adding new property functions such as setColor
and setSize
OR you can set color and size variables randomly in makeParticle.
Example
Here is one possible solution:
Specification Check List
- ___ (Previous behavior) Pressing the mouse generates particles at the mouse position.
- ____ (Previous behavior) Particles follow a physics-based trajectory.
- ____ (Previous behavior) Particles bounce off the sides and bottom of the canvas.
- ____ (Previous behavior) Particles disappear after a fixed number of steps.
- ____ (New behavior) Particles must have multiple (at least 5 not including black and white) colors. Particles must not flash or change colors from frame to frame.
- ____ (New behavior) Particles must have multiple (at least 5) sizes. Particle sizes must not change from frame to frame.
- ____ (New behavior) This requirement is brought to you by the Department of Redundancy Department. As previously stated, particles retain their size and color from frame to frame.
Problem 2
Add a coordinate point rpx, rpy to particleStep
to represent a location that repels particles. The repelling force will be equal to rpc / (Math.pow(d, 2)
, where d
is the distance from the particle to (rpx
, rpy
), computed easily with the Processing dist
function. rpc
is a fixed, constant factor you should adjust to get the right “look”: if rpc
is too small, particles will not be noticeably affected by the force. If rpc
is extremely large, particles will all be immediately pushed away, possibly “running” to the corners to “get away.”
To implement repulsion, you want to accelerate away from (rpx
, rpy
) by the repulsive force. Let’s say the force, computed according the formula above, is f
, and assume the particle is at location (x
, y
). Then the direction of the force is dirx = (x - rpx) / d
and diry = (y - rpy) / d
, where d
again is the distance from (x
, y
) to (rpx
, rpy
). The repulsive force to add to (this.dx
, this.dy
) is (dirx * f
, diry * f
).
Draw something at the location (rpx
, rpy
) to give the impression that particles are bouncing off the object.
This challenge is inspired by “Example 4.7: ParticleSystem with repeller” from Chapter 4 of DanielShiffman, The Nature of Code.