Skip to content

Instantly share code, notes, and snippets.

@gncgnc
Last active August 27, 2017 06:08
Show Gist options
  • Save gncgnc/86d3d4e2d99081739d8ab0c27b78da14 to your computer and use it in GitHub Desktop.
Save gncgnc/86d3d4e2d99081739d8ab0c27b78da14 to your computer and use it in GitHub Desktop.
Code for grid-drop
var gif, canvElt,
numFrames = 45,
duration = 1500,
recording = true,
time = 0,
gridW = 10, // number of cells in a row/column
margin = 0.15,
pts = []
;
function setup() {
canvElt = createCanvas(1000, 1000);
ellipseMode(CENTER)
strokeJoin(MITER)
strokeCap(SQUARE)
// generate the data of the grid and its shattered version
var cellW = (1-2*margin)*width / gridW
for (var i = 0; i < gridW+1; i++) {
for (var j = 0; j < gridW+1; j++) {
var x = width*margin + cellW*i,
y = width*margin + cellW*j,
p = {
inix: x,
iniy: y,
// add a random amount to x and y to "shatter" the grid
endx: x + cellW*random(-0.35,0.35),
endy: y + cellW*random(-0.35,0.35)
}
pts[i + j*(gridW+1)] = p
}
}
stroke(255)
noFill()
strokeWeight(width/200)
}
function draw() {
background(0)
time = ((frameCount+numFrames*0.5)%numFrames)/numFrames // goes from 0 to 1 as the gif progresses
// some animation stuff to make it appear like it's falling
var sc = time < 0.4 ?
anim(1, 0.8, quintEaseOut, 0, 0.4) :
anim(0.8, 1, quintEase, 0.6, 1)
translate(width*0.5, height*0.5)
scale(sc)
translate(width*-0.5, height*-0.5)
// animate points to shattered positions
pts.forEach(p => {
p.x = anim(p.inix, p.endx, quintEase, 0.35, 0.5),
p.y = anim(p.iniy, p.endy, quintEase, 0.35, 0.5)
if (time > 0.6) {
p.x = anim(p.endx, p.inix, quintEase, 0.6, 1)
p.y = anim(p.endy, p.iniy, quintEase, 0.6, 1)
}
point(p.x,p.y)
})
// draw the grid with new animated positions
for (var i = 0; i < gridW; i++) {
beginShape(QUAD_STRIP)
for (var j = 0; j < gridW+1; j++) {
var p = pts[i + j*(gridW+1)],
pn = pts[i + j*(gridW+1) + 1]
vertex(p.x, p.y)
vertex(pn.x, pn.y)
}
endShape()
}
// glitch the grid when it's being shattered using the shiftRows function
if (time > 0.45) {
var img = get()
img.loadPixels()
for (var i = 0; i < 40; i++) {
var r = random(height)
shiftRows(img, r, height*random(0.1,0.2), map(time, .35, 1, 1,0) * width*random(-0.03,0.03), random([0,1]))
}
img.updatePixels()
resetMatrix()
image(img,0,0)
}
}
// actually a quad ease, too lazy to change function names lol
var quintEaseOut = function(t) {
return t**2
}
var quintEase = function(t) {
return ease(t,5)
}
// glorified lerp with start and end times, easing; used to animate stuff
function anim(from, to, ease, startTime, endTime) {
// handle inputs
startTime = (typeof startTime === "undefined") ? 0 : startTime;
endTime = (typeof endTime === "undefined") ? 1 : endTime;
ease = ease || function(t) {return t}
// if before start time, return initial value
if (time < startTime) {
return from;
// if after end time, return final value
} else if (time > endTime) {
return to;
// if between start and end time, return lerped and eased value
} else {
// normalize time to be between start and end time
var t = (time - startTime) / (endTime - startTime)
return lerp(from, to, ease(t));
}
}
function shiftRows (im, r0, h, shift, channel) {
var r1 = int(r0 + h); r0 = int(r0); shift = int(shift) // sanitize inputs
// shift the specified "channel" (r,g,b or a) in a span of rows from "r0" to "r1", "shift" number of pixels
for (var i=r0; i<=r1; i++) {
var startInd = 4 * i * im.width + channel,
endInd = 4 * (i+1) * im.width,
row = im.pixels.slice(startInd, endInd)
for (var j=0; j<row.length; j+=4) {
im.pixels[startInd+j] = row[mod(j+shift*4,row.length)]
}
}
}
// mathematical mod, always returns values in range [0, m-1], even for negative values
function mod(n, m) {
return ((n % m) + m) % m;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment