Skip to content

Instantly share code, notes, and snippets.

@somaholiday
Last active May 23, 2021 17:15
Show Gist options
  • Save somaholiday/ad03c9445ac25046ba66dd74b84915be to your computer and use it in GitHub Desktop.
Save somaholiday/ad03c9445ac25046ba66dd74b84915be to your computer and use it in GitHub Desktop.
Seamlessly Looping Art • Code Samples
int rectSize = 100;
void setup() {
size(500, 500);
}
void draw() {
// This will draw a rectangle with a top-left corner where your mouse cursor is.
rect(mouseX, mouseY, rectSize, rectSize);
}
int x = 0;
int y = 0;
int rectSize = 100;
void setup() {
size(500, 500);
}
void draw() {
background(0);
// Draw a rectangle that moves 2 pixels right and down each frame.
rect(x, y, rectSize, rectSize);
x += 2;
y += 2;
}
int x = 0;
int y = 0;
int rectSize = 100;
void setup() {
size(500, 500);
}
void draw() {
background(0);
rect(x, y, rectSize, rectSize);
x += 2;
y += 2;
// This is one way to reset if the rectangle goes off-screen.
/*
if (x > width || y > height) {
x = 0;
y = 0;
}
*/
// This is another, more succinct and expressive way.
// % is the modulo operator
// a % b = the remainder of a / b
x = x % width;
y = y % height;
}
int rectSize = 100;
void setup() {
size(500, 500);
}
void draw() {
background(0);
drawRect(frameCount);
}
void drawRect(int frameNumber) {
int x = (frameNumber * 2) % width;
int y = (frameNumber * 2) % height;
rect(x, y, rectSize, rectSize);
}
int rectSize = 100;
void setup() {
size(500, 500);
/*
note: if you divide an int by an int, you get an int.
*/
int someInteger = 50;
// This returns 0, not 0.5!
println(someInteger / rectSize);
}
void draw() {
background(0);
drawRect(frameCount, 240);
}
/*
note: due to the note above, we are using floats now, rather than ints, because we are working with fractional values
*/
void drawRect(float frameNumber, float totalFramesForLoop) {
// keep loopFrame always between 0 and totalFramesForLoop
float loopFrame = frameNumber % totalFramesForLoop;
// calculate percentage of frames passed of totalFramesForLoop
float normalizedTime = loopFrame / totalFramesForLoop;
float x = normalizedTime * width;
float y = normalizedTime * height;
rect(x, y, rectSize, rectSize);
}
int rectSize = 100;
void setup() {
size(500, 500);
}
void draw() {
background(0);
float normalizedTime = loopNormal(frameCount, 240);
drawRect(normalizedTime);
}
/*
This function calculates how far we are through our total frame count
*/
float loopNormal(float frameNumber, float totalFramesForLoop) {
return (frameNumber % totalFramesForLoop) / totalFramesForLoop;
}
/*
Now our animation function just takes in a value from 0 to 1
*/
void drawRect(float normalizedTime) {
float x = normalizedTime * width;
float y = normalizedTime * height;
rect(x, y, rectSize, rectSize);
}
void setup() {
size(500, 500);
}
void draw() {
background(0);
stroke(255);
//float normalizedTime = loopNormal(frameCount, 240);
drawSine();
}
/*
This function calculates how far we are through our total frame count
*/
float loopNormal(float frameNumber, float totalFramesForLoop) {
return (frameNumber % totalFramesForLoop) / totalFramesForLoop;
}
void drawSine() {
float baseY = height * 0.5;
float amplitude = 100;
// draw X axis
push();
stroke(255, 64);
line(0, baseY, width, baseY);
pop();
for (int x=0; x < width; x++) {
// multiply by amplitude to increase height of wave
// multiply x by 0.1 to increase wavelength of wave
float y = amplitude * sin( x * 0.1 );
point(x, baseY + y);
}
}
void setup() {
size(500, 500);
}
void draw() {
background(0);
stroke(255);
float normalizedTime = loopNormal(frameCount, 240);
drawSine(normalizedTime);
}
/*
This function calculates how far we are through our total frame count
*/
float loopNormal(float frameNumber, float totalFramesForLoop) {
return (frameNumber % totalFramesForLoop) / totalFramesForLoop;
}
void drawSine(float normalizedTime) {
float baseY = height * 0.5;
float amplitude = 100;
// draw X axis
push();
stroke(255, 64);
line(0, baseY, width, baseY);
pop();
float x_offset = normalizedTime * TWO_PI;
for (int x=0; x < width; x++) {
float y = amplitude * sin( x * 0.1 + x_offset );
point(x, baseY + y);
}
}
void setup() {
size(500, 500);
}
void draw() {
background(0);
stroke(255);
float normalizedTime = loopNormal(frameCount, 240);
drawCircle(normalizedTime);
}
/*
This function calculates how far we are through our total frame count
*/
float loopNormal(float frameNumber, float totalFramesForLoop) {
return (frameNumber % totalFramesForLoop) / totalFramesForLoop;
}
void drawCircle(float normalizedTime) {
float x_center = width * 0.5;
float y_center = height * 0.5;
float diameter = width * sin(normalizedTime * TWO_PI);
// note that diameter goes into negative values
// (also note that printing lots of values can slow down your sketch)
println(diameter);
circle(x_center, y_center, diameter);
}
void setup() {
size(500, 500);
}
void draw() {
background(0);
stroke(255);
float normalizedTime = loopNormal(frameCount, 240);
drawCircle(normalizedTime);
}
/*
This function calculates how far we are through our total frame count
*/
float loopNormal(float frameNumber, float totalFramesForLoop) {
return (frameNumber % totalFramesForLoop) / totalFramesForLoop;
}
void drawCircle(float normalizedTime) {
float x_center = width * 0.5;
float y_center = height * 0.5;
// map the output of sin from the range [-1, 1] to [100, 300]
float diameter = map(sin(normalizedTime * TWO_PI), -1, 1, 100, 300);
circle(x_center, y_center, diameter);
}
void setup() {
size(500, 500);
stroke(255);
strokeWeight(2);
}
void draw() {
background(0);
// I'm going to start calling normalizedTime "t"
float t = loopNormal(frameCount, 60);
drawGrid(t);
// draw a red circle on top of the grid
drawTopCircle();
}
/*
This function calculates how far we are through our total frame count
*/
float loopNormal(float frameNumber, float totalFramesForLoop) {
return (frameNumber % totalFramesForLoop) / totalFramesForLoop;
}
void drawGrid(float t) {
int rows = 10;
int cols = rows;
float distance = width/rows;
// draw the vertical lines (note <= rather than < to add last line)
for (int i=0; i <= cols; i++) {
float x = i * distance;
/*
Here's where our loop timing comes in.
We want the lines to move by (distance) pixels
across the duration of the loop.
*/
x -= t * distance;
line(x, 0, x, height);
}
// draw the horizontal lines (note <= rather than < to add last line)
for (int j=0; j <= rows; j++) {
float y = j * distance;
/*
Here's where our loop timing comes in.
We want the lines to move by (distance) pixels
across the duration of the loop.
*/
y += t * distance;
line(0, y, width, y);
}
}
void drawTopCircle() {
/*
push() and pop() allow us to set styles and then reset them.
*/
push();
noStroke();
fill(255, 0, 0);
circle(width * 0.5, height * 0.5, 200);
/*
When we call pop(), the styles will return to what they were
at the last time push() was called.
*/
pop();
}
void setup() {
size(500, 500);
noStroke();
fill(255);
}
void draw() {
background(0);
// I'm going to start calling normalizedTime "t"
float t = loopNormal(frameCount, 120);
drawCircles(t);
}
/*
This function calculates how far we are through our total frame count
*/
float loopNormal(float frameNumber, float totalFramesForLoop) {
return (frameNumber % totalFramesForLoop) / totalFramesForLoop;
}
void drawCircles(float t) {
int rows = 5;
int cols = rows;
float diameter = width/rows;
for (int i=0; i < cols; i++) {
float x = i * diameter + diameter * 0.5;
/* Note that we start from -1 to have an extra row that comes in from the top */
for (int j=-1; j < rows; j++) {
float y = j * diameter + diameter * 0.5;
/*
Here's where our loop timing comes in.
We want the circles to move by (diameter) pixels
across the duration of the loop.
*/
float y_offset = t * diameter;
ellipse(x, y + y_offset, diameter, diameter);
}
}
}
void setup() {
size(500, 500);
noStroke();
fill(255);
}
void draw() {
background(0);
float t = loopNormal(frameCount, 120);
drawCircles(t);
}
/*
This function calculates how far we are through our total frame count
*/
float loopNormal(float frameNumber, float totalFramesForLoop) {
return (frameNumber % totalFramesForLoop) / totalFramesForLoop;
}
void drawCircles(float t) {
int rows = 10;
int cols = rows;
float diameter = width/rows;
for (int i=0; i < cols; i++) {
float x = i * diameter + diameter * 0.5;
for (int j=0; j < rows; j++) {
float y = j * diameter + diameter * 0.5;
// First we decide what should contribute to the offset of the sine wave
float sin_offset = x + y;
// Then add that offset to a wave that we know will complete one cycle in our loop
float sin_value = sin(t * TWO_PI + sin_offset);
// Then map the output to the parameter we want to modulate.
float draw_diameter = map(sin_value, -1, 1, 0, diameter);
ellipse(x, y, draw_diameter, draw_diameter);
}
}
}
void setup() {
size(500, 500);
noStroke();
}
void draw() {
background(0);
float t = loopNormal(frameCount, 120);
drawRing(t);
}
/*
This function calculates how far we are through our total frame count
*/
float loopNormal(float frameNumber, float totalFramesForLoop) {
return (frameNumber % totalFramesForLoop) / totalFramesForLoop;
}
void drawRing(float t) {
int circle_count = 12;
float ring_radius = 150;
float circle_diameter = 50;
// push() and pop() work for translate() too!
push();
/*
translate() changes the origin of our coordinate system
This call has the effect of moving (0, 0) to the center of our sketch
*/
translate(width * 0.5, height * 0.5);
for (int i=0; i < circle_count; i++) {
// distribute the circle number evenly across the range [0, TWO_PI]
float angle = map(i, 0, circle_count, 0, TWO_PI);
// remember when we looked at that sin/cos visualization?
// https://jackschaedler.github.io/circles-sines-signals/sincos.html
float x = cos(angle) * ring_radius;
float y = sin(angle) * ring_radius;
// First we decide what should contribute to the offset of the sine wave
float sin_offset = angle;
// Then add that offset to a wave that we know will complete one cycle in our loop
float sin_value = sin(t * TWO_PI + sin_offset);
// Then map the output to the parameter we want to modulate.
float draw_diameter = map(sin_value, -1, 1, 0, circle_diameter);
circle(x, y, draw_diameter);
}
// after we call pop(), (0, 0) will move back to the top-left corner
pop();
}
void setup() {
size(500, 500);
noStroke();
}
void draw() {
background(255, 0, 0);
float t = loopNormal(frameCount, 120);
drawFadingCircle(t);
}
/*
This function calculates how far we are through our total frame count
*/
float loopNormal(float frameNumber, float totalFramesForLoop) {
return (frameNumber % totalFramesForLoop) / totalFramesForLoop;
}
void drawFadingCircle(float t) {
// use push() and pop() to keep style changes isolated
push();
float sin_value = sin(t * TWO_PI);
// map the sin value to the range for colors
float fill_value = map(sin_value, -1, 1, 0, 255);
// set the fill to the mapped color
fill(fill_value);
circle(width * 0.5, height * 0.5, 200);
pop();
}
void setup() {
size(500, 500);
noStroke();
}
void draw() {
background(255, 0, 0);
float t = loopNormal(frameCount, 120);
drawFadingCircle(t);
}
/*
This function calculates how far we are through our total frame count
*/
float loopNormal(float frameNumber, float totalFramesForLoop) {
return (frameNumber % totalFramesForLoop) / totalFramesForLoop;
}
/*
We use this so much, it's worth having a utility function for it.
*/
float mapsin(float value, float start, float stop) {
return map(sin(value), -1, 1, start, stop);
}
void drawFadingCircle(float t) {
// use push() and pop() to keep style changes isolated
push();
// map the sin value to the range for colors
float fill_value = mapsin(t * TWO_PI, 0, 255);
// set the fill to the mapped color
fill(fill_value);
circle(width * 0.5, height * 0.5, 200);
pop();
}
color red = color(255, 0, 0);
color green = color(0, 255, 0);
void setup() {
size(500, 500);
noStroke();
}
void draw() {
background(0, 0, 255);
float t = loopNormal(frameCount, 120);
drawFadingCircle(t);
}
/*
This function calculates how far we are through our total frame count
*/
float loopNormal(float frameNumber, float totalFramesForLoop) {
return (frameNumber % totalFramesForLoop) / totalFramesForLoop;
}
/*
We use this so much, it's worth having a utility function for it.
*/
float mapsin(float value, float start, float stop) {
return map(sin(value), -1, 1, start, stop);
}
void drawFadingCircle(float t) {
// use push() and pop() to keep style changes isolated
push();
float sin_value = sin(t * TWO_PI);
// this value will range from 0 to 1
float normalized_value = norm(sin_value, -1, 1);
// interpolate the color based on normalized_value
color lerpedColor = lerpColor(red, green, normalized_value);
// set the fill to the lerp color
fill(lerpedColor);
circle(width * 0.5, height * 0.5, 200);
pop();
}
/*
NOTE: these colors will still be RGB,
because they are defined before we call colorMode()
*/
color red = color(255, 0, 0);
color green = color(0, 255, 0);
void setup() {
size(500, 500);
noStroke();
colorMode(HSB, 1.0);
}
void draw() {
background(0);
float t = loopNormal(frameCount, 120);
drawRainbowCircle(t);
}
/*
This function calculates how far we are through our total frame count
*/
float loopNormal(float frameNumber, float totalFramesForLoop) {
return (frameNumber % totalFramesForLoop) / totalFramesForLoop;
}
/*
We use this so much, it's worth having a utility function for it.
*/
float mapsin(float value, float start, float stop) {
return map(sin(value), -1, 1, start, stop);
}
void drawRainbowCircle(float t) {
// use push() and pop() to keep style changes isolated
push();
// choose the hue based on t
// keep saturation and brightness at full
color hsbColor = color(t, 1, 1);
// set the fill
fill(hsbColor);
circle(width * 0.5, height * 0.5, 200);
pop();
}
// Generate a random number between 1000 and 10000 to mix up the noise motion
float noiseSeed = random(1000, 10000);
void setup() {
size(500, 500);
noStroke();
}
void draw() {
background(0);
float t = loopNormal(frameCount, 480);
drawNervousCircle(t);
}
/*
This function calculates how far we are through our total frame count
*/
float loopNormal(float frameNumber, float totalFramesForLoop) {
return (frameNumber % totalFramesForLoop) / totalFramesForLoop;
}
/*
We use this so much, it's worth having a utility function for it.
*/
float mapsin(float value, float start, float stop) {
return map(sin(value), -1, 1, start, stop);
}
void drawNervousCircle(float t) {
push();
float base_x = width * 0.5;
float base_y = height * 0.5;
/*
We're drawing a circle around the noise space,
so at the end of our loop, our noise offset is the same
as it was when started.
*/
float noise_input_x = cos(t * TWO_PI);
float noise_input_y = sin(t * TWO_PI);
float x_offset = noise(noise_input_x, noise_input_y);
// We add a random noiseSeed to move to a different part of the noise space
float y_offset = noise(noiseSeed + noise_input_x, noiseSeed + noise_input_y);
// Remap the noise offsets from [0, 1] to [-100, 100]
x_offset = map(x_offset, 0, 1, -100, 100);
y_offset = map(y_offset, 0, 1, -100, 100);
/*
Uncomment this line to offset by a sine wave instead
and compare the motions.
*/
//x_offset = 0;
//y_offset = mapsin(t * TWO_PI, -100, 100);
circle(base_x + x_offset, base_y + y_offset, 200);
pop();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment