Skip to content

Instantly share code, notes, and snippets.

@KrabCode
Last active December 3, 2017 22:57
Show Gist options
  • Select an option

  • Save KrabCode/0f42a8934f71bbc1a5d8fe6b45176031 to your computer and use it in GitHub Desktop.

Select an option

Save KrabCode/0f42a8934f71bbc1a5d8fe6b45176031 to your computer and use it in GitHub Desktop.
takes a screenshot, splits it into squares and lets the squares follow a flowfield in a solitaire-victory-like animation
import processing.core.PApplet;
import processing.core.PImage;
import processing.core.PVector;
import java.awt.*;
PImage orig;
FlowField flowField;
Piece[] pieces;
//int windowScale = 120; //dimensions of sketch window as percent of screen size (just go fullscreen for 100)
int pieceScale = 10; //dimensions of one square piece as percent of screen size
int flowScale = 200; //resolution of the flow field
public void settings() {
// size(round((1920/100)*windowScale), round((1080/100)*windowScale));
fullScreen();
}
public void draw() {
noStroke();
fill(0,15);
rect(0,0,width, height);
if(flowField == null){
flowField = new FlowField(flowScale);
}
for(Piece p : pieces){
if(p != null){
p.follow(flowField);
p.draw();
}
}
//flowField.display();
flowField.update();
}
public void setup() {
orig = screenshot();
frameRate(30);
noiseSeed(round(random(100000)));
pieces = cutImage(orig, pieceScale);
}
private Piece[] cutImage(PImage orig, int pieceScale) {
Piece[] pieces = new Piece[width/pieceScale * height/pieceScale];
int i = 0;
int xoff = 0;
for(int x = 0; x < width/pieceScale; x++){
int yoff = 0;
xoff += pieceScale;
for(int y = 0; y < height/pieceScale; y++) {
yoff += pieceScale;
pieces[i++] = new Piece(
new PVector(x*pieceScale, y*pieceScale),
orig.get(xoff, yoff, pieceScale, pieceScale)
);
}
}
return pieces;
}
private PImage screenshot() {
PImage screenshot = null;
try {
screenshot = new PImage(new Robot().createScreenCapture(
new Rectangle(0, 0, displayWidth, displayHeight)));
} catch (AWTException e) {
e.printStackTrace();
}
return screenshot;
}
class Piece{
int maxSpd = 5;
PVector pos, spd, acc;
PImage img;
Piece(PVector pos, PImage img){
this.pos = pos;
this.img = img;
spd = new PVector();
acc = new PVector();
}
public void applyForce(PVector f){
acc.add(f);
}
void follow(FlowField flowField){
applyForce(flowField.lookup(pos));
}
void draw(){
update();
borderCheck();
image(img, pos.x, pos.y, img.width, img.height);
}
private void update(){
spd.add(acc);
spd.limit(maxSpd);
pos.add(spd);
acc.mult(0);
}
private void borderCheck(){
if(pos.x < -img.width) pos.x = width+img.width;
if(pos.x> width + img.width) pos.x = -img.width;
if(pos.y < -img.height) pos.y = height+img.height;
if(pos.y > height + img.height) pos.y = -img.height;
}
}
// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com
// Flow Field Following
class FlowField {
// A flow field is a two dimensional array of PVectors
PVector[][] field;
int cols, rows; // Columns and Rows
int resolution; // How large is each "cell" of the flow field
float zoff = 0; // 3rd dimension of noise
FlowField(int r) {
resolution = r;
// Determine the number of columns and rows based on sketch's width and height
cols = width/resolution;
rows = height/resolution;
field = new PVector[cols][rows];
zoff = random(100);
init();
}
void init() {
// Reseed noise so we get a new flow field every time
noiseSeed((int)random(10000));
float xoff = 0;
for (int i = 0; i < cols; i++) {
float yoff = 0;
for (int j = 0; j < rows; j++) {
float theta = noise(xoff,yoff) * TAU;
field[i][j] = PVector.fromAngle(theta);
yoff += 0.1;
}
xoff += 0.1;
}
}
void update() {
float xoff = 0;
for (int i = 0; i < cols; i++) {
float yoff = 0;
for (int j = 0; j < rows; j++) {
float theta = -PI/2 + noise(xoff, yoff, zoff)*PI;
// Make a vector from an angle
field[i][j] = PVector.fromAngle(theta);
yoff += 0.1;
}
xoff += 0.1;
}
// Animate by changing 3rd dimension of noise every frame
zoff += 0.01;
}
// Draw every vector
void display() {
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
drawVector(field[i][j],i*resolution,j*resolution,resolution-2);
}
}
}
// Renders a vector object 'v' as an arrow and a position 'x,y'
void drawVector(PVector v, float x, float y, float scayl) {
pushMatrix();
float arrowsize = 4;
// Translate to position to render vector
translate(x,y);
stroke(0,150);
// Call vector heading function to get direction (note that pointing up is a heading of 0) and rotate
rotate(v.heading());
// Calculate length of vector & scale it to be bigger or smaller if necessary
float len = v.mag()*scayl;
// Draw three lines to make an arrow (draw pointing up since we've rotate to the proper direction)
line(0,0,len,0);
//line(len,0,len-arrowsize,+arrowsize/2);
//line(len,0,len-arrowsize,-arrowsize/2);
popMatrix();
}
PVector lookup(PVector lookup) {
int column = (int)(constrain(lookup.x/resolution,0,cols-1));
int row = (int)(constrain(lookup.y/resolution,0,rows-1));
return field[column][row];
}
}
@KrabCode
Copy link
Author

KrabCode commented Dec 1, 2017

2017-12-01

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment