Re-adding Topics to SVN

This commit is contained in:
Casey Reas
2011-09-05 23:58:47 +00:00
parent 4fc6dcca86
commit 391c79c2b6
219 changed files with 31093 additions and 0 deletions
@@ -0,0 +1,47 @@
/**
* Bounce.
*
* When the shape hits the edge of the window, it reverses its direction.
*/
int size = 60; // Width of the shape
float xpos, ypos; // Starting position of shape
float xspeed = 2.8; // Speed of the shape
float yspeed = 2.2; // Speed of the shape
int xdirection = 1; // Left or Right
int ydirection = 1; // Top to Bottom
void setup()
{
size(640, 200);
noStroke();
frameRate(30);
smooth();
// Set the starting position of the shape
xpos = width/2;
ypos = height/2;
}
void draw()
{
background(102);
// Update the position of the shape
xpos = xpos + ( xspeed * xdirection );
ypos = ypos + ( yspeed * ydirection );
// Test to see if the shape exceeds the boundaries of the screen
// If it does, reverse its direction by multiplying by -1
if (xpos > width-size || xpos < 0) {
xdirection *= -1;
}
if (ypos > height-size || ypos < 0) {
ydirection *= -1;
}
// Draw the shape
ellipse(xpos+size/2, ypos+size/2, size, size);
}
@@ -0,0 +1,97 @@
/**
* Bouncy Bubbles.
* Based on code from Keith Peters (www.bit-101.com).
*
* Multiple-object collision.
*/
int numBalls = 12;
float spring = 0.05;
float gravity = 0.03;
float friction = -0.9;
Ball[] balls = new Ball[numBalls];
void setup()
{
size(640, 200);
noStroke();
smooth();
for (int i = 0; i < numBalls; i++) {
balls[i] = new Ball(random(width), random(height), random(20, 40), i, balls);
}
}
void draw()
{
background(0);
for (int i = 0; i < numBalls; i++) {
balls[i].collide();
balls[i].move();
balls[i].display();
}
}
class Ball {
float x, y;
float diameter;
float vx = 0;
float vy = 0;
int id;
Ball[] others;
Ball(float xin, float yin, float din, int idin, Ball[] oin) {
x = xin;
y = yin;
diameter = din;
id = idin;
others = oin;
}
void collide() {
for (int i = id + 1; i < numBalls; i++) {
float dx = others[i].x - x;
float dy = others[i].y - y;
float distance = sqrt(dx*dx + dy*dy);
float minDist = others[i].diameter/2 + diameter/2;
if (distance < minDist) {
float angle = atan2(dy, dx);
float targetX = x + cos(angle) * minDist;
float targetY = y + sin(angle) * minDist;
float ax = (targetX - others[i].x) * spring;
float ay = (targetY - others[i].y) * spring;
vx -= ax;
vy -= ay;
others[i].vx += ax;
others[i].vy += ay;
}
}
}
void move() {
vy += gravity;
x += vx;
y += vy;
if (x + diameter/2 > width) {
x = width - diameter/2;
vx *= friction;
}
else if (x - diameter/2 < 0) {
x = diameter/2;
vx *= friction;
}
if (y + diameter/2 > height) {
y = height - diameter/2;
vy *= friction;
}
else if (y - diameter/2 < 0) {
y = diameter/2;
vy *= friction;
}
}
void display() {
fill(255, 204);
ellipse(x, y, diameter, diameter);
}
}
@@ -0,0 +1,48 @@
/**
* Brownian motion.
*
* Recording random movement as a continuous line.
*/
int num = 2000;
int range = 6;
float[] ax = new float[num];
float[] ay = new float[num];
void setup()
{
size(640, 360);
for(int i = 0; i < num; i++) {
ax[i] = width/2;
ay[i] = height/2;
}
frameRate(30);
}
void draw()
{
background(51);
// Shift all elements 1 place to the left
for(int i = 1; i < num; i++) {
ax[i-1] = ax[i];
ay[i-1] = ay[i];
}
// Put a new value at the end of the array
ax[num-1] += random(-range, range);
ay[num-1] += random(-range, range);
// Constrain all points to the screen
ax[num-1] = constrain(ax[num-1], 0, width);
ay[num-1] = constrain(ay[num-1], 0, height);
// Draw a line connecting the points
for(int i=1; i<num; i++) {
float val = float(i)/num * 204.0 + 51;
stroke(val);
line(ax[i-1], ay[i-1], ax[i], ay[i]);
}
}
@@ -0,0 +1,16 @@
class Ball{
float x, y, r, m;
// default constructor
Ball() {
}
Ball(float x, float y, float r) {
this.x = x;
this.y = y;
this.r = r;
m = r*.1;
}
}
@@ -0,0 +1,136 @@
/**
* Circle Collision with Swapping Velocities
* by Ira Greenberg.
*
* Based on Keith Peter's Solution in
* Foundation Actionscript Animation: Making Things Move!
*/
Ball[] balls = {
new Ball(100, 400, 20),
new Ball(700, 400, 80)
};
PVector[] vels = {
new PVector(2.15, -1.35),
new PVector(-1.65, .42)
};
void setup() {
size(640, 360);
smooth();
noStroke();
}
void draw() {
background(51);
fill(204);
for (int i=0; i< 2; i++){
balls[i].x += vels[i].x;
balls[i].y += vels[i].y;
ellipse(balls[i].x, balls[i].y, balls[i].r*2, balls[i].r*2);
checkBoundaryCollision(balls[i], vels[i]);
}
checkObjectCollision(balls, vels);
}
void checkObjectCollision(Ball[] b, PVector[] v){
// get distances between the balls components
PVector bVect = new PVector();
bVect.x = b[1].x - b[0].x;
bVect.y = b[1].y - b[0].y;
// calculate magnitude of the vector separating the balls
float bVectMag = sqrt(bVect.x * bVect.x + bVect.y * bVect.y);
if (bVectMag < b[0].r + b[1].r){
// get angle of bVect
float theta = atan2(bVect.y, bVect.x);
// precalculate trig values
float sine = sin(theta);
float cosine = cos(theta);
/* bTemp will hold rotated ball positions. You
just need to worry about bTemp[1] position*/
Ball[] bTemp = {
new Ball(), new Ball() };
/* b[1]'s position is relative to b[0]'s
so you can use the vector between them (bVect) as the
reference point in the rotation expressions.
bTemp[0].x and bTemp[0].y will initialize
automatically to 0.0, which is what you want
since b[1] will rotate around b[0] */
bTemp[1].x = cosine * bVect.x + sine * bVect.y;
bTemp[1].y = cosine * bVect.y - sine * bVect.x;
// rotate Temporary velocities
PVector[] vTemp = {
new PVector(), new PVector() };
vTemp[0].x = cosine * v[0].x + sine * v[0].y;
vTemp[0].y = cosine * v[0].y - sine * v[0].x;
vTemp[1].x = cosine * v[1].x + sine * v[1].y;
vTemp[1].y = cosine * v[1].y - sine * v[1].x;
/* Now that velocities are rotated, you can use 1D
conservation of momentum equations to calculate
the final velocity along the x-axis. */
PVector[] vFinal = {
new PVector(), new PVector() };
// final rotated velocity for b[0]
vFinal[0].x = ((b[0].m - b[1].m) * vTemp[0].x + 2 * b[1].m *
vTemp[1].x) / (b[0].m + b[1].m);
vFinal[0].y = vTemp[0].y;
// final rotated velocity for b[0]
vFinal[1].x = ((b[1].m - b[0].m) * vTemp[1].x + 2 * b[0].m *
vTemp[0].x) / (b[0].m + b[1].m);
vFinal[1].y = vTemp[1].y;
// hack to avoid clumping
bTemp[0].x += vFinal[0].x;
bTemp[1].x += vFinal[1].x;
/* Rotate ball positions and velocities back
Reverse signs in trig expressions to rotate
in the opposite direction */
// rotate balls
Ball[] bFinal = {
new Ball(), new Ball() };
bFinal[0].x = cosine * bTemp[0].x - sine * bTemp[0].y;
bFinal[0].y = cosine * bTemp[0].y + sine * bTemp[0].x;
bFinal[1].x = cosine * bTemp[1].x - sine * bTemp[1].y;
bFinal[1].y = cosine * bTemp[1].y + sine * bTemp[1].x;
// update balls to screen position
b[1].x = b[0].x + bFinal[1].x;
b[1].y = b[0].y + bFinal[1].y;
b[0].x = b[0].x + bFinal[0].x;
b[0].y = b[0].y + bFinal[0].y;
// update velocities
v[0].x = cosine * vFinal[0].x - sine * vFinal[0].y;
v[0].y = cosine * vFinal[0].y + sine * vFinal[0].x;
v[1].x = cosine * vFinal[1].x - sine * vFinal[1].y;
v[1].y = cosine * vFinal[1].y + sine * vFinal[1].x;
}
}
void checkBoundaryCollision(Ball ball, PVector vel) {
if (ball.x > width-ball.r) {
ball.x = width-ball.r;
vel.x *= -1;
}
else if (ball.x < ball.r) {
ball.x = ball.r;
vel.x *= -1;
}
else if (ball.y > height-ball.r) {
ball.y = height-ball.r;
vel.y *= -1;
}
else if (ball.y < ball.r) {
ball.y = ball.r;
vel.y *= -1;
}
}
@@ -0,0 +1,85 @@
/**
* Collision (Pong).
*
* Move the mouse up and down to move the paddle.
*/
// Global variables for the ball
float ball_x;
float ball_y;
float ball_dir = 1;
float ball_size = 15; // Radius
float dy = 0; // Direction
// Global variables for the paddle
int paddle_width = 10;
int paddle_height = 60;
int dist_wall = 15;
void setup()
{
size(640, 360);
rectMode(RADIUS);
ellipseMode(RADIUS);
noStroke();
smooth();
ball_y = height/2;
ball_x = 1;
}
void draw()
{
background(51);
ball_x += ball_dir * 1.0;
ball_y += dy;
if(ball_x > width+ball_size) {
ball_x = -width/2 - ball_size;
ball_y = random(0, height);
dy = 0;
}
// Constrain paddle to screen
float paddle_y = constrain(mouseY, paddle_height, height-paddle_height);
// Test to see if the ball is touching the paddle
float py = width-dist_wall-paddle_width-ball_size;
if(ball_x == py
&& ball_y > paddle_y - paddle_height - ball_size
&& ball_y < paddle_y + paddle_height + ball_size) {
ball_dir *= -1;
if(mouseY != pmouseY) {
dy = (mouseY-pmouseY)/2.0;
if(dy > 5) { dy = 5; }
if(dy < -5) { dy = -5; }
}
}
// If ball hits paddle or back wall, reverse direction
if(ball_x < ball_size && ball_dir == -1) {
ball_dir *= -1;
}
// If the ball is touching top or bottom edge, reverse direction
if(ball_y > height-ball_size) {
dy = dy * -1;
}
if(ball_y < ball_size) {
dy = dy * -1;
}
// Draw ball
fill(255);
ellipse(ball_x, ball_y, ball_size, ball_size);
// Draw the paddle
fill(153);
rect(width-dist_wall, paddle_y, paddle_width, paddle_height);
}
@@ -0,0 +1,26 @@
/**
* Linear Motion.
*
* Changing a variable to create a moving line.
* When the line moves off the edge of the window,
* the variable is set to 0, which places the line
* back at the bottom of the screen.
*/
float a = 100;
void setup()
{
size(640, 200);
stroke(255);
}
void draw()
{
background(51);
a = a - 0.5;
if (a < 0) {
a = height;
}
line(0, a, width, a);
}
@@ -0,0 +1,50 @@
/**
* Moving On Curves.
*
* In this example, the circles moves along the curve y = x^4.
* Click the mouse to have it move to a new position.
*/
float beginX = 20.0; // Initial x-coordinate
float beginY = 10.0; // Initial y-coordinate
float endX = 570.0; // Final x-coordinate
float endY = 320.0; // Final y-coordinate
float distX; // X-axis distance to move
float distY; // Y-axis distance to move
float exponent = 4; // Determines the curve
float x = 0.0; // Current x-coordinate
float y = 0.0; // Current y-coordinate
float step = 0.01; // Size of each step along the path
float pct = 0.0; // Percentage traveled (0.0 to 1.0)
void setup()
{
size(640, 360);
noStroke();
smooth();
distX = endX - beginX;
distY = endY - beginY;
}
void draw()
{
fill(0, 2);
rect(0, 0, width, height);
pct += step;
if (pct < 1.0) {
x = beginX + (pct * distX);
y = beginY + (pow(pct, exponent) * distY);
}
fill(255);
ellipse(x, y, 20, 20);
}
void mousePressed() {
pct = 0.0;
beginX = x;
beginY = y;
endX = mouseX;
endY = mouseY;
distX = endX - beginX;
distY = endY - beginY;
}
+91
View File
@@ -0,0 +1,91 @@
/**
* Puff
* by Ira Greenberg.
*
* Series of ellipses simulating a multi-segmented
* organism, utilizing a follow the leader algorithm.
* Collision detection occurs on the organism's head,
* controlling overall direction, and on the individual
* body segments, controlling body shape and jitter.
*/
// For puff head
float headX;
float headY;
float speedX = .7;
float speedY = .9;
// For puff body
int cells = 1000;
float[]px= new float[cells];
float[]py= new float[cells];
float[]radiiX = new float[cells];
float[]radiiY = new float[cells];
float[]angle = new float[cells];
float[]frequency = new float[cells];
float[]cellRadius = new float[cells];
void setup(){
size(640, 360);
// Begin in the center
headX = width/2;
headY = height/2;
// Fill body arrays
for (int i=0; i< cells; i++){
radiiX[i] = random(-7, 7);
radiiY[i] = random(-4, 4);
frequency[i]= random(-9, 9);
cellRadius[i] = random(16, 30);
}
frameRate(30);
}
void draw(){
background(0);
noStroke();
fill(255, 255, 255, 5);
// Follow the leader
for (int i =0; i< cells; i++){
if (i==0){
px[i] = headX+sin(radians(angle[i]))*radiiX[i];
py[i] = headY+cos(radians(angle[i]))*radiiY[i];
}
else{
px[i] = px[i-1]+cos(radians(angle[i]))*radiiX[i];
py[i] = py[i-1]+sin(radians(angle[i]))*radiiY[i];
// Check collision of body
if (px[i] >= width-cellRadius[i]/2 || px[i] <= cellRadius[i]/2){
radiiX[i]*=-1;
cellRadius[i] = random(1, 40);
frequency[i]= random(-13, 13);
}
if (py[i] >= height-cellRadius[i]/2 || py[i] <= cellRadius[i]/2){
radiiY[i]*=-1;
cellRadius[i] = random(1, 40);
frequency[i]= random(-9, 9);
}
}
// Draw puff
ellipse(px[i], py[i], cellRadius[i], cellRadius[i]);
// Set speed of body
angle[i]+=frequency[i];
}
// Set velocity of head
headX+=speedX;
headY+=speedY;
// Check boundary collision of head
if (headX >= width-cellRadius[0]/2 || headX <=cellRadius[0]/2){
speedX*=-1;
}
if (headY >= height-cellRadius[0]/2 || headY <= cellRadius[0]/2){
speedY*=-1;
}
}
@@ -0,0 +1,129 @@
/**
* Non-orthogonal Reflection
* by Ira Greenberg.
*
* Based on the equation (R = 2N(N*L)-L) where R is the
* reflection vector, N is the normal, and L is the incident
* vector.
*/
float baseX1, baseY1, baseX2, baseY2;
float baseLength;
float[] xCoords, yCoords;
float ellipseX, ellipseY, ellipseRadius = 6;
float directionX, directionY;
float ellipseSpeed = 3.5;
float velocityX, velocityY;
void setup(){
size(640, 240);
frameRate(30);
fill(128);
smooth();
baseX1 = 0;
baseY1 = height-150;
baseX2 = width;
baseY2 = height;
// start ellipse at middle top of screen
ellipseX = width/2;
// calculate initial random direction
directionX = random(0.1, 0.99);
directionY = random(0.1, 0.99);
// normalize direction vector
float directionVectLength = sqrt(directionX*directionX +
directionY*directionY);
directionX /= directionVectLength;
directionY /= directionVectLength;
}
void draw(){
// draw background
fill(0, 12);
noStroke();
rect(0, 0, width, height);
// calculate length of base top
baseLength = dist(baseX1, baseY1, baseX2, baseY2);
xCoords = new float[ceil(baseLength)];
yCoords = new float[ceil(baseLength)];
// fill base top coordinate array
for (int i=0; i<xCoords.length; i++){
xCoords[i] = baseX1 + ((baseX2-baseX1)/baseLength)*i;
yCoords[i] = baseY1 + ((baseY2-baseY1)/baseLength)*i;
}
// draw base
fill(200);
quad(baseX1, baseY1, baseX2, baseY2, baseX2, height, 0, height);
// calculate base top normal
float baseDeltaX = (baseX2-baseX1)/baseLength;
float baseDeltaY = (baseY2-baseY1)/baseLength;
float normalX = -baseDeltaY;
float normalY = baseDeltaX;
// draw ellipse
noStroke();
fill(255);
ellipse(ellipseX, ellipseY, ellipseRadius*2, ellipseRadius*2);
// calculate ellipse velocity
velocityX = directionX * ellipseSpeed;
velocityY = directionY * ellipseSpeed;
// move elipse
ellipseX += velocityX;
ellipseY += velocityY;
// normalized incidence vector
float incidenceVectorX = -directionX;
float incidenceVectorY = -directionY;
// detect and handle collision
for (int i=0; i<xCoords.length; i++){
// check distance between ellipse and base top coordinates
if (dist(ellipseX, ellipseY, xCoords[i], yCoords[i]) < ellipseRadius){
// calculate dot product of incident vector and base top normal
float dot = incidenceVectorX*normalX + incidenceVectorY*normalY;
// calculate reflection vector
float reflectionVectorX = 2*normalX*dot - incidenceVectorX;
float reflectionVectorY = 2*normalY*dot - incidenceVectorY;
// assign reflection vector to direction vector
directionX = reflectionVectorX;
directionY = reflectionVectorY;
// draw base top normal at collision point
stroke(255, 128, 0);
line(ellipseX, ellipseY, ellipseX-normalX*100,
ellipseY-normalY*100);
}
}
// detect boundary collision
// right
if (ellipseX > width-ellipseRadius){
ellipseX = width-ellipseRadius;
directionX *= -1;
}
// left
if (ellipseX < ellipseRadius){
ellipseX = ellipseRadius;
directionX *= -1;
}
// top
if (ellipseY < ellipseRadius){
ellipseY = ellipseRadius;
directionY *= -1;
// randomize base top
baseY1 = random(height-100, height);
baseY2 = random(height-100, height);
}
}
@@ -0,0 +1,20 @@
class Ground {
float x1, y1, x2, y2;
float x, y, len, rot;
// Default constructor
Ground(){
}
// Constructor
Ground(float x1, float y1, float x2, float y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
x = (x1+x2)/2;
y = (y1+y2)/2;
len = dist(x1, y1, x2, y2);
rot = atan2((y2-y1), (x2-x1));
}
}
@@ -0,0 +1,14 @@
class Orb{
float x, y, r;
// Default constructor
Orb() {
}
Orb(float x, float y, float r) {
this.x = x;
this.y = y;
this.r = r;
}
}
@@ -0,0 +1,128 @@
/**
* Non-orthogonal Collision with Multiple Ground Segments
* by Ira Greenberg.
*
* Based on Keith Peter's Solution in
* Foundation Actionscript Animation: Making Things Move!
*/
Orb orb;
PVector velocity;
float gravity = .05, damping = 0.8;
int segments = 40;
Ground[] ground = new Ground[segments];
float[] peakHeights = new float[segments+1];
void setup(){
size(640, 200);
smooth();
orb = new Orb(50, 50, 3);
velocity = new PVector(.5, 0);
// Calculate ground peak heights
for (int i=0; i<peakHeights.length; i++){
peakHeights[i] = random(height-40, height-30);
}
/* Float value required for segment width (segs)
calculations so the ground spans the entire
display window, regardless of segment number. */
float segs = segments;
for (int i=0; i<segments; i++){
ground[i] = new Ground(width/segs*i, peakHeights[i],
width/segs*(i+1), peakHeights[i+1]);
}
}
void draw(){
// Background
noStroke();
fill(0, 15);
rect(0, 0, width, height);
// Move orb
orb.x += velocity.x;
velocity.y += gravity;
orb.y += velocity.y;
// Draw ground
fill(127);
beginShape();
for (int i=0; i<segments; i++){
vertex(ground[i].x1, ground[i].y1);
vertex(ground[i].x2, ground[i].y2);
}
vertex(ground[segments-1].x2, height);
vertex(ground[0].x1, height);
endShape(CLOSE);
// Draw orb
noStroke();
fill(200);
ellipse(orb.x, orb.y, orb.r*2, orb.r*2);
// Collision detection
checkWallCollision();
for (int i=0; i<segments; i++){
checkGroundCollision(ground[i]);
}
}
void checkWallCollision(){
if (orb.x > width-orb.r){
orb.x = width-orb.r;
velocity.x *= -1;
velocity.x *= damping;
}
else if (orb.x < orb.r){
orb.x = orb.r;
velocity.x *= -1;
velocity.x *= damping;
}
}
void checkGroundCollision(Ground groundSegment) {
// Get difference between orb and ground
float deltaX = orb.x - groundSegment.x;
float deltaY = orb.y - groundSegment.y;
// Precalculate trig values
float cosine = cos(groundSegment.rot);
float sine = sin(groundSegment.rot);
/* Rotate ground and velocity to allow
orthogonal collision calculations */
float groundXTemp = cosine * deltaX + sine * deltaY;
float groundYTemp = cosine * deltaY - sine * deltaX;
float velocityXTemp = cosine * velocity.x + sine * velocity.y;
float velocityYTemp = cosine * velocity.y - sine * velocity.x;
/* Ground collision - check for surface
collision and also that orb is within
left/rights bounds of ground segment */
if (groundYTemp > -orb.r &&
orb.x > groundSegment.x1 &&
orb.x < groundSegment.x2 ){
// keep orb from going into ground
groundYTemp = -orb.r;
// bounce and slow down orb
velocityYTemp *= -1.0;
velocityYTemp *= damping;
}
// Reset ground, velocity and orb
deltaX = cosine * groundXTemp - sine * groundYTemp;
deltaY = cosine * groundYTemp + sine * groundXTemp;
velocity.x = cosine * velocityXTemp - sine * velocityYTemp;
velocity.y = cosine * velocityYTemp + sine * velocityXTemp;
orb.x = groundSegment.x + deltaX;
orb.y = groundSegment.y + deltaY;
}