Initial Commit

This commit is contained in:
plane000
2018-04-20 10:15:15 +01:00
parent 49150ccfe4
commit 62101e8e61
2870 changed files with 520122 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
/**
* Bounce.
*
* When the shape hits the edge of the window, it reverses its direction.
*/
int rad = 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, 360);
noStroke();
frameRate(30);
ellipseMode(RADIUS);
// 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-rad || xpos < rad) {
xdirection *= -1;
}
if (ypos > height-rad || ypos < rad) {
ydirection *= -1;
}
// Draw the shape
ellipse(xpos, ypos, rad, rad);
}

View File

@@ -0,0 +1,95 @@
/**
* Bouncy Bubbles
* based on code from Keith Peters.
*
* 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, 360);
for (int i = 0; i < numBalls; i++) {
balls[i] = new Ball(random(width), random(height), random(30, 70), i, balls);
}
noStroke();
fill(255, 204);
}
void draw() {
background(0);
for (Ball ball : balls) {
ball.collide();
ball.move();
ball.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() {
ellipse(x, y, diameter, diameter);
}
}

View File

@@ -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]);
}
}

View File

@@ -0,0 +1,135 @@
class Ball {
PVector position;
PVector velocity;
float radius, m;
Ball(float x, float y, float r_) {
position = new PVector(x, y);
velocity = PVector.random2D();
velocity.mult(3);
radius = r_;
m = radius*.1;
}
void update() {
position.add(velocity);
}
void checkBoundaryCollision() {
if (position.x > width-radius) {
position.x = width-radius;
velocity.x *= -1;
} else if (position.x < radius) {
position.x = radius;
velocity.x *= -1;
} else if (position.y > height-radius) {
position.y = height-radius;
velocity.y *= -1;
} else if (position.y < radius) {
position.y = radius;
velocity.y *= -1;
}
}
void checkCollision(Ball other) {
// Get distances between the balls components
PVector distanceVect = PVector.sub(other.position, position);
// Calculate magnitude of the vector separating the balls
float distanceVectMag = distanceVect.mag();
// Minimum distance before they are touching
float minDistance = radius + other.radius;
if (distanceVectMag < minDistance) {
float distanceCorrection = (minDistance-distanceVectMag)/2.0;
PVector d = distanceVect.copy();
PVector correctionVector = d.normalize().mult(distanceCorrection);
other.position.add(correctionVector);
position.sub(correctionVector);
// get angle of distanceVect
float theta = distanceVect.heading();
// 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*/
PVector[] bTemp = {
new PVector(), new PVector()
};
/* this ball's position is relative to the other
so you can use the vector between them (bVect) as the
reference point in the rotation expressions.
bTemp[0].position.x and bTemp[0].position.y will initialize
automatically to 0.0, which is what you want
since b[1] will rotate around b[0] */
bTemp[1].x = cosine * distanceVect.x + sine * distanceVect.y;
bTemp[1].y = cosine * distanceVect.y - sine * distanceVect.x;
// rotate Temporary velocities
PVector[] vTemp = {
new PVector(), new PVector()
};
vTemp[0].x = cosine * velocity.x + sine * velocity.y;
vTemp[0].y = cosine * velocity.y - sine * velocity.x;
vTemp[1].x = cosine * other.velocity.x + sine * other.velocity.y;
vTemp[1].y = cosine * other.velocity.y - sine * other.velocity.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 = ((m - other.m) * vTemp[0].x + 2 * other.m * vTemp[1].x) / (m + other.m);
vFinal[0].y = vTemp[0].y;
// final rotated velocity for b[0]
vFinal[1].x = ((other.m - m) * vTemp[1].x + 2 * m * vTemp[0].x) / (m + other.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
PVector[] bFinal = {
new PVector(), new PVector()
};
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
other.position.x = position.x + bFinal[1].x;
other.position.y = position.y + bFinal[1].y;
position.add(bFinal[0]);
// update velocities
velocity.x = cosine * vFinal[0].x - sine * vFinal[0].y;
velocity.y = cosine * vFinal[0].y + sine * vFinal[0].x;
other.velocity.x = cosine * vFinal[1].x - sine * vFinal[1].y;
other.velocity.y = cosine * vFinal[1].y + sine * vFinal[1].x;
}
}
void display() {
noStroke();
fill(204);
ellipse(position.x, position.y, radius*2, radius*2);
}
}

View File

@@ -0,0 +1,32 @@
/**
* 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)
};
void setup() {
size(640, 360);
}
void draw() {
background(51);
for (Ball b : balls) {
b.update();
b.display();
b.checkBoundaryCollision();
}
balls[0].checkCollision(balls[1]);
}

View File

@@ -0,0 +1,114 @@
// Custom Cube Class
class Cube {
// Position, velocity vectors
PVector position;
PVector velocity;
// Also using PVector to hold rotation values for 3 axes
PVector rotation;
// Vertices of the cube
PVector[] vertices = new PVector[24];
// width, height, depth
float w, h, d;
// colors for faces of cube
color[] quadBG = new color[6];
Cube(float w, float h, float d) {
this.w = w;
this.h = h;
this.d = d;
// Colors are hardcoded
quadBG[0] = color(0);
quadBG[1] = color(51);
quadBG[2] = color(102);
quadBG[3] = color(153);
quadBG[4] = color(204);
quadBG[5] = color(255);
// Start in center
position = new PVector();
// Random velocity vector
velocity = PVector.random3D();
// Random rotation
rotation = new PVector(random(40, 100), random(40, 100), random(40, 100));
// cube composed of 6 quads
//front
vertices[0] = new PVector(-w/2, -h/2, d/2);
vertices[1] = new PVector(w/2, -h/2, d/2);
vertices[2] = new PVector(w/2, h/2, d/2);
vertices[3] = new PVector(-w/2, h/2, d/2);
//left
vertices[4] = new PVector(-w/2, -h/2, d/2);
vertices[5] = new PVector(-w/2, -h/2, -d/2);
vertices[6] = new PVector(-w/2, h/2, -d/2);
vertices[7] = new PVector(-w/2, h/2, d/2);
//right
vertices[8] = new PVector(w/2, -h/2, d/2);
vertices[9] = new PVector(w/2, -h/2, -d/2);
vertices[10] = new PVector(w/2, h/2, -d/2);
vertices[11] = new PVector(w/2, h/2, d/2);
//back
vertices[12] = new PVector(-w/2, -h/2, -d/2);
vertices[13] = new PVector(w/2, -h/2, -d/2);
vertices[14] = new PVector(w/2, h/2, -d/2);
vertices[15] = new PVector(-w/2, h/2, -d/2);
//top
vertices[16] = new PVector(-w/2, -h/2, d/2);
vertices[17] = new PVector(-w/2, -h/2, -d/2);
vertices[18] = new PVector(w/2, -h/2, -d/2);
vertices[19] = new PVector(w/2, -h/2, d/2);
//bottom
vertices[20] = new PVector(-w/2, h/2, d/2);
vertices[21] = new PVector(-w/2, h/2, -d/2);
vertices[22] = new PVector(w/2, h/2, -d/2);
vertices[23] = new PVector(w/2, h/2, d/2);
}
// Cube shape itself
void drawCube() {
// Draw cube
for (int i=0; i<6; i++) {
fill(quadBG[i]);
beginShape(QUADS);
for (int j=0; j<4; j++) {
vertex(vertices[j+4*i].x, vertices[j+4*i].y, vertices[j+4*i].z);
}
endShape();
}
}
// Update location
void update() {
position.add(velocity);
// Check wall collisions
if (position.x > bounds/2 || position.x < -bounds/2) {
velocity.x*=-1;
}
if (position.y > bounds/2 || position.y < -bounds/2) {
velocity.y*=-1;
}
if (position.z > bounds/2 || position.z < -bounds/2) {
velocity.z*=-1;
}
}
// Display method
void display() {
pushMatrix();
translate(position.x, position.y, position.z);
rotateX(frameCount*PI/rotation.x);
rotateY(frameCount*PI/rotation.y);
rotateZ(frameCount*PI/rotation.z);
noStroke();
drawCube(); // Farm out shape to another method
popMatrix();
}
}

View File

@@ -0,0 +1,50 @@
/**
* Cubes Contained Within a Cube
* by Ira Greenberg.
*
* Collision detection against all
* outer cube's surfaces.
*/
// 20 little internal cubes
Cube[] cubies = new Cube[20];
// Size of outer cube
float bounds = 300;
void setup() {
size(640, 360, P3D);
for (int i = 0; i < cubies.length; i++) {
// Cubies are randomly sized
float cubieSize = random(5, 15);
cubies[i] = new Cube(cubieSize, cubieSize, cubieSize);
}
}
void draw() {
background(50);
lights();
// Center in display window
translate(width/2, height/2, -130);
// Rotate everything, including external large cube
rotateX(frameCount * 0.001);
rotateY(frameCount * 0.002);
rotateZ(frameCount * 0.001);
stroke(255);
// Outer transparent cube, just using box() method
noFill();
box(bounds);
// Move and rotate cubies
for (Cube c : cubies) {
c.update();
c.display();
}
}

View File

@@ -0,0 +1,25 @@
/**
* 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;
void setup() {
size(640, 360);
stroke(255);
a = height/2;
}
void draw() {
background(51);
line(0, a, width, a);
a = a - 0.5;
if (a < 0) {
a = height;
}
}

View File

@@ -0,0 +1,95 @@
/**
* Morph.
*
* Changing one shape into another by interpolating
* vertices from one to another
*/
// Two ArrayLists to store the vertices for two shapes
// This example assumes that each shape will have the same
// number of vertices, i.e. the size of each ArrayList will be the same
ArrayList<PVector> circle = new ArrayList<PVector>();
ArrayList<PVector> square = new ArrayList<PVector>();
// An ArrayList for a third set of vertices, the ones we will be drawing
// in the window
ArrayList<PVector> morph = new ArrayList<PVector>();
// This boolean variable will control if we are morphing to a circle or square
boolean state = false;
void setup() {
size(640, 360);
// Create a circle using vectors pointing from center
for (int angle = 0; angle < 360; angle += 9) {
// Note we are not starting from 0 in order to match the
// path of a circle.
PVector v = PVector.fromAngle(radians(angle-135));
v.mult(100);
circle.add(v);
// Let's fill out morph ArrayList with blank PVectors while we are at it
morph.add(new PVector());
}
// A square is a bunch of vertices along straight lines
// Top of square
for (int x = -50; x < 50; x += 10) {
square.add(new PVector(x, -50));
}
// Right side
for (int y = -50; y < 50; y += 10) {
square.add(new PVector(50, y));
}
// Bottom
for (int x = 50; x > -50; x -= 10) {
square.add(new PVector(x, 50));
}
// Left side
for (int y = 50; y > -50; y -= 10) {
square.add(new PVector(-50, y));
}
}
void draw() {
background(51);
// We will keep how far the vertices are from their target
float totalDistance = 0;
// Look at each vertex
for (int i = 0; i < circle.size(); i++) {
PVector v1;
// Are we lerping to the circle or square?
if (state) {
v1 = circle.get(i);
}
else {
v1 = square.get(i);
}
// Get the vertex we will draw
PVector v2 = morph.get(i);
// Lerp to the target
v2.lerp(v1, 0.1);
// Check how far we are from target
totalDistance += PVector.dist(v1, v2);
}
// If all the vertices are close, switch shape
if (totalDistance < 0.1) {
state = !state;
}
// Draw relative to center
translate(width/2, height/2);
strokeWeight(4);
// Draw a polygon that makes up all the vertices
beginShape();
noFill();
stroke(255);
for (PVector v : morph) {
vertex(v.x, v.y);
}
endShape(CLOSE);
}

View File

@@ -0,0 +1,47 @@
/**
* 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();
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;
}

View File

@@ -0,0 +1,124 @@
/**
* 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.
*/
// Position of left hand side of floor
PVector base1;
// Position of right hand side of floor
PVector base2;
// Length of floor
float baseLength;
// An array of subpoints along the floor path
PVector[] coords;
// Variables related to moving ball
PVector position;
PVector velocity;
float r = 6;
float speed = 3.5;
void setup() {
size(640, 360);
fill(128);
base1 = new PVector(0, height-150);
base2 = new PVector(width, height);
createGround();
// start ellipse at middle top of screen
position = new PVector(width/2, 0);
// calculate initial random velocity
velocity = PVector.random2D();
velocity.mult(speed);
}
void draw() {
// draw background
fill(0, 12);
noStroke();
rect(0, 0, width, height);
// draw base
fill(200);
quad(base1.x, base1.y, base2.x, base2.y, base2.x, height, 0, height);
// calculate base top normal
PVector baseDelta = PVector.sub(base2, base1);
baseDelta.normalize();
PVector normal = new PVector(-baseDelta.y, baseDelta.x);
// draw ellipse
noStroke();
fill(255);
ellipse(position.x, position.y, r*2, r*2);
// move elipse
position.add(velocity);
// normalized incidence vector
PVector incidence = PVector.mult(velocity, -1);
incidence.normalize();
// detect and handle collision
for (int i=0; i<coords.length; i++) {
// check distance between ellipse and base top coordinates
if (PVector.dist(position, coords[i]) < r) {
// calculate dot product of incident vector and base top normal
float dot = incidence.dot(normal);
// calculate reflection vector
// assign reflection vector to direction vector
velocity.set(2*normal.x*dot - incidence.x, 2*normal.y*dot - incidence.y, 0);
velocity.mult(speed);
// draw base top normal at collision point
stroke(255, 128, 0);
line(position.x, position.y, position.x-normal.x*100, position.y-normal.y*100);
}
}
// detect boundary collision
// right
if (position.x > width-r) {
position.x = width-r;
velocity.x *= -1;
}
// left
if (position.x < r) {
position.x = r;
velocity.x *= -1;
}
// top
if (position.y < r) {
position.y = r;
velocity.y *= -1;
// randomize base top
base1.y = random(height-100, height);
base2.y = random(height-100, height);
createGround();
}
}
// Calculate variables for the ground
void createGround() {
// calculate length of base top
baseLength = PVector.dist(base1, base2);
// fill base top coordinate array
coords = new PVector[ceil(baseLength)];
for (int i=0; i<coords.length; i++) {
coords[i] = new PVector();
coords[i].x = base1.x + ((base2.x-base1.x)/baseLength)*i;
coords[i].y = base1.y + ((base2.y-base1.y)/baseLength)*i;
}
}

View File

@@ -0,0 +1,16 @@
class Ground {
float x1, y1, x2, y2;
float x, y, len, rot;
// 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));
}
}

View File

@@ -0,0 +1,79 @@
class Orb {
// Orb has positio and velocity
PVector position;
PVector velocity;
float r;
// A damping of 80% slows it down when it hits the ground
float damping = 0.8;
Orb(float x, float y, float r_) {
position = new PVector(x, y);
velocity = new PVector(.5, 0);
r = r_;
}
void move() {
// Move orb
velocity.add(gravity);
position.add(velocity);
}
void display() {
// Draw orb
noStroke();
fill(200);
ellipse(position.x, position.y, r*2, r*2);
}
// Check boundaries of window
void checkWallCollision() {
if (position.x > width-r) {
position.x = width-r;
velocity.x *= -damping;
}
else if (position.x < r) {
position.x = r;
velocity.x *= -damping;
}
}
void checkGroundCollision(Ground groundSegment) {
// Get difference between orb and ground
float deltaX = position.x - groundSegment.x;
float deltaY = position.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 > -r &&
position.x > groundSegment.x1 &&
position.x < groundSegment.x2 ) {
// keep orb from going into ground
groundYTemp = -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;
position.x = groundSegment.x + deltaX;
position.y = groundSegment.y + deltaY;
}
}

View File

@@ -0,0 +1,75 @@
/**
* 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 gravity = new PVector(0,0.05);
// The ground is an array of "Ground" objects
int segments = 40;
Ground[] ground = new Ground[segments];
void setup(){
size(640, 360);
// An orb object that will fall and bounce around
orb = new Orb(50, 50, 3);
// Calculate ground peak heights
float[] peakHeights = new float[segments+1];
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 and display the orb
orb.move();
orb.display();
// Check walls
orb.checkWallCollision();
// Check against all the ground segments
for (int i=0; i<segments; i++){
orb.checkGroundCollision(ground[i]);
}
// 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);
}