Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association
/***
|''Name:''|ProcessingjsPlugin|
|''Description:''|TiddlyWiki Bundle of John Ressig's processing.js|
|''Date:''|May 9, 2008|
|''Author:''|PaulDowney (psd (at) osmosoft (dot) com)|
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/PaulDowney/plugins/ProcessingPlugin.js|
|''Version:''|0.2|
|''License:''|[[MIT license]]|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev |
|''~CoreVersion:''|2.2|
With contributions from Simon Baird.
***/
//{{{
// Ensure Plugin is only installed once.
if(!version.extensions.Processingjs) {
version.extensions.Processingjs = {installed:true};
config.macros.Processing = {
counter: 0,
handler: function (place,macroName,params,wikifier,paramString,tiddler) {
var id = "processingcanvas"+this.counter;
var canvas = createTiddlyElement(place,"canvas",id);
// inlined code
var code = paramString;
// quick and dirty grab of code from a named tiddler
if (store.tiddlerExists(params[0])) {
code = store.getTiddlerText(params[0]);
}
// or with no params, grab code from this tiddler
if (paramString.trim() == '') {
code = tiddler.text;
}
createTiddlyElement(place,"br");
var restartBtn = createTiddlyButton(place,"restart","restart",function() {
story.refreshTiddler(tiddler.title,null,true);
return false;
},
'processingRestart' // it's a class so you can style the button
);
Processing(canvas,code);
}
};
// requires 2.4
merge(config.macros.view.views,{
processing: function(value,place,params,wikifier,paramString,tiddler) {
wikify("<<Processing\n"+value+"\n>>",place,highlightHack,tiddler);
}
});
/*
* inlined copy of Processing.js
* latest code at: http://ejohn.org/blog/processingjs/
*/
/*
* Processing.js - John Resig (http://ejohn.org/)
* MIT Licensed
* http://ejohn.org/blog/processingjs/
*
* This is a port of the Processing Visualization Language.
* More information: http://processing.org/
*/
(function(){
this.Processing = function Processing( aElement, aCode ) {
if ( typeof aElement == "string" )
aElement = document.getElementById( aElement );
var p = buildProcessing( aElement );
if ( aCode )
p.init( aCode );
return p;
};
function log() {
try {
console.log.apply( console, arguments );
} catch(e) {
try {
opera.postError.apply( opera, arguments );
} catch(e){}
}
}
var parse = Processing.parse = function parse( aCode, p ) {
// Angels weep at this parsing code :-(
// Remove end-of-line comments
aCode = aCode.replace(/\/\/ .*\n/g, "\n");
// Weird parsing errors with %
aCode = aCode.replace(/([^\s])%([^\s])/g, "$1 % $2");
// Simple convert a function-like thing to function
aCode = aCode.replace(/(?:static )?(\w+ )(\w+)\s*(\([^\)]*\)\s*{)/g, function(all, type, name, args) {
if ( name == "if" || name == "for" || name == "while" ) {
return all;
} else {
return "Processing." + name + " = function " + name + args;
}
});
// Force .length() to be .length
aCode = aCode.replace(/\.length\(\)/g, ".length");
// foo( int foo, float bar )
aCode = aCode.replace(/([\(,]\s*)(\w+)((?:\[\])+| )\s*(\w+\s*[\),])/g, "$1$4");
aCode = aCode.replace(/([\(,]\s*)(\w+)((?:\[\])+| )\s*(\w+\s*[\),])/g, "$1$4");
// float[] foo = new float[5];
aCode = aCode.replace(/new (\w+)((?:\[([^\]]*)\])+)/g, function(all, name, args) {
return "new ArrayList(" + args.slice(1,-1).split("][").join(", ") + ")";
});
aCode = aCode.replace(/(?:static )?\w+\[\]\s*(\w+)\[?\]?\s*=\s*{.*?};/g, function(all) {
return all.replace(/{/g, "[").replace(/}/g, "]");
});
// int|float foo;
var intFloat = /(\n\s*(?:int|float)(?:\[\])?(?:\s*|[^\(]*?,\s*))([a-z]\w*)(;|,)/i;
while ( intFloat.test(aCode) ) {
aCode = aCode.replace(new RegExp(intFloat), function(all, type, name, sep) {
return type + " " + name + " = 0" + sep;
});
}
// float foo = 5;
aCode = aCode.replace(/(?:static )?(\w+)((?:\[\])+| ) *(\w+)\[?\]?(\s*[=,;])/g, function(all, type, arr, name, sep) {
if ( type == "return" )
return all;
else
return "var " + name + sep;
});
// Fix Array[] foo = {...} to [...]
aCode = aCode.replace(/=\s*{((.|\s)*?)};/g, function(all,data) {
return "= [" + data.replace(/{/g, "[").replace(/}/g, "]") + "]";
});
// static { ... } blocks
aCode = aCode.replace(/static\s*{((.|\n)*?)}/g, function(all, init) {
// Convert the static definitons to variable assignments
//return init.replace(/\((.*?)\)/g, " = $1");
return init;
});
// super() is a reserved word
aCode = aCode.replace(/super\(/g, "superMethod(");
var classes = ["int", "float", "boolean", "string"];
function ClassReplace(all, name, extend, vars, last) {
classes.push( name );
var static = "";
vars = vars.replace(/final\s+var\s+(\w+\s*=\s*.*?;)/g, function(all,set) {
static += " " + name + "." + set;
return "";
});
// Move arguments up from constructor and wrap contents with
// a with(this), and unwrap constructor
return "function " + name + "() {with(this){\n " +
(extend ? "var __self=this;function superMethod(){extendClass(__self,arguments," + extend + ");}\n" : "") +
// Replace var foo = 0; with this.foo = 0;
// and force var foo; to become this.foo = null;
vars
.replace(/,\s?/g, ";\n this.")
.replace(/\b(var |final |public )+\s*/g, "this.")
.replace(/this.(\w+);/g, "this.$1 = null;") +
(extend ? "extendClass(this, " + extend + ");\n" : "") +
"<CLASS " + name + " " + static + ">" + (typeof last == "string" ? last : name + "(");
}
var matchClasses = /(?:public |abstract |static )*class (\w+)\s*(?:extends\s*(\w+)\s*)?{\s*((?:.|\n)*?)\b\1\s*\(/g;
var matchNoCon = /(?:public |abstract |static )*class (\w+)\s*(?:extends\s*(\w+)\s*)?{\s*((?:.|\n)*?)(Processing)/g;
aCode = aCode.replace(matchClasses, ClassReplace);
aCode = aCode.replace(matchNoCon, ClassReplace);
var matchClass = /<CLASS (\w+) (.*?)>/, m;
while ( (m = aCode.match( matchClass )) ) {
var left = RegExp.leftContext,
allRest = RegExp.rightContext,
rest = nextBrace(allRest),
className = m[1],
staticVars = m[2] || "";
allRest = allRest.slice( rest.length + 1 );
rest = rest.replace(new RegExp("\\b" + className + "\\(([^\\)]*?)\\)\\s*{", "g"), function(all, args) {
args = args.split(/,\s*?/);
if ( args[0].match(/^\s*$/) )
args.shift();
var fn = "if ( arguments.length == " + args.length + " ) {\n";
for ( var i = 0; i < args.length; i++ ) {
fn += " var " + args[i] + " = arguments[" + i + "];\n";
}
return fn;
});
// Fix class method names
// this.collide = function() { ... }
// and add closing } for with(this) ...
rest = rest.replace(/(?:public )?Processing.\w+ = function (\w+)\((.*?)\)/g, function(all, name, args) {
return "ADDMETHOD(this, '" + name + "', function(" + args + ")";
});
var matchMethod = /ADDMETHOD([\s\S]*?{)/, mc;
var methods = "";
while ( (mc = rest.match( matchMethod )) ) {
var prev = RegExp.leftContext,
allNext = RegExp.rightContext,
next = nextBrace(allNext);
methods += "addMethod" + mc[1] + next + "});"
rest = prev + allNext.slice( next.length + 1 );
}
rest = methods + rest;
aCode = left + rest + "\n}}" + staticVars + allRest;
}
// Do some tidying up, where necessary
aCode = aCode.replace(/Processing.\w+ = function addMethod/g, "addMethod");
function nextBrace( right ) {
var rest = right;
var position = 0;
var leftCount = 1, rightCount = 0;
while ( leftCount != rightCount ) {
var nextLeft = rest.indexOf("{");
var nextRight = rest.indexOf("}");
if ( nextLeft < nextRight && nextLeft != -1 ) {
leftCount++;
rest = rest.slice( nextLeft + 1 );
position += nextLeft + 1;
} else {
rightCount++;
rest = rest.slice( nextRight + 1 );
position += nextRight + 1;
}
}
return right.slice(0, position - 1);
}
// Handle (int) Casting
aCode = aCode.replace(/\(int\)/g, "0|");
// Remove Casting
aCode = aCode.replace(new RegExp("\\((" + classes.join("|") + ")(\\[\\])?\\)", "g"), "");
// Convert 3.0f to just 3.0
aCode = aCode.replace(/(\d+)f/g, "$1");
// Force numbers to exist
//aCode = aCode.replace(/([^.])(\w+)\s*\+=/g, "$1$2 = ($2||0) +");
// Force characters-as-bytes to work
aCode = aCode.replace(/('[a-zA-Z0-9]')/g, "$1.charCodeAt(0)");
// Convert #aaaaaa into color
aCode = aCode.replace(/#([a-f0-9]{6})/ig, function(m, hex){
var num = toNumbers(hex);
return "color(" + num[0] + "," + num[1] + "," + num[2] + ")";
});
function toNumbers( str ){
var ret = [];
str.replace(/(..)/g, function(str){
ret.push( parseInt( str, 16 ) );
});
return ret;
}
//log(aCode);
return aCode;
};
function buildProcessing( curElement ){
var p = {};
// init
p.PI = Math.PI;
p.TWO_PI = 2 * p.PI;
p.HALF_PI = p.PI / 2;
p.P3D = 3;
p.CORNER = 0;
p.RADIUS = 1;
p.CENTER_RADIUS = 1;
p.CENTER = 2;
p.POLYGON = 2;
p.QUADS = 5;
p.TRIANGLES = 6;
p.POINTS = 7;
p.LINES = 8;
p.TRIANGLE_STRIP = 9;
p.TRIANGLE_FAN = 4;
p.QUAD_STRIP = 3;
p.CORNERS = 10;
p.CLOSE = true;
p.RGB = 1;
p.HSB = 2;
// mouseButton constants: values adjusted to come directly from e.which
p.LEFT = 1;
p.CENTER = 2;
p.RIGHT = 3;
// "Private" variables used to maintain state
var curContext = curElement.getContext("2d");
var doFill = true;
var doStroke = true;
var loopStarted = false;
var hasBackground = false;
var doLoop = true;
var looping = 0;
var curRectMode = p.CORNER;
var curEllipseMode = p.CENTER;
var inSetup = false;
var inDraw = false;
var curBackground = "rgba(204,204,204,1)";
var curFrameRate = 1000;
var curShape = p.POLYGON;
var curShapeCount = 0;
var curvePoints = [];
var curTightness = 0;
var opacityRange = 255;
var redRange = 255;
var greenRange = 255;
var blueRange = 255;
var pathOpen = false;
var mousePressed = false;
var keyPressed = false;
var firstX, firstY, secondX, secondY, prevX, prevY;
var curColorMode = p.RGB;
var curTint = -1;
var curTextSize = 12;
var curTextFont = "Arial";
var getLoaded = false;
var start = (new Date).getTime();
// Global vars for tracking mouse position
p.pmouseX = 0;
p.pmouseY = 0;
p.mouseX = 0;
p.mouseY = 0;
p.mouseButton = 0;
// Will be replaced by the user, most likely
p.mouseDragged = undefined;
p.mouseMoved = undefined;
p.mousePressed = undefined;
p.mouseReleased = undefined;
p.keyPressed = undefined;
p.keyReleased = undefined;
p.draw = undefined;
p.setup = undefined;
// The height/width of the canvas
p.width = curElement.width - 0;
p.height = curElement.height - 0;
// The current animation frame
p.frameCount = 0;
// In case I ever need to do HSV conversion:
// http://srufaculty.sru.edu/david.dailey/javascript/js/5rml.js
p.color = function color( aValue1, aValue2, aValue3, aValue4 ) {
var aColor = "";
if ( arguments.length == 3 ) {
aColor = p.color( aValue1, aValue2, aValue3, opacityRange );
} else if ( arguments.length == 4 ) {
var a = aValue4 / opacityRange;
a = isNaN(a) ? 1 : a;
if ( curColorMode == p.HSB ) {
var rgb = HSBtoRGB(aValue1, aValue2, aValue3);
var r = rgb[0], g = rgb[1], b = rgb[2];
} else {
var r = getColor(aValue1, redRange);
var g = getColor(aValue2, greenRange);
var b = getColor(aValue3, blueRange);
}
aColor = "rgba(" + r + "," + g + "," + b + "," + a + ")";
} else if ( typeof aValue1 == "string" ) {
aColor = aValue1;
if ( arguments.length == 2 ) {
var c = aColor.split(",");
c[3] = (aValue2 / opacityRange) + ")";
aColor = c.join(",");
}
} else if ( arguments.length == 2 ) {
aColor = p.color( aValue1, aValue1, aValue1, aValue2 );
} else if ( typeof aValue1 == "number" ) {
aColor = p.color( aValue1, aValue1, aValue1, opacityRange );
} else {
aColor = p.color( redRange, greenRange, blueRange, opacityRange );
}
// HSB conversion function from Mootools, MIT Licensed
function HSBtoRGB(h, s, b) {
h = (h / redRange) * 100;
s = (s / greenRange) * 100;
b = (b / blueRange) * 100;
if (s == 0){
return [b, b, b];
} else {
var hue = h % 360;
var f = hue % 60;
var br = Math.round(b / 100 * 255);
var p = Math.round((b * (100 - s)) / 10000 * 255);
var q = Math.round((b * (6000 - s * f)) / 600000 * 255);
var t = Math.round((b * (6000 - s * (60 - f))) / 600000 * 255);
switch (Math.floor(hue / 60)){
case 0: return [br, t, p];
case 1: return [q, br, p];
case 2: return [p, br, t];
case 3: return [p, q, br];
case 4: return [t, p, br];
case 5: return [br, p, q];
}
}
}
function getColor( aValue, range ) {
return Math.round(255 * (aValue / range));
}
return aColor;
}
p.nf = function( num, pad ) {
var str = "" + num;
while ( pad - str.length )
str = "0" + str;
return str;
};
p.AniSprite = function( prefix, frames ) {
this.images = [];
this.pos = 0;
for ( var i = 0; i < frames; i++ ) {
this.images.push( prefix + p.nf( i, ("" + frames).length ) + ".gif" );
}
this.display = function( x, y ) {
p.image( this.images[ this.pos ], x, y );
if ( ++this.pos >= frames )
this.pos = 0;
};
this.getWidth = function() {
return getImage(this.images[0]).width;
};
this.getHeight = function() {
return getImage(this.images[0]).height;
};
};
function buildImageObject( obj ) {
var pixels = obj.data;
var data = p.createImage( obj.width, obj.height );
if ( data.__defineGetter__ && data.__lookupGetter__ && !data.__lookupGetter__("pixels") ) {
var pixelsDone;
data.__defineGetter__("pixels", function() {
if ( pixelsDone )
return pixelsDone;
pixelsDone = [];
for ( var i = 0; i < pixels.length; i += 4 ) {
pixelsDone.push( p.color(pixels[i], pixels[i+1], pixels[i+2], pixels[i+3]) );
}
return pixelsDone;
});
} else {
data.pixels = [];
for ( var i = 0; i < pixels.length; i += 4 ) {
data.pixels.push( p.color(pixels[i], pixels[i+1], pixels[i+2], pixels[i+3]) );
}
}
return data;
}
p.createImage = function createImage( w, h, mode ) {
var data = {};
data.width = w;
data.height = h;
data.data = [];
if ( curContext.createImageData ) {
data = curContext.createImageData( w, h );
}
data.pixels = new Array( w * h );
data.get = function(x,y) {
return this.pixels[w*y+x];
};
data._mask = null;
data.mask = function(img) {
this._mask = img;
};
data.loadPixels = function(){};
data.updatePixels = function(){};
return data;
};
p.createGraphics = function createGraphics( w, h ) {
var canvas = document.createElement("canvas");
var ret = buildProcessing( canvas );
ret.size( w, h );
ret.canvas = canvas;
return ret;
};
p.beginDraw = function beginDraw(){};
p.endDraw = function endDraw(){};
p.tint = function tint( rgb, a ) {
curTint = a;
};
function getImage( img ) {
if ( typeof img == "string" ) {
return document.getElementById(img);
}
if ( img.img || img.canvas ) {
return img.img || img.canvas;
}
for ( var i = 0, l = img.pixels.length; i < l; i++ ) {
var pos = i * 4;
var c = (img.pixels[i] || "rgba(0,0,0,1)").slice(5,-1).split(",");
img.data[pos] = parseInt(c[0]);
img.data[pos+1] = parseInt(c[1]);
img.data[pos+2] = parseInt(c[2]);
img.data[pos+3] = parseFloat(c[3]) * 100;
}
var canvas = document.createElement("canvas")
canvas.width = img.width;
canvas.height = img.height;
var context = canvas.getContext("2d");
context.putImageData( img, 0, 0 );
img.canvas = canvas;
return canvas;
}
p.image = function image( img, x, y, w, h ) {
x = x || 0;
y = y || 0;
var obj = getImage(img);
if ( curTint >= 0 ) {
var oldAlpha = curContext.globalAlpha;
curContext.globalAlpha = curTint / opacityRange;
}
if ( arguments.length == 3 ) {
curContext.drawImage( obj, x, y );
} else {
curContext.drawImage( obj, x, y, w, h );
}
if ( curTint >= 0 ) {
curContext.globalAlpha = oldAlpha;
}
if ( img._mask ) {
var oldComposite = curContext.globalCompositeOperation;
curContext.globalCompositeOperation = "darker";
p.image( img._mask, x, y );
curContext.globalCompositeOperation = oldComposite;
}
};
p.exit = function exit() {
clearInterval(looping);
};
p.save = function save( file ){};
p.loadImage = function loadImage( file ) {
var img = document.getElementById(file);
if ( !img )
return;
var h = img.height, w = img.width;
var canvas = document.createElement("canvas");
canvas.width = w;
canvas.height = h;
var context = canvas.getContext("2d");
context.drawImage( img, 0, 0 );
var data = buildImageObject( context.getImageData( 0, 0, w, h ) );
data.img = img;
return data;
};
p.loadFont = function loadFont( name ) {
return {
name: name,
width: function( str ) {
if ( curContext.mozMeasureText )
return curContext.mozMeasureText( typeof str == "number" ?
String.fromCharCode( str ) :
str) / curTextSize;
else
return 0;
}
};
};
p.textFont = function textFont( name, size ) {
curTextFont = name;
p.textSize( size );
};
p.textSize = function textSize( size ) {
if ( size ) {
curTextSize = size;
}
};
p.textAlign = function textAlign(){};
p.text = function text( str, x, y ) {
if ( str && curContext.mozDrawText ) {
curContext.save();
curContext.mozTextStyle = curTextSize + "px " + curTextFont.name;
curContext.translate(x, y);
curContext.mozDrawText( typeof str == "number" ?
String.fromCharCode( str ) :
str );
curContext.restore();
}
};
p.char = function char( key ) {
return key;
};
p.println = function println(){};
p.map = function map( value, istart, istop, ostart, ostop ) {
return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
};
String.prototype.replaceAll = function(re, replace) {
return this.replace(new RegExp(re, "g"), replace);
};
p.Point = function Point( x, y ) {
this.x = x;
this.y = y;
this.copy = function() {
return new Point( x, y );
}
};
p.Random = function() {
var haveNextNextGaussian = false;
var nextNextGaussian;
this.nextGaussian = function() {
if (haveNextNextGaussian) {
haveNextNextGaussian = false;
return nextNextGaussian;
} else {
var v1, v2, s;
do {
v1 = 2 * p.random(1) - 1; // between -1.0 and 1.0
v2 = 2 * p.random(1) - 1; // between -1.0 and 1.0
s = v1 * v1 + v2 * v2;
} while (s >= 1 || s == 0);
var multiplier = Math.sqrt(-2 * Math.log(s)/s);
nextNextGaussian = v2 * multiplier;
haveNextNextGaussian = true;
return v1 * multiplier;
}
};
};
p.ArrayList = function ArrayList( size, size2, size3 ) {
var array = new Array( 0 | size );
if ( size2 ) {
for ( var i = 0; i < size; i++ ) {
array[i] = [];
for ( var j = 0; j < size2; j++ ) {
var a = array[i][j] = size3 ? new Array( size3 ) : 0;
for ( var k = 0; k < size3; k++ ) {
a[k] = 0;
}
}
}
} else {
for ( var i = 0; i < size; i++ ) {
array[i] = 0;
}
}
array.size = function() {
return this.length;
};
array.get = function( i ) {
return this[ i ];
};
array.remove = function( i ) {
return this.splice( i, 1 );
};
array.add = function( item ) {
return this.push( item );
};
array.clone = function() {
var a = new ArrayList( size );
for ( var i = 0; i < size; i++ ) {
a[ i ] = this[ i ];
}
return a;
};
array.isEmpty = function() {
return !this.length;
};
array.clear = function() {
this.length = 0;
};
return array;
};
p.colorMode = function colorMode( mode, range1, range2, range3, range4 ) {
curColorMode = mode;
if ( arguments.length >= 4 ) {
redRange = range1;
greenRange = range2;
blueRange = range3;
}
if ( arguments.length == 5 ) {
opacityRange = range4;
}
if ( arguments.length == 2 ) {
p.colorMode( mode, range1, range1, range1, range1 );
}
};
p.beginShape = function beginShape( type ) {
curShape = type;
curShapeCount = 0;
curvePoints = [];
};
p.endShape = function endShape( close ) {
if ( curShapeCount != 0 ) {
if ( close || doFill )
curContext.lineTo( firstX, firstY );
if ( doFill )
curContext.fill();
if ( doStroke )
curContext.stroke();
curContext.closePath();
curShapeCount = 0;
pathOpen = false;
}
if ( pathOpen ) {
if ( doFill )
curContext.fill();
if ( doStroke )
curContext.stroke();
curContext.closePath();
curShapeCount = 0;
pathOpen = false;
}
};
p.vertex = function vertex( x, y, x2, y2, x3, y3 ) {
if ( curShapeCount == 0 && curShape != p.POINTS ) {
pathOpen = true;
curContext.beginPath();
curContext.moveTo( x, y );
firstX = x;
firstY = y;
} else {
if ( curShape == p.POINTS ) {
p.point( x, y );
} else if ( arguments.length == 2 ) {
if ( curShape != p.QUAD_STRIP || curShapeCount != 2 )
curContext.lineTo( x, y );
if ( curShape == p.TRIANGLE_STRIP ) {
if ( curShapeCount == 2 ) {
// finish shape
p.endShape(p.CLOSE);
pathOpen = true;
curContext.beginPath();
// redraw last line to start next shape
curContext.moveTo( prevX, prevY );
curContext.lineTo( x, y );
curShapeCount = 1;
}
firstX = prevX;
firstY = prevY;
}
if ( curShape == p.TRIANGLE_FAN && curShapeCount == 2 ) {
// finish shape
p.endShape(p.CLOSE);
pathOpen = true;
curContext.beginPath();
// redraw last line to start next shape
curContext.moveTo( firstX, firstY );
curContext.lineTo( x, y );
curShapeCount = 1;
}
if ( curShape == p.QUAD_STRIP && curShapeCount == 3 ) {
// finish shape
curContext.lineTo( prevX, prevY );
p.endShape(p.CLOSE);
pathOpen = true;
curContext.beginPath();
// redraw lines to start next shape
curContext.moveTo( prevX, prevY );
curContext.lineTo( x, y );
curShapeCount = 1;
}
if ( curShape == p.QUAD_STRIP) {
firstX = secondX;
firstY = secondY;
secondX = prevX;
secondY = prevY;
}
} else if ( arguments.length == 4 ) {
if ( curShapeCount > 1 ) {
curContext.moveTo( prevX, prevY );
curContext.quadraticCurveTo( firstX, firstY, x, y );
curShapeCount = 1;
}
} else if ( arguments.length == 6 ) {
curContext.bezierCurveTo( x, y, x2, y2, x3, y3 );
curShapeCount = -1;
}
}
prevX = x;
prevY = y;
curShapeCount++;
if ( curShape == p.LINES && curShapeCount == 2 ||
(curShape == p.TRIANGLES) && curShapeCount == 3 ||
(curShape == p.QUADS) && curShapeCount == 4 ) {
p.endShape(p.CLOSE);
}
};
p.curveVertex = function( x, y, x2, y2 ) {
if ( curvePoints.length < 3 ) {
curvePoints.push([x,y]);
} else {
var b = [], s = 1 - curTightness;
/*
* Matrix to convert from Catmull-Rom to cubic Bezier
* where t = curTightness
* |0 1 0 0 |
* |(t-1)/6 1 (1-t)/6 0 |
* |0 (1-t)/6 1 (t-1)/6 |
* |0 0 0 0 |
*/
curvePoints.push([x,y]);
b[0] = [curvePoints[1][0],curvePoints[1][1]];
b[1] = [curvePoints[1][0]+(s*curvePoints[2][0]-s*curvePoints[0][0])/6,curvePoints[1][1]+(s*curvePoints[2][1]-s*curvePoints[0][1])/6];
b[2] = [curvePoints[2][0]+(s*curvePoints[1][0]-s*curvePoints[3][0])/6,curvePoints[2][1]+(s*curvePoints[1][1]-s*curvePoints[3][1])/6];
b[3] = [curvePoints[2][0],curvePoints[2][1]];
if ( !pathOpen ) {
p.vertex( b[0][0], b[0][1] );
} else {
curShapeCount = 1;
}
p.vertex( b[1][0], b[1][1], b[2][0], b[2][1], b[3][0], b[3][1] );
curvePoints.shift();
}
};
p.curveTightness = function( tightness ) {
curTightness = tightness;
};
p.bezierVertex = p.vertex;
p.rectMode = function rectMode( aRectMode ) {
curRectMode = aRectMode;
};
p.imageMode = function(){};
p.ellipseMode = function ellipseMode( aEllipseMode ) {
curEllipseMode = aEllipseMode;
};
p.dist = function dist( x1, y1, x2, y2 ) {
return Math.sqrt( Math.pow( x2 - x1, 2 ) + Math.pow( y2 - y1, 2 ) );
};
p.year = function year() {
return (new Date).getYear() + 1900;
};
p.month = function month() {
return (new Date).getMonth();
};
p.day = function day() {
return (new Date).getDay();
};
p.hour = function hour() {
return (new Date).getHours();
};
p.minute = function minute() {
return (new Date).getMinutes();
};
p.second = function second() {
return (new Date).getSeconds();
};
p.millis = function millis() {
return (new Date).getTime() - start;
};
p.ortho = function ortho(){};
p.translate = function translate( x, y ) {
curContext.translate( x, y );
};
p.scale = function scale( x, y ) {
curContext.scale( x, y || x );
};
p.rotate = function rotate( aAngle ) {
curContext.rotate( aAngle );
};
p.pushMatrix = function pushMatrix() {
curContext.save();
};
p.popMatrix = function popMatrix() {
curContext.restore();
};
p.redraw = function redraw() {
if ( hasBackground ) {
p.background();
}
p.frameCount++;
inDraw = true;
p.pushMatrix();
p.draw();
p.popMatrix();
inDraw = false;
};
p.loop = function loop() {
if ( loopStarted )
return;
looping = setInterval(function() {
try {
p.redraw();
}
catch(e) {
clearInterval( looping );
throw e;
}
}, 1000 / curFrameRate );
loopStarted = true;
};
p.frameRate = function frameRate( aRate ) {
curFrameRate = aRate;
};
p.background = function background( img ) {
if ( arguments.length ) {
if ( img && img.img ) {
curBackground = img;
} else {
curBackground = p.color.apply( this, arguments );
}
}
if ( curBackground.img ) {
p.image( curBackground, 0, 0 );
} else {
var oldFill = curContext.fillStyle;
curContext.fillStyle = curBackground + "";
curContext.fillRect( 0, 0, p.width, p.height );
curContext.fillStyle = oldFill;
}
};
p.sq = function sq( aNumber ) {
return aNumber * aNumber;
};
p.sqrt = function sqrt( aNumber ) {
return Math.sqrt( aNumber );
};
p.int = function int( aNumber ) {
return Math.floor( aNumber );
};
p.min = function min( aNumber, aNumber2 ) {
return Math.min( aNumber, aNumber2 );
};
p.max = function max( aNumber, aNumber2 ) {
return Math.max( aNumber, aNumber2 );
};
p.ceil = function ceil( aNumber ) {
return Math.ceil( aNumber );
};
p.round = function round( aNumber ) {
return Math.round( aNumber );
};
p.floor = function floor( aNumber ) {
return Math.floor( aNumber );
};
p.float = function float( aNumber ) {
return typeof aNumber == "string" ?
p.float( aNumber.charCodeAt(0) ) :
parseFloat( aNumber );
};
p.byte = function byte( aNumber ) {
return aNumber || 0;
};
p.random = function random( aMin, aMax ) {
return arguments.length == 2 ?
aMin + (Math.random() * (aMax - aMin)) :
Math.random() * aMin;
};
// From: http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
p.noise = function( x, y, z ) {
return arguments.length >= 2 ?
PerlinNoise_2D( x, y ) :
PerlinNoise_2D( x, x );
};
function Noise(x, y) {
var n = x + y * 57;
n = (n<<13) ^ n;
return Math.abs(1.0 - (((n * ((n * n * 15731) + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0));
};
function SmoothedNoise(x, y) {
var corners = ( Noise(x-1, y-1)+Noise(x+1, y-1)+Noise(x-1, y+1)+Noise(x+1, y+1) ) / 16;
var sides = ( Noise(x-1, y) +Noise(x+1, y) +Noise(x, y-1) +Noise(x, y+1) ) / 8;
var center = Noise(x, y) / 4;
return corners + sides + center;
};
function InterpolatedNoise(x, y) {
var integer_X = Math.floor(x);
var fractional_X = x - integer_X;
var integer_Y = Math.floor(y);
var fractional_Y = y - integer_Y;
var v1 = SmoothedNoise(integer_X, integer_Y);
var v2 = SmoothedNoise(integer_X + 1, integer_Y);
var v3 = SmoothedNoise(integer_X, integer_Y + 1);
var v4 = SmoothedNoise(integer_X + 1, integer_Y + 1);
var i1 = Interpolate(v1 , v2 , fractional_X);
var i2 = Interpolate(v3 , v4 , fractional_X);
return Interpolate(i1 , i2 , fractional_Y);
}
function PerlinNoise_2D(x, y) {
var total = 0;
var p = 0.25;
var n = 3;
for ( var i = 0; i <= n; i++ ) {
var frequency = Math.pow(2, i);
var amplitude = Math.pow(p, i);
total = total + InterpolatedNoise(x * frequency, y * frequency) * amplitude;
}
return total;
}
function Interpolate(a, b, x) {
var ft = x * p.PI;
var f = (1 - p.cos(ft)) * .5;
return a*(1-f) + b*f;
}
p.red = function( aColor ) {
return parseInt(aColor.slice(5));
};
p.green = function( aColor ) {
return parseInt(aColor.split(",")[1]);
};
p.blue = function( aColor ) {
return parseInt(aColor.split(",")[2]);
};
p.alpha = function( aColor ) {
return parseInt(aColor.split(",")[3]);
};
p.abs = function abs( aNumber ) {
return Math.abs( aNumber );
};
p.cos = function cos( aNumber ) {
return Math.cos( aNumber );
};
p.sin = function sin( aNumber ) {
return Math.sin( aNumber );
};
p.pow = function pow( aNumber, aExponent ) {
return Math.pow( aNumber, aExponent );
};
p.constrain = function constrain( aNumber, aMin, aMax ) {
return Math.min( Math.max( aNumber, aMin ), aMax );
};
p.sqrt = function sqrt( aNumber ) {
return Math.sqrt( aNumber );
};
p.atan2 = function atan2( aNumber, aNumber2 ) {
return Math.atan2( aNumber, aNumber2 );
};
p.radians = function radians( aAngle ) {
return ( aAngle / 180 ) * p.PI;
};
p.size = function size( aWidth, aHeight ) {
var fillStyle = curContext.fillStyle;
var strokeStyle = curContext.strokeStyle;
curElement.width = p.width = aWidth;
curElement.height = p.height = aHeight;
curContext.fillStyle = fillStyle;
curContext.strokeStyle = strokeStyle;
};
p.noStroke = function noStroke() {
doStroke = false;
};
p.noFill = function noFill() {
doFill = false;
};
p.smooth = function smooth(){};
p.noLoop = function noLoop() {
doLoop = false;
};
p.fill = function fill() {
doFill = true;
curContext.fillStyle = p.color.apply( this, arguments );
};
p.stroke = function stroke() {
doStroke = true;
curContext.strokeStyle = p.color.apply( this, arguments );
};
p.strokeWeight = function strokeWeight( w ) {
curContext.lineWidth = w;
};
p.point = function point( x, y ) {
var oldFill = curContext.fillStyle;
curContext.fillStyle = curContext.strokeStyle;
curContext.fillRect( Math.round( x ), Math.round( y ), 1, 1 );
curContext.fillStyle = oldFill;
};
p.get = function get( x, y ) {
if ( arguments.length == 0 ) {
var c = p.createGraphics( p.width, p.height );
c.image( curContext, 0, 0 );
return c;
}
if ( !getLoaded ) {
getLoaded = buildImageObject( curContext.getImageData(0, 0, p.width, p.height) );
}
return getLoaded.get( x, y );
};
p.set = function set( x, y, obj ) {
if ( obj && obj.img ) {
p.image( obj, x, y );
} else {
var oldFill = curContext.fillStyle;
var color = obj;
curContext.fillStyle = color;
curContext.fillRect( Math.round( x ), Math.round( y ), 1, 1 );
curContext.fillStyle = oldFill;
}
};
p.arc = function arc( x, y, width, height, start, stop ) {
if ( width <= 0 )
return;
if ( curEllipseMode == p.CORNER ) {
x += width / 2;
y += height / 2;
}
curContext.beginPath();
curContext.moveTo( x, y );
curContext.arc( x, y, curEllipseMode == p.CENTER_RADIUS ? width : width/2, start, stop, false );
if ( doFill )
curContext.fill();
if ( doStroke )
curContext.stroke();
curContext.closePath();
};
p.line = function line( x1, y1, x2, y2 ) {
curContext.lineCap = "round";
curContext.beginPath();
curContext.moveTo( x1 || 0, y1 || 0 );
curContext.lineTo( x2 || 0, y2 || 0 );
curContext.stroke();
curContext.closePath();
};
p.bezier = function bezier( x1, y1, x2, y2, x3, y3, x4, y4 ) {
curContext.lineCap = "butt";
curContext.beginPath();
curContext.moveTo( x1, y1 );
curContext.bezierCurveTo( x2, y2, x3, y3, x4, y4 );
curContext.stroke();
curContext.closePath();
};
p.triangle = function triangle( x1, y1, x2, y2, x3, y3 ) {
p.beginShape();
p.vertex( x1, y1 );
p.vertex( x2, y2 );
p.vertex( x3, y3 );
p.endShape();
};
p.quad = function quad( x1, y1, x2, y2, x3, y3, x4, y4 ) {
p.beginShape();
p.vertex( x1, y1 );
p.vertex( x2, y2 );
p.vertex( x3, y3 );
p.vertex( x4, y4 );
p.endShape();
};
p.rect = function rect( x, y, width, height ) {
if ( width == 0 && height == 0 )
return;
curContext.beginPath();
var offsetStart = 0;
var offsetEnd = 0;
if ( curRectMode == p.CORNERS ) {
width -= x;
height -= y;
}
if ( curRectMode == p.RADIUS ) {
width *= 2;
height *= 2;
}
if ( curRectMode == p.CENTER || curRectMode == p.RADIUS ) {
x -= width / 2;
y -= height / 2;
}
curContext.rect(
Math.round( x ) - offsetStart,
Math.round( y ) - offsetStart,
Math.round( width ) + offsetEnd,
Math.round( height ) + offsetEnd
);
if ( doFill )
curContext.fill();
if ( doStroke )
curContext.stroke();
curContext.closePath();
};
p.ellipse = function ellipse( x, y, width, height ) {
x = x || 0;
y = y || 0;
if ( width <= 0 && height <= 0 )
return;
curContext.beginPath();
if ( curEllipseMode == p.RADIUS ) {
width *= 2;
height *= 2;
}
var offsetStart = 0;
// Shortcut for drawing a circle
if ( width == height )
curContext.arc( x - offsetStart, y - offsetStart, width / 2, 0, Math.PI * 2, false );
if ( doFill )
curContext.fill();
if ( doStroke )
curContext.stroke();
curContext.closePath();
};
p.link = function( href, target ) {
window.location = href;
};
p.loadPixels = function() {
p.pixels = buildImageObject( curContext.getImageData(0, 0, p.width, p.height) ).pixels;
};
p.updatePixels = function() {
var colors = /(\d+),(\d+),(\d+),(\d+)/;
var pixels = {};
pixels.width = p.width;
pixels.height = p.height;
pixels.data = [];
if ( curContext.createImageData ) {
pixels = curContext.createImageData( p.width, p.height );
}
var data = pixels.data;
var pos = 0;
for ( var i = 0, l = p.pixels.length; i < l; i++ ) {
var c = (p.pixels[i] || "rgba(0,0,0,1)").match(colors);
data[pos] = parseInt(c[1]);
data[pos+1] = parseInt(c[2]);
data[pos+2] = parseInt(c[3]);
data[pos+3] = parseFloat(c[4]) * 100;
pos += 4;
}
curContext.putImageData(pixels, 0, 0);
};
p.extendClass = function extendClass( obj, args, fn ) {
if ( arguments.length == 3 ) {
fn.apply( obj, args );
} else {
args.call( obj );
}
};
p.addMethod = function addMethod( object, name, fn ) {
if ( object[ name ] ) {
var args = fn.length;
var oldfn = object[ name ];
object[ name ] = function() {
if ( arguments.length == args )
return fn.apply( this, arguments );
else
return oldfn.apply( this, arguments );
};
} else {
object[ name ] = fn;
}
};
p.init = function init(code){
p.stroke( 0 );
p.fill( 255 );
// Canvas has trouble rendering single pixel stuff on whole-pixel
// counts, so we slightly offset it (this is super lame).
curContext.translate( 0.5, 0.5 );
if ( code ) {
(function(Processing){with (p){
eval(parse(code, p));
}})(p);
}
if ( p.setup ) {
inSetup = true;
p.setup();
}
inSetup = false;
if ( p.draw ) {
if ( !doLoop ) {
p.redraw();
} else {
p.loop();
}
}
attach( curElement, "mousemove", function(e) {
var scrollX = window.scrollX != null ? window.scrollX : window.pageXOffset;
var scrollY = window.scrollY != null ? window.scrollY : window.pageYOffset;
p.pmouseX = p.mouseX;
p.pmouseY = p.mouseY;
p.mouseX = e.clientX - curElement.offsetLeft + scrollX;
p.mouseY = e.clientY - curElement.offsetTop + scrollY;
if ( p.mouseMoved ) {
p.mouseMoved();
}
if ( mousePressed && p.mouseDragged ) {
p.mouseDragged();
}
});
attach( curElement, "mousedown", function(e) {
mousePressed = true;
p.mouseButton = e.which;
if ( typeof p.mousePressed == "function" ) {
p.mousePressed();
} else {
p.mousePressed = true;
}
});
attach( curElement, "contextmenu", function(e) {
e.preventDefault();
e.stopPropagation();
});
attach( curElement, "mouseup", function(e) {
mousePressed = false;
if ( typeof p.mousePressed != "function" ) {
p.mousePressed = false;
}
if ( p.mouseReleased ) {
p.mouseReleased();
}
});
attach( document, "keydown", function(e) {
keyPressed = true;
p.key = e.keyCode + 32;
if ( e.shiftKey ) {
p.key = String.fromCharCode(p.key).toUpperCase().charCodeAt(0);
}
if ( typeof p.keyPressed == "function" ) {
p.keyPressed();
} else {
p.keyPressed = true;
}
});
attach( document, "keyup", function(e) {
keyPressed = false;
if ( typeof p.keyPressed != "function" ) {
p.keyPressed = false;
}
if ( p.keyReleased ) {
p.keyReleased();
}
});
function attach(elem, type, fn) {
if ( elem.addEventListener )
elem.addEventListener( type, fn, false );
else
elem.attachEvent( "on" + type, fn );
}
};
return p;
}
})();
} //# end of "install only once"
//}}}
TiddlyProcessing
[[Basic Examples|BasicExample]]
ProcessingjsPlugin
Processing.js in TiddlyWiki
[[TiddlyWiki|http://tiddlywiki.com]], a wiki in a single HTML page. Open a [[Downloaded]] a copy of this page in Firefox, and you'll be able to edit the examples and save your changes locally on your computer. For more help on using TiddlyWiki, including support for other browsers, see [[Download Software|http://www.tiddlywiki.com/#DownloadSoftware]].
If you have questions, the ~TiddlyWiki community is incredibly helpful - there's a [[developer's group|http://groups.google.com/group/TiddlyWikiDev]] and a [[user's group|http://groups.google.com/group/TiddlyWiki]] on Google Groups.
TiddlyProcessing is a TiddlyWiki containing [[John Ressig|http://ejohn.org]]'s [[Processing.js|http://ejohn.org/apps/processing.js/]] [[basic examples|BasicExample]]. Double click an example, e.g. [[Clock]] to view and edit the source. Most of the examples work, with the notable exception of those involving images. [[Download|./download.php]] this file and reopen it in Firefox to save your work.
[[Simon Baird|http://simonbaird.com/]] has made some great tweaks and examples, and put [[his version|http://tiddlyprocessing-simon.tiddlyspot.com]] up on [[TiddlySpot|http://tiddlyspot.com]], a great place to store your ~TiddlyWikis.
by Daniel Shiffman. Create a more complex wave by adding two waves together.
<<Processing
int xspacing = 8; // How far apart should each horizontal location be spaced
int w; // Width of entire wave
int maxwaves = 4; // total # of waves to add together
float theta = 0.0f;
float[] amplitude = new float[maxwaves]; // Height of wave
float[] dx = new float[maxwaves]; // Value for incrementing X, to be calculated as a function of period and xspacing
float[] yvalues; // Using an array to store height values for the wave (not entirely necessary)
void setup() {
size(200,200);
frameRate(30);
colorMode(RGB,255,255,255,100);
smooth();
w = width+16;
for (int i = 0; i < maxwaves; i++) {
amplitude[i] = random(10,30);
float period = random(100,300); // How many pixels before the wave repeats
dx[i] = (TWO_PI / period) * xspacing;
}
yvalues = new float[w/xspacing];
}
void draw() {
background(0);
calcWave();
renderWave();
}
void calcWave() {
// Increment theta (try different values for 'angular velocity' here
theta += 0.02;
// Set all height values to zero
for (int i = 0; i < yvalues.length; i++) {
yvalues[i] = 0.0f;
}
// Accumulate wave height values
for (int j = 0; j < maxwaves; j++) {
float x = theta;
for (int i = 0; i < yvalues.length; i++) {
// Every other wave is cosine instead of sine
if (j % 2 == 0) yvalues[i] += sin(x)*amplitude[j];
else yvalues[i] += cos(x)*amplitude[j];
x+=dx[j];
}
}
}
void renderWave() {
// A simple way to draw the wave with an ellipse at each location
noStroke();
fill(255,50);
ellipseMode(CENTER);
for (int x = 0; x < yvalues.length; x++) {
ellipse(x*xspacing,width/2+yvalues[x],16,16);
}
}
>>
Taken from [[basic/additivewave.html|http://ejohn.org/apps/processing.js/examples/basic/additivewave.html]]
Loads a "mask" for an image to specify the transparency in different parts of the image. The two images are blended together using the mask() method of PImage. Created 29 April 2003.
<<Processing
PImage img;
PImage maskImg;
void setup()
{
size(200,200);
img = loadImage("test.jpg");
maskImg = loadImage("mask.jpg");
img.mask(maskImg);
}
void draw()
{
background((mouseX+mouseY)/1.5);
image(img, 50, 50);
image(img, mouseX-50, mouseY-50);
}
>>
Taken from [[basic/alphamask.html|http://ejohn.org/apps/processing.js/examples/basic/alphamask.html]]
The angle of each segment is controlled with the mouseX and mouseY position. The transformations applied to the first segment are also applied to the second segment because they are inside the same pushMatrix() and popMatrix() group.
<<Processing
float x = 50;
float y = 100;
float angle1 = 0.0;
float angle2 = 0.0;
float segLength = 50;
void setup() {
size(200, 200);
smooth();
strokeWeight(20.0);
stroke(0, 100);
}
void draw() {
background(226);
angle1 = (mouseX/float(width) - 0.5) * -PI;
angle2 = (mouseY/float(height) - 0.5) * PI;
pushMatrix();
segment(x, y, angle1);
segment(segLength, 0, angle2);
popMatrix();
}
void segment(float x, float y, float a) {
translate(x, y);
rotate(a);
line(0, 0, segLength, 0);
}
>>
Taken from [[basic/arm.html|http://ejohn.org/apps/processing.js/examples/basic/arm.html]]
An array is a list of data. Each piece of data in an array is identified by an index number representing its position in the array. Arrays are zero based, which means that the first element in the array is [0], the second element is [1], and so on. In this example, an array named "coswav" is created and filled with the cosine values. This data is displayed three separate ways on the screen.
<<Processing
size(200, 200);
float[] coswave = new float[width];
for(int i=0; i<width; i++) {
float ratio = (float)i/(float)width;
coswave[i] = abs( cos(ratio*PI) );
}
for(int i=0; i<width; i++) {
stroke(coswave[i]*255);
line(i, 0, i, width/3);
}
for(int i=0; i<width; i++) {
stroke(coswave[i]*255/4);
line(i, width/3, i, width/3*2);
}
for(int i=0; i<width; i++) {
stroke(255-coswave[i]*255);
line(i, width/3*2, i, height);
}
>>
Taken from [[basic/array.html|http://ejohn.org/apps/processing.js/examples/basic/array.html]]
Demonstrates the syntax for creating a two-dimensional (2D) array. Values in a 2D array are accessed through two index values. 2D arrays are useful for storing images. In this example, each dot is colored in relation to its distance from the center of the image.
<<Processing
float[][] distances;
float maxDistance;
size(200, 200);
background(0);
maxDistance = dist(width/2, height/2, width, height);
distances = new float[width][height];
for(int i=0; i<height; i++) {
for(int j=0; j<width; j++) {
float d = dist(width/2, height/2, j, i);
distances[j][i] = d/maxDistance * 255;
}
}
for(int i=0; i<height; i+=2) {
for(int j=0; j<width; j+=2) {
stroke(distances[j][i]);
point(j, i);
}
}
>>
Taken from [[basic/array2d.html|http://ejohn.org/apps/processing.js/examples/basic/array2d.html]]
Demonstrates the syntax for creating an array of custom objects.
<<Processing
int unit = 40;
int num;
Module[] mods;
void setup()
{
size(200, 200);
background(176);
noStroke();
num = width/unit * width/unit;
mods = new Module[num];
for (int i=0; i<height/unit; i++) {
for(int j=0; j<height/unit; j++) {
int index = i*height/unit + j;
mods[index] = new Module(j*unit, i*unit, unit/2, unit/2, random(0.05, 0.8));
}
}
}
void draw()
{
for(int i=0; i<num; i++) {
mods[i].update();
mods[i].draw();
}
}
class Module {
float mx, my;
int size = unit;
float x, y = 0;
int xdir = 1;
int ydir = 1;
float speed;
// Contructor (required)
Module(float imx, float imy, float ix, float iy, float ispeed) {
mx = imy;
my = imx;
x = int(ix);
y = int(iy);
speed = ispeed;
}
// Custom method for updating the variables
void update() {
x = x + (speed * xdir);
if (x >= size || x <= 0) {
xdir *= -1;
x = x + (1 * xdir);
y = y + (1 * ydir);
}
if (y >= size || y <= 0) {
ydir *= -1;
y = y + (1 * ydir);
}
}
// Custom method for drawing the object
void draw() {
stroke(second()*4);
point(mx+x-1, my+y-1);
}
}
>>
Taken from [[basic/arrayobjects.html|http://ejohn.org/apps/processing.js/examples/basic/arrayobjects.html]]
This example presents the fastest way to load a background image into Processing. To load an image as the background, it must be the same width and height as the program.
<<Processing
PImage bg;
int a;
void setup()
{
size(200,200);
frameRate(30);
// The background image must be the same size as the parameters
// into the size() method. In this program, the size of "milan_rubbish.jpg"
// is 200 x 200 pixels.
bg = loadImage("milan_rubbish.jpg");
}
void draw()
{
background(bg);
a = (a + 1)%(width+32);
stroke(226, 204, 0);
line(0, a, width, a-26);
line(0, a-6, width, a-32);
}
>>
Taken from [[basic/backgroundimage.html|http://ejohn.org/apps/processing.js/examples/basic/backgroundimage.html]]
The first two parameters for the bezier() function specify the first point in the curve and the last two parameters specify the last point. The middle parameters set the control points that define the shape of the curve.
<<Processing
size(200, 200);
background(0);
stroke(255);
noFill();
smooth();
for(int i = 0; i < 100; i += 20) {
bezier(90-(i/2.0), 20+i, 210, 10, 220, 150, 120-(i/8.0), 150+(i/4.0));
}
>>
Taken from [[basic/bezier.html|http://ejohn.org/apps/processing.js/examples/basic/bezier.html]]
by Rusty Robison. Brightness is the relative lightness or darkness of a color. Move the cursor vertically over each bar to alter its brightness.
<<Processing
int barWidth = 5;
int[] brightness;
void setup()
{
size(200, 200);
colorMode(HSB, 360, height, height);
brightness = new int[width/barWidth];
}
void draw()
{
int j = 0;
for (int i = 0; i <= (width-barWidth); i += barWidth) {
noStroke();
if ((mouseX > i) && (mouseX < i+barWidth)) {
brightness[j] = mouseY;
}
fill(i, height, brightness[j]);
rect(i, 0, barWidth, height);
j++;
}
}
>>
Taken from [[basic/brightness.html|http://ejohn.org/apps/processing.js/examples/basic/brightness.html]]
Click on the image to give it focus and then type letters to shift the location of the image. Characters are typographic symbols such as A, d, and %. The character datatype, abbreviated as char, stores letters and symbols in the Unicode format, a coding system developed to support a variety of world languages. Characters are distinguished from other symbols by putting them between single quotes ('P'). A string is a sequence of characters. A string is noted by surrounding a group of letters with double quotes ("Processing"). Chars and strings are most often used with the keyboard methods, to display text to the screen, and to load images or files.
<<Processing
PImage frog;
PFont fontA;
int lettersize = 90;
int xoffset;
char letter;
void setup()
{
size(200, 200);
fontA = loadFont("Arial");
textFont(fontA);
textSize(lettersize);
// The String datatype must be capitalized because it is a complex datatype.
// A String is actually a class with its own methods, some of which are
// featured below.
String name= "rathausFrog";
String extension = ".jpg";
int nameLength = name.length();
println("The length of " + name + " is " + nameLength + ".");
name = name.concat(extension);
nameLength = name.length();
println("The length of " + name + " is " + nameLength + ".");
// The parameter for the loadImage() method must be a string
// This line could also be written "frog = loadImage("rathausFrog.jpg");
frog = loadImage(name);
}
void draw()
{
background(51); // Set background to dark gray
image(frog, xoffset, 0);
// Draw an X
line(0, 0, width, height);
line(0, height, width, 0);
// Get the width of the letter
int letterWidth = int(fontA.width(letter) * lettersize);
// Draw the letter to the center of the screen
text(letter, width/2-letterWidth/2, height/2);
}
void keyPressed()
{
// The variable "key" always contains the value of the most recent key pressed.
// If the key is an upper or lowercase letter between 'A' and 'z'
// the image is shifted to the corresponding value of that key
if(key >= 'A' && key <= 'z') {
letter = char(key);
// Scale the values to numbers between 0 and 100
float scale = 100.0/57.0;
int temp = int((key - 'A') * scale);
// Set the offset for the image
xoffset = temp;
println(key);
}
}
>>
Taken from [[basic/charactersstrings.html|http://ejohn.org/apps/processing.js/examples/basic/charactersstrings.html]]
The current time can be read with the second(), minute(), and hour() functions. In this example, sin() and cos() values are used to set the position of the hands. *
<<Processing
void setup() {
size(200, 200);
stroke(255);
smooth();
}
void draw() {
background(0);
fill(80);
noStroke();
// Angles for sin() and cos() start at 3 o'clock;
// subtract HALF_PI to make them start at the top
ellipse(100, 100, 160, 160);
float s = map(second(), 0, 60, 0, TWO_PI) - HALF_PI;
float m = map(minute(), 0, 60, 0, TWO_PI) - HALF_PI;
float h = map(hour() % 12, 0, 12, 0, TWO_PI) - HALF_PI;
stroke(255);
strokeWeight(1);
line(100, 100, cos(s) * 72 + 100, sin(s) * 72 + 100);
strokeWeight(2);
line(100, 100, cos(m) * 60 + 100, sin(m) * 60 + 100);
strokeWeight(4);
line(100, 100, cos(h) * 50 + 100, sin(h) * 50 + 100);
}
>>
Taken from [[basic/clock.html|http://ejohn.org/apps/processing.js/examples/basic/clock.html]]
by Ira Greenberg. The primaries are red, yellow, and blue. The secondaries are green, purple, and orange. The tertiaries are yellow-orange, red-orange, red-purple, blue-purple, blue-green, and yellow-green. Create a shade or tint of the subtractive color wheel using SHADE or TINT parameters.
<<Processing
int segs = 12;
int steps = 6;
float rotAdjust = radians(360.0/segs/2.0);
float radius = 95.0;
float segWidth = radius/steps;
float interval = TWO_PI/segs;
int SHADE = 0;
int TINT = 1;
void setup(){
size(200, 200);
background(127);
smooth();
ellipseMode(CENTER_RADIUS);
noStroke();
// you can substitue TINT for SHADE argument
createWheel(width/2, height/2, SHADE);
}
void createWheel(int x, int y, int valueShift){
if (valueShift == SHADE){
for (int j=0; j<steps; j++){
color[]cols = {
color(255-(255/steps)*j, 255-(255/steps)*j, 0),
color(255-(255/steps)*j, (255/1.5)-((255/1.5)/steps)*j, 0),
color(255-(255/steps)*j, (255/2)-((255/2)/steps)*j, 0),
color(255-(255/steps)*j, (255/2.5)-((255/2.5)/steps)*j, 0),
color(255-(255/steps)*j, 0, 0),
color(255-(255/steps)*j, 0, (255/2)-((255/2)/steps)*j),
color(255-(255/steps)*j, 0, 255-(255/steps)*j),
color((255/2)-((255/2)/steps)*j, 0, 255-(255/steps)*j),
color(0, 0, 255-(255/steps)*j),
color(0, 255-(255/steps)*j, (255/2.5)-((255/2.5)/steps)*j),
color(0, 255-(255/steps)*j, 0),
color((255/2)-((255/2)/steps)*j, 255-(255/steps)*j, 0) };
for (int i=0; i< segs; i++){
fill(cols[i]);
arc(x, y, radius, radius, interval*i+rotAdjust, interval*(i+1)+rotAdjust);
}
radius -= segWidth;
}
} else if (valueShift == TINT){
for (int j=0; j<steps; j++){
color[]cols = {
color((255/steps)*j, (255/steps)*j, 0),
color((255/steps)*j, ((255/1.5)/steps)*j, 0),
color((255/steps)*j, ((255/2)/steps)*j, 0),
color((255/steps)*j, ((255/2.5)/steps)*j, 0),
color((255/steps)*j, 0, 0),
color((255/steps)*j, 0, ((255/2)/steps)*j),
color((255/steps)*j, 0, (255/steps)*j),
color(((255/2)/steps)*j, 0, (255/steps)*j),
color(0, 0, (255/steps)*j),
color(0, (255/steps)*j, ((255/2.5)/steps)*j),
color(0, (255/steps)*j, 0),
color(((255/2)/steps)*j, (255/steps)*j, 0) };
for (int i=0; i< segs; i++){
fill(cols[i]);
arc(x, y, radius, radius, interval*i+rotAdjust, interval*(i+1)+rotAdjust);
}
radius -= segWidth;
}
}
}
>>
Taken from [[basic/colorwheel.html|http://ejohn.org/apps/processing.js/examples/basic/colorwheel.html]]
An object can include several other objects. Creating such composite objects is a good way to use the principles of modularity and build higher levels of abstraction within a program.
<<Processing
EggRing er1, er2;
void setup()
{
size(200, 200);
smooth();
er1 = new EggRing(66, 132, 0.1, 66);
er2 = new EggRing(132, 180, 0.05, 132);
}
void draw()
{
background(0);
er1.transmit();
er2.transmit();
}
class EggRing
{
Egg ovoid;
Ring circle = new Ring();
EggRing(int x, int y, float t, float sp) {
ovoid = new Egg(x, y, t, sp);
circle.start(x, y - sp/2);
}
void transmit() {
ovoid.wobble();
ovoid.display();
circle.grow();
circle.display();
if (circle.on == false) {
circle.on = true;
}
}
}
class Egg {
float x, y; // X-coordinate, y-coordinate
float tilt; // Left and right angle offset
float angle; // Used to define the tilt
float scalar; // Height of the egg
// Constructor
Egg(int xpos, int ypos, float t, float s) {
x = xpos;
y = ypos;
tilt = t;
scalar = s / 100.0;
}
void wobble() {
tilt = cos(angle) / 8;
angle += 0.1;
}
void display() {
noStroke();
fill(255);
pushMatrix();
translate(x, y);
rotate(tilt);
scale(scalar);
beginShape();
vertex(0, -100);
bezierVertex(25, -100, 40, -65, 40, -40);
bezierVertex(40, -15, 25, 0, 0, 0);
bezierVertex(-25, 0, -40, -15, -40, -40);
bezierVertex(-40, -65, -25, -100, 0, -100);
endShape();
popMatrix();
}
}
class Ring {
float x, y; // X-coordinate, y-coordinate
float diameter; // Diameter of the ring
boolean on = false; // Turns the display on and off
void start(float xpos, float ypos) {
x = xpos;
y = ypos;
on = true;
diameter = 1;
}
void grow() {
if (on == true) {
diameter += 0.5;
if (diameter > width*2) {
diameter = 0.0;
}
}
}
void display() {
if (on == true) {
noFill();
strokeWeight(4);
stroke(155, 153);
ellipse(x, y, diameter, diameter);
}
}
}
>>
Taken from [[basic/compositeobjects.html|http://ejohn.org/apps/processing.js/examples/basic/compositeobjects.html]]
Conditions are like questions. They allow a program to decide to take one action if the answer to a question is true or to do another action if the answer to the question is false. The questions asked within a program are always logical or relational statements. For example, if the variable 'i' is equal to zero then draw a line.
<<Processing
size(200, 200);
background(0);
for(int i=10; i<width; i+=10) {
// If 'i' divides by 20 with no remainder draw the first line
// else draw the second line
if(i%20 == 0) {
stroke(153);
line(i, 40, i, height/2);
} else {
stroke(102);
line(i, 20, i, 180);
}
}
>>
Taken from [[basic/conditionals1.html|http://ejohn.org/apps/processing.js/examples/basic/conditionals1.html]]
We extend the language of conditionals by adding the keyword "else". This allows conditionals to ask two or more sequential questions, each with a different action.
<<Processing
size(200, 200);
background(0);
for(int i=2; i<width-2; i+=2) {
// If 'i' divides by 20 with no remainder
// draw the first line else draw the second line
if(i%20 == 0) {
stroke(255);
line(i, 40, i, height/2);
} else if (i%10 == 0) {
stroke(153);
line(i, 20, i, 180);
} else {
stroke(102);
line(i, height/2, i, height-40);
}
}
>>
Taken from [[basic/conditionals2.html|http://ejohn.org/apps/processing.js/examples/basic/conditionals2.html]]
Move the mouse across the screen to move the circle. The program constrains the circle to its box.
<<Processing
float mx;
float my;
float easing = 0.05;
float esize = 25.0;
int box = 30;
void setup()
{
size(200, 200);
noStroke();
smooth();
ellipseMode(CENTER_RADIUS);
}
void draw()
{
background(51);
if(abs(mouseX - mx) > 0.1) {
mx = mx + (mouseX - mx) * easing;
}
if(abs(mouseY - my) > 0.1) {
my = my + (mouseY- my) * easing;
}
float distance = esize * 2;
mx = constrain(mx, box+distance, width-box-distance);
my = constrain(my, box+distance, height-box-distance);
fill(76);
rect(box+esize, box+esize, box*3, box*3);
fill(255);
ellipse(mx, my, esize, esize);
}
>>
Taken from [[basic/constrain.html|http://ejohn.org/apps/processing.js/examples/basic/constrain.html]]
All shapes drawn to the screen have a position that is specified as a coordinate. All coordinates are measured as the distance from the origin in units of pixels. The origin [0, 0] is the coordinate is in the upper left of the window and the coordinate in the lower right is [width-1, height-1].
<<Processing
// Sets the screen to be 200, 200, so the width of the window is 200 pixels
// and the height of the window is 200 pixels
size(200, 200);
background(0);
noFill();
stroke(255);
// The two parameters of the point() method each specify coordinates.
// This call to point() draws at the position [100, 100]
point(width/2, height/2);
// Draws to the position [100, 50]
point(width/2, height/4);
// It is also possible to specify a point with any parameter,
// but only coordinates on the screen are visible
point(60, 30);
point(60, 134);
point(160, 50);
point(280, -800);
point(201, 100);
// Coordinates are used for drawing all shapes, not just points.
// Parameters for different methods are used for different purposes.
// For example, the first two parameters to line() specify the coordinates of the
// first point and the second two parameters specify the second point
stroke(204);
line(0, 73, width, 73);
// The first two parameters to rect() are coordinates
// and the second two are the width and height
rect(110, 55, 40, 36);
>>
Taken from [[basic/coordinates.html|http://ejohn.org/apps/processing.js/examples/basic/coordinates.html]]
The createGraphics() function creates an object from the PGraphics class (PGraphics is the main graphics and rendering context for Processing). The beginDraw() method is necessary to prepare for drawing and endDraw() is necessary to finish. Use this class if you need to draw into an off-screen graphics buffer or to maintain two contexts with different properties.
<<Processing
PGraphics pg;
void setup() {
size(200, 200);
pg = createGraphics(80, 80, P3D);
}
void draw() {
fill(0, 12);
rect(0, 0, width, height);
fill(255);
noStroke();
ellipse(mouseX, mouseY, 60, 60);
pg.beginDraw();
pg.background(102);
pg.noFill();
pg.stroke(255);
pg.ellipse(mouseX-60, mouseY-60, 60, 60);
pg.endDraw();
image(pg, 60, 60);
}
>>
Taken from [[basic/creategraphics.html|http://ejohn.org/apps/processing.js/examples/basic/creategraphics.html]]
The createImage() function provides a fresh buffer of pixels to play with. This example creates an image gradient.
<<Processing
PImage img;
void setup()
{
size(200, 200);
img = createImage(120, 120, RGB);
for(int i=0; i < img.pixels.length; i++) {
img.pixels[i] = color(0, 90, 102, i%img.width * 2);
}
}
void draw()
{
background(204);
image(img, 33, 33);
image(img, mouseX-60, mouseY-60);
}
>>
Taken from [[basic/createimage.html|http://ejohn.org/apps/processing.js/examples/basic/createimage.html]]
Creating variables for colors that may be referred to in the program by their name, rather than a number.
<<Processing
size(200, 200);
noStroke();
color inside = color(204, 102, 0);
color middle = color(204, 153, 0);
color outside = color(153, 51, 0);
// These statements are equivalent to the statements above.
// Programmers may use the format they prefer.
//color inside = #CC6600;
//color middle = #CC9900;
//color outside = #993300;
fill(outside);
rect(0, 0, 200, 200);
fill(middle);
rect(40, 60, 120, 120);
fill(inside);
rect(60, 90, 80, 80);
>>
Taken from [[basic/creating.html|http://ejohn.org/apps/processing.js/examples/basic/creating.html]]
It is sometimes beneficial to convert a value from one type of data to another. Each of the conversion functions converts its parameter to an equivalent representation within its datatype. The conversion functions include int(), float(), char(), byte(), and others.
<<Processing
size(200, 200);
background(51);
noStroke();
char c; // Chars are used for storing typographic symbols
float f; // Floats are decimal numbers
int i; // Ints are values between 2,147,483,647 and -2147483648
byte b; // Bytes are values between -128 and 128
c = 'A';
f = float(c); // Sets f = 65.0
i = int(f * 1.4); // Sets i to 91
b = byte(c / 2); // Sets b to 32
rect(f, 0, 40, 66);
fill(204);
rect(i, 67, 40, 66);
fill(255);
rect(b, 134, 40, 66);
>>
Taken from [[basic/datatypeconversion.html|http://ejohn.org/apps/processing.js/examples/basic/datatypeconversion.html]]
Images can be displayed to the screen at their actual size or any other size.
<<Processing
size(200, 200);
PImage a; // Declare variable "a" of type PImage
a = loadImage("arch.jpg"); // Load the images into the program
image(a, 0, 0); // Displays the image from point (0,0)
image(a, width/2, 0, a.width/2, a.height/2);
>>
Taken from [[basic/displaying.html|http://ejohn.org/apps/processing.js/examples/basic/displaying.html]]
Move the mouse across the image to obscure and reveal the matrix. Measures the distance from the mouse to each square and sets the size proportionally.
<<Processing
float max_distance;
void setup() {
size(200, 200);
smooth();
noStroke();
max_distance = dist(0, 0, width, height);
}
void draw()
{
background(51);
for(int i = 0; i <= width; i += 20) {
for(int j = 0; j <= width; j += 20) {
float size = dist(mouseX, mouseY, i, j);
size = size/max_distance * 66;
//opera.postError(i, j, size);
ellipse(i, j, size, size);
}
}
}
>>
Taken from [[basic/distance2d.html|http://ejohn.org/apps/processing.js/examples/basic/distance2d.html]]
by Ira Greenberg. Using 2 random() calls the and point() function to create an irregular sawtooth line.
<<Processing
size(200, 200);
background(0);
int totalPts = 300;
float steps = totalPts+1;
stroke(255);
float rand = 0;
for (int i=1; i< steps; i++){
point( (width/steps) * i, (height/2) + random(-rand, rand) );
rand += random(-5, 5);
}
>>
Taken from [[basic/doublerandom.html|http://ejohn.org/apps/processing.js/examples/basic/doublerandom.html]]
Move the mouse across the screen and the symbol will follow. Between drawing each frame of the animation, the program calculates the difference between the position of the symbol and the cursor. If the distance is larger than 1 pixel, the symbol moves half of the distance from its current position toward the cursor.
<<Processing
float x;
float y;
float targetX, targetY;
float easing = 0.05;
void setup()
{
size(200, 200);
smooth();
noStroke();
}
void draw()
{
background( 51 );
targetX = mouseX;
float dx = mouseX - x;
if(abs(dx) > 1) {
x += dx * easing;
}
targetY = mouseY;
float dy = mouseY - y;
if(abs(dy) > 1) {
y += dy * easing;
}
ellipse(x, y, 33, 33);
}
>>
Taken from [[basic/easing.html|http://ejohn.org/apps/processing.js/examples/basic/easing.html]]
Embedding "for" structures allows repetition in two dimensions.
<<Processing
float box_size = 11;
float box_space = 12;
int margin = 7;
size(200, 200);
background(0);
noStroke();
// Draw gray boxes
for(int i = margin; i < width-margin; i += box_space) {
for(int j = margin; j < height-margin; j += box_space) {
fill(255 - box_size*10);
rect(j, i, box_size, box_size);
}
box_size = box_size - 0.6;
}
>>
Taken from [[basic/embeddediteration.html|http://ejohn.org/apps/processing.js/examples/basic/embeddediteration.html]]
Click on the left button to open a different URL in the same window (Only works online). Click on the right button to open a URL in a new browser window. Created 21 June 2003.
<<Processing
boolean overLeftButton = false;
boolean overRightButton = false;
void setup()
{
size(200, 200);
}
void draw()
{
background(204);
// Left buttom
if(overLeftButton == true) {
fill(255);
} else {
noFill();
}
rect(20, 60, 75, 75);
rect(50, 90, 15, 15);
// Right button
if(overRightButton == true) {
fill(255);
} else {
noFill();
}
rect(105, 60, 75, 75);
line(135, 105, 155, 85);
line(140, 85, 155, 85);
line(155, 85, 155, 100);
}
void mousePressed()
{
if(overLeftButton) {
link("http://www.processing.org");
} else if (overRightButton) {
link("http://www.processing.org", "_new");
}
}
void mouseMoved() {
checkButtons();
}
void mouseDragged() {
checkButtons();
}
void checkButtons() {
if(mouseX > 20 && mouseX < 95 &&
mouseY > 60 && mouseY <135) {
overLeftButton = true;
} else if (mouseX > 105 && mouseX < 180 &&
mouseY > 60 && mouseY <135) {
overRightButton = true;
} else {
overLeftButton = overRightButton = false;
}
}
>>
Taken from [[basic/embeddedlinks.html|http://ejohn.org/apps/processing.js/examples/basic/embeddedlinks.html]]
The draw_target() function makes it easy to draw many distinct targets. Each call to draw_target() specifies the position, size, and number of rings for each target.
<<Processing
void setup()
{
size(200, 200);
background(51);
noStroke();
smooth();
noLoop();
}
void draw()
{
draw_target(68, 34, 200, 10);
draw_target(152, 16, 100, 3);
draw_target(100, 144, 80, 5);
}
void draw_target(int xloc, int yloc, int size, int num)
{
float grayvalues = 255/num;
float steps = size/num;
for(int i=0; i<num; i++) {
fill(i*grayvalues);
ellipse(xloc, yloc, size-i*steps, size-i*steps);
}
}
>>
Taken from [[basic/functions.html|http://ejohn.org/apps/processing.js/examples/basic/functions.html]]
by Daniel Shiffman. Graphics the following equation: sin(n*cos(r) + 5*theta) where n is a function of horizontal mouse location.
<<Processing
void setup() {
size(50,50);
frameRate(30);
}
void draw() {
loadPixels();
float n = (mouseX * 10.0) / width;
float w = 16.0; // 2D space width
float h = 16.0; // 2D space height
float dx = w / width; // Increment x this amount per pixel
float dy = h / height; // Increment y this amount per pixel
float x = -w/2; // Start x at -1 * width / 2
for (int i = 0; i < width; i++) {
float y = -h/2; // Start y at -1 * height / 2
for (int j = 0; j < height; j++) {
float r = sqrt((x*x) + (y*y)); // Convert cartesian to polar
float theta = atan2(y,x); // Convert cartesian to polar
// Compute 2D polar coordinate function
float val = sin(n*cos(r) + 5 * theta); // Results in a value between -1 and 1
//float val = cos(r); // Another simple function
//float val = sin(theta); // Another simple function
// Map resulting vale to grayscale value
pixels[i+j*width] = color((val + 1.0) * 255.0/2.0); // Scale to between 0 and 255
y += dy; // Increment y
}
x += dx; // Increment x
}
updatePixels();
}
>>
Taken from [[basic/graphing2dequation.html|http://ejohn.org/apps/processing.js/examples/basic/graphing2dequation.html]]
Hue is the color reflected from or transmitted through an object and is typically referred to as the name of the color (red, blue, yellow, etc.) Move the cursor vertically over each bar to alter its hue.
<<Processing
int barWidth = 5;
int[] hue;
void setup()
{
size(400, 400);
colorMode(HSB, 360, height, height);
hue = new int[width/barWidth];
noStroke();
}
void draw()
{
int j = 0;
for (int i=0; i<=(width-barWidth); i+=barWidth) {
if ((mouseX > i) && (mouseX < i+barWidth)) {
hue[j] = mouseY;
}
fill(hue[j], height/1.2, height/1.2);
rect(i, 0, barWidth, height);
j++;
}
}
>>
Taken from [[basic/hue.html|http://ejohn.org/apps/processing.js/examples/basic/hue.html]]
Writing "a++" is equivalent to "a = a + 1". Writing "a--" is equivalent to "a = a - 1".
<<Processing
int a;
int b;
boolean direction;
void setup()
{
size(200, 200);
colorMode(RGB, width);
a = 0;
b = width;
direction = true;
frameRate(30);
}
void draw()
{
a++;
if(a > width) {
a = 0;
direction = !direction;
}
if(direction == true){
stroke(a);
} else {
stroke(width-a);
}
line(a, 0, a, height/2);
b--;
if(b < 0) {
b = width;
}
if(direction == true) {
stroke(width-b);
} else {
stroke(b);
}
line(b, height/2+1, b, height);
}
>>
Taken from [[basic/incrementdecrement.html|http://ejohn.org/apps/processing.js/examples/basic/incrementdecrement.html]]
A class can be defined using another class as a foundation. In object-oriented programming terminology, one class can inherit fi elds and methods from another. An object that inherits from another is called a subclass, and the object it inherits from is called a superclass. A subclass extends the superclass.
<<Processing
SpinSpots spots;
SpinArm arm;
void setup()
{
size(200, 200);
smooth();
arm = new SpinArm(width/2, height/2, 0.01);
spots = new SpinSpots(width/2, height/2, -0.02, 33.0);
}
void draw()
{
background(204);
arm.update();
arm.display();
spots.update();
spots.display();
}
class Spin
{
float x, y, speed;
float angle = 0.0;
Spin(float xpos, float ypos, float s) {
x = xpos;
y = ypos;
speed = s;
}
void update() {
angle += speed;
}
}
class SpinArm extends Spin
{
SpinArm(float x, float y, float s) {
super(x, y, s);
}
void display() {
strokeWeight(1);
stroke(0);
pushMatrix();
translate(x, y);
angle += speed;
rotate(angle);
line(0, 0, 66, 0);
popMatrix();
}
}
class SpinSpots extends Spin
{
float dim;
SpinSpots(float x, float y, float s, float d) {
super(x, y, s);
dim = d;
}
void display() {
noStroke();
pushMatrix();
translate(x, y);
angle += speed;
rotate(angle);
ellipse(-dim/2, 0, dim, dim);
ellipse(dim/2, 0, dim, dim);
popMatrix();
}
}
>>
Taken from [[basic/inheritance.html|http://ejohn.org/apps/processing.js/examples/basic/inheritance.html]]
Integers and floats are two different kinds of numerical data. An integer (more commonly called an int) is a number without a decimal point. A float is a floating-point number, which means it is a number that has a decimal place. Floats are used when more precision is needed.
<<Processing
int a = 0; // Create a variable "a" of the datatype "int"
float b = 0.0; // Create a variable "b" of the datatype "float"
void setup()
{
size(200, 200);
stroke(255);
frameRate(30);
}
void draw()
{
background(51);
a = a + 1;
b = b + 0.2;
line(a, 0, a, height/2);
line(b, height/2, b, height);
if(a > width) {
a = 0;
}
if(b > width) {
b = 0;
}
}
>>
Taken from [[basic/integersfloats.html|http://ejohn.org/apps/processing.js/examples/basic/integersfloats.html]]
Iteration with a "for" structure constructs repetitive forms.
<<Processing
int k;
int xpos1 = 100;
int xpos2 = 118;
int count = 0;
int timey = 0;
int num = 12;
size(200, 200);
background(102);
noStroke();
// Draw gray bars
fill(255);
k=60;
for(int i=0; i < num/3; i++) {
rect(25, k, 155, 5);
k+=10;
}
// Black bars
fill(51);
k = 40;
for(int i=0; i < num; i++) {
rect(105, k, 30, 5);
k += 10;
}
k = 15;
for(int i = 0; i < num; i++) {
rect(125, k, 30, 5);
k +=10;
}
// Thin lines
k = 42;
fill(0);
for(int i=0; i < num-1; i++) {
rect(36, k, 20, 1);
k+=10;
}
>>
Taken from [[basic/iteration.html|http://ejohn.org/apps/processing.js/examples/basic/iteration.html]]
Click on the image to give it focus and press the letter keys to create forms in time and space. Each key has a unique identifying number called it's ASCII value. These numbers can be used to position shapes in space.
<<Processing
int numChars = 26;
color[] colors = new color[numChars];
int keyIndex;
float keyScale;
int rectWidth;
void setup()
{
size(200, 200);
noStroke();
background(0);
keyScale = 200/numChars-1.0;
rectWidth = width/4;
}
void draw()
{
if(keyPressed) {
if(key >= 'A' && key <= 'z') {
if(key <= 'Z') {
keyIndex = key-'A';
} else {
keyIndex = key-'a';
}
fill(millis()%255);
float beginRect = rectWidth/2 + keyIndex*keyScale-rectWidth/2;
rect(beginRect, 0.0, rectWidth, height);
}
}
}
>>
Taken from [[basic/keyboard.html|http://ejohn.org/apps/processing.js/examples/basic/keyboard.html]]
Modified from code by Martin. Original 'Color Typewriter' concept by John Maeda. Click on the window to give it focus and press the letter keys to type colors. The keyboard function keyPressed() is called whenever a key is pressed. keyReleased() is another keyboard function that is called when a key is released.
<<Processing
int max_height = 20;
int min_height = 10;
int letter_height = max_height; // Height of the letters
int letter_width = 10; // Width of the letter
int x = -letter_width; // X position of the letters
int y = 0; // Y position of the letters
boolean newletter;
int numChars = 26; // There are 26 characters in the alphabet
color[] colors = new color[numChars];
void setup()
{
size(200, 200);
noStroke();
colorMode(RGB, numChars);
background(numChars/2);
// Set a gray value for each key
for(int i=0; i<numChars; i++) {
colors[i] = color(i, i, i);
}
}
void draw()
{
if(newletter == true) {
// Draw the "letter"
int y_pos;
if (letter_height == max_height) {
y_pos = y;
rect( x, y_pos, letter_width, letter_height );
} else {
y_pos = y + min_height;
rect( x, y_pos, letter_width, letter_height );
fill(numChars/2);
rect( x, y_pos-min_height, letter_width, letter_height );
}
newletter = false;
}
}
void keyPressed()
{
// if the key is between 'A'(65) and 'z'(122)
if( key >= 'A' && key <= 'z') {
int keyIndex;
if(key <= 'Z') {
keyIndex = key-'A';
letter_height = max_height;
fill(colors[key-'A']);
} else {
keyIndex = key-'a';
letter_height = min_height;
fill(colors[key-'a']);
}
} else {
fill(0);
letter_height = 10;
}
newletter = true;
// Update the "letter" position
x = ( x + letter_width );
// Wrap horizontally
if (x > width - letter_width) {
x = 0;
y+= max_height;
}
// Wrap vertically
if( y > height - letter_height) {
y = 0; // reset y to 0
}
}
>>
Taken from [[basic/keyboardfunctions.html|http://ejohn.org/apps/processing.js/examples/basic/keyboardfunctions.html]]
Drawing letters to the screen in Processing uses a technology developed in the mid 1990s at the Visual Language Workshop at the MIT Media Laboratory. It is a closed system, but we have supplied a number of fonts located in the "font" directory in the main "processing" directory. We expect to change the Processing font technology in the future.
<<Processing
size(200, 200);
background(0);
// Load the font. Fonts are located within the
// main Processing directory/folder and they
// must be placed within the data directory
// of your sketch for them to load
PFont fontA = loadFont("Courier New");
textFont(fontA, 36);
textAlign(CENTER);
// Set the gray value of the letters
fill(255);
// Set the left and top margin
int margin = 6;
int gap = 30;
translate(margin*1.5, margin*2);
// Create a matrix of letterforms
int counter = 0;
for(int i=0; i<margin; i++) {
for(int j=0; j<margin; j++) {
char letter;
// Select the letter
int count = 65+(i*margin)+j;
if(count <= 90) {
letter = char(65+counter);
if(letter == 'A' || letter == 'E' || letter == 'I' ||
letter == 'O' || letter == 'U') {
fill(204, 204, 0);
} else {
fill(255);
}
} else {
fill(153);
letter = char(48+counter);
}
// Draw the letter to the screen
text(letter, 15+j*gap, 20+i*gap);
// Increment the counter
counter++;
if(counter >= 26) {
counter = 0;
}
}
}
>>
Taken from [[basic/letters.html|http://ejohn.org/apps/processing.js/examples/basic/letters.html]]
by Ira Greenberg. Using the convenient red(), green() and blue() component functions, generate some linear gradients.
<<Processing
// constants
int Y_AXIS = 1;
int X_AXIS = 2;
void setup(){
size(200, 200);
// create some gradients
// background
color b1 = color(190, 190, 190);
color b2 = color(20, 20, 20);
//setGradient(0, 0, width, height, b1, b2, Y_AXIS);
//center squares
color c1 = color(255, 120, 0);
color c2 = color(10, 45, 255);
color c3 = color(10, 255, 15);
color c4 = color(125, 2, 140);
color c5 = color(255, 255, 0);
color c6 = color(25, 255, 200);
setGradient(25, 25, 75, 75, c1, c2, Y_AXIS);
setGradient(100, 25, 75, 75, c3, c4, X_AXIS);
setGradient(25, 100, 75, 75, c2, c5, X_AXIS);
setGradient(100, 100, 75, 75, c4, c6, Y_AXIS);
}
void setGradient(int x, int y, float w, float h, color c1, color c2, int axis ){
// calculate differences between color components
float deltaR = red(c2)-red(c1);
float deltaG = green(c2)-green(c1);
float deltaB = blue(c2)-blue(c1);
// choose axis
if(axis == Y_AXIS){
/*nested for loops set pixels
in a basic table structure */
// column
for (int i=x; i<=(x+w); i++){
// row
for (int j = y; j<=(y+h); j++){
color c = color(
(red(c1)+(j-y)*(deltaR/h)),
(green(c1)+(j-y)*(deltaG/h)),
(blue(c1)+(j-y)*(deltaB/h))
);
set(i, j, c);
}
}
}
else if(axis == X_AXIS){
// column
for (int i=y; i<=(y+h); i++){
// row
for (int j = x; j<=(x+w); j++){
color c = color(
(red(c1)+(j-x)*(deltaR/h)),
(green(c1)+(j-x)*(deltaG/h)),
(blue(c1)+(j-x)*(deltaB/h))
);
set(j, i, c);
}
}
}
}
>>
Taken from [[basic/lineargradient.html|http://ejohn.org/apps/processing.js/examples/basic/lineargradient.html]]
The logical operators for AND (&&) and OR (||) are used to combine simple relational statements into more complex expressions. The NOT (!) operator is used to negate a boolean statement.
<<Processing
size(200, 200);
background(126);
boolean op = false;
for(int i=5; i<=195; i+=5) {
// Logical AND
stroke(0);
if((i > 35) && (i < 100)) {
line(5, i, 95, i);
op = false;
}
// Logical OR
stroke(76);
if((i <= 35) || (i >= 100)) {
line(105, i, 195, i);
op = true;
}
// Testing if a boolean value is "true"
// The expression "if(op)" is equivalent to "if(op == true)"
if(op) {
stroke(0);
point(width/2, i);
}
// Testing if a boolean value is "false"
// The expression "if(!op)" is equivalent to "if(op == false)"
if(!op) {
stroke(255);
point(width/4, i);
}
}
>>
Taken from [[basic/logicaloperators.html|http://ejohn.org/apps/processing.js/examples/basic/logicaloperators.html]]
The loop() function causes draw() to execute continuously. If noLoop is called in setup() the draw() is only executed once. In this example click the mouse to execute loop(), which will cause the draw() the execute continuously.
<<Processing
// The statements in the setup() function
// execute once when the program begins
void setup()
{
size(200, 200); // Size should be the first statement
stroke(255); // Set stroke color to white
noLoop();
}
float y = 100;
// The statements in draw() are run until the
// program is stopped. Each statement is run in
// sequence and after the last line is read, the first
// line is run again.
void draw()
{
background(0); // Set the background to black
line(0, y, width, y);
y = y - 1;
if (y < 0) {
y = height;
}
}
void mousePressed()
{
loop();
}
>>
Taken from [[basic/loop.html|http://ejohn.org/apps/processing.js/examples/basic/loop.html]]
A millisecond is 1/1000 of a second. Processing keeps track of the number of milliseconds a program has run. By modifying this number with the modulo(%) operator, different patterns in time are created.
<<Processing
float scale;
void setup()
{
size(200, 200);
noStroke();
scale = width/10;
}
void draw()
{
for(int i=0; i<scale; i++) {
colorMode(RGB, (i+1) * scale * 10);
fill(millis()%((i+1) * scale * 10) );
rect(i*scale, 0, scale, height);
}
}
>>
Taken from [[basic/milliseconds.html|http://ejohn.org/apps/processing.js/examples/basic/milliseconds.html]]
The modulo operator (%) returns the remainder of a number divided by another. As in this example, it is often used to keep numerical values within a set range. Created 12 January 2003.
<<Processing
int num = 20;
float c;
void setup()
{
size(200,200);
fill(255);
frameRate(30);
}
void draw()
{
background(0);
c+=0.1;
for(int i=1; i<height/num; i++) {
float x = (c%i)*i*i;
stroke(102);
line(0, i*num, x, i*num);
noStroke();
rect(x, i*num-num/2, 8, num);
}
}
>>
Taken from [[basic/modulo.html|http://ejohn.org/apps/processing.js/examples/basic/modulo.html]]
Move the mouse left and right to shift the balance. The "mouseX" variable is used to control both the size and color of the rectangles.
<<Processing
int gx = 15;
int gy = 35;
float leftColor = 0.0;
float rightColor = 0.0;
void setup()
{
size(200, 200);
colorMode(RGB, 1.0);
noStroke();
}
void draw()
{
background(0.0);
update(mouseX);
fill(0.0, leftColor + 0.4, leftColor + 0.6);
rect(width/4-gx, width/2-gx, gx*2, gx*2);
fill(0.0, rightColor + 0.2, rightColor + 0.4);
rect(width/1.33-gy, width/2-gy, gy*2, gy*2);
}
void update(int x)
{
leftColor = -0.002 * x/2 + 0.06;
rightColor = 0.002 * x/2 + 0.06;
gx = x/2;
gy = 100-x/2;
if (gx < 10) {
gx = 10;
} else if (gx > 90) {
gx = 90;
}
if (gy > 90) {
gy = 90;
} else if (gy < 10) {
gy = 10;
}
}
>>
Taken from [[basic/mouse1d.html|http://ejohn.org/apps/processing.js/examples/basic/mouse1d.html]]
Moving the mouse changes the position and size of each box.
<<Processing
void setup()
{
size(200, 200);
noStroke();
colorMode(RGB, 255, 255, 255, 100);
rectMode(CENTER);
}
void draw()
{
background(51);
fill(255, 80);
rect(mouseX, height/2, mouseY/2+10, mouseY/2+10);
fill(255, 80);
rect(width-mouseX, height/2, ((height-mouseY)/2)+10, ((height-mouseY)/2)+10);
}
>>
Taken from [[basic/mouse2d.html|http://ejohn.org/apps/processing.js/examples/basic/mouse2d.html]]
Click on the box and drag it across the screen.
<<Processing
float bx;
float by;
int bs = 20;
boolean bover = false;
boolean locked = false;
float bdifx = 0.0;
float bdify = 0.0;
void setup()
{
size(200, 200);
bx = width/2.0;
by = height/2.0;
rectMode(CENTER_RADIUS);
}
void draw()
{
background(0);
// Test if the cursor is over the box
if (mouseX > bx-bs && mouseX < bx+bs &&
mouseY > by-bs && mouseY < by+bs) {
bover = true;
if(!locked) {
stroke(255);
fill(153);
}
} else {
stroke(153);
fill(153);
bover = false;
}
// Draw the box
rect(bx, by, bs, bs);
}
void mousePressed() {
if(bover) {
locked = true;
fill(255, 255, 255);
} else {
locked = false;
}
bdifx = mouseX-bx;
bdify = mouseY-by;
}
void mouseDragged() {
if(locked) {
bx = mouseX-bdifx;
by = mouseY-bdify;
}
}
void mouseReleased() {
locked = false;
}
>>
Taken from [[basic/mousefunctions.html|http://ejohn.org/apps/processing.js/examples/basic/mousefunctions.html]]
Move the mouse to position the shape. Press the mouse button to invert the color.
<<Processing
void setup() {
size(200, 200);
fill(126);
background(102);
}
void draw() {
if(mousePressed) {
stroke(255);
} else {
stroke(0);
}
line(mouseX-66, mouseY, mouseX+66, mouseY);
line(mouseX, mouseY-66, mouseX, mouseY+66);
}
>>
Taken from [[basic/mousepress.html|http://ejohn.org/apps/processing.js/examples/basic/mousepress.html]]
Move and click the mouse to generate signals. The top row is the signal from "mouseX", the middle row is the signal from "mouseY", and the bottom row is the signal from "mousePressed".
<<Processing
int[] xvals;
int[] yvals;
int[] bvals;
void setup()
{
size(200, 200);
xvals = new int[width];
yvals = new int[width];
bvals = new int[width];
}
int arrayindex = 0;
void draw()
{
background(102);
for(int i=1; i<width; i++) {
xvals[i-1] = xvals[i];
yvals[i-1] = yvals[i];
bvals[i-1] = bvals[i];
}
// Add the new values to the end of the array
xvals[width-1] = mouseX;
yvals[width-1] = mouseY;
if(mousePressed) {
bvals[width-1] = 0;
} else {
bvals[width-1] = 255;
}
fill(255);
noStroke();
rect(0, height/3, width, height/3+1);
for(int i=1; i<width; i++) {
stroke(255);
point(i, xvals[i]/3);
stroke(0);
point(i, height/3+yvals[i]/3);
stroke(255);
line(i, 2*height/3+bvals[i]/3, i, (2*height/3+bvals[i-1]/3));
}
}
>>
Taken from [[basic/mousesignals.html|http://ejohn.org/apps/processing.js/examples/basic/mousesignals.html]]
A class can have multiple constructors that assign the fields in different ways. Sometimes it's beneficial to specify every aspect of an objectÕs data by assigning parameters to the fields, but other times it might be appropriate to define only one or a few.
<<Processing
Spot sp1, sp2;
void setup()
{
size(200, 200);
background(204);
smooth();
noLoop();
// Run the constructor without parameters
sp1 = new Spot();
// Run the constructor with three parameters
sp2 = new Spot(122, 100, 40);
}
void draw() {
sp1.display();
sp2.display();
}
class Spot {
float x, y, radius;
// First version of the Spot constructor;
// the fields are assigned default values
Spot() {
x = 66;
y = 100;
radius = 16;
}
// Second version of the Spot constructor;
// the fields are assigned with parameters
Spot(float xpos, float ypos, float r) {
x = xpos;
y = ypos;
radius = r;
}
void display() {
ellipse(x, y, radius*2, radius*2);
}
}
>>
Taken from [[basic/multipleconstructors.html|http://ejohn.org/apps/processing.js/examples/basic/multipleconstructors.html]]
By Ira Greenberg Draw a neighborhood of houses using Door, Window, Roof and House classes. Good example of class composition, with component Door, Window, Roof class references encapsulated within House class. This arrangement allows House class to handle placement and sizing of its components, while still allowing user customization of the individual components.
<<Processing
void setup(){
size(200, 200);
background(190);
smooth();
// Ground plane
int groundHeight = 10;
fill(0);
rect(0, height-groundHeight, width, groundHeight);
fill(255);
// Center the houses
translate(12, 0);
// Houses
Door door1 = new Door(20, 40);
Window window1 = new Window(50, 62, false, Window.DOUBLE);
Roof roof1 = new Roof(Roof.DOME);
House house1 = new House(75, 75, door1, window1, roof1, House.MIDDLE_DOOR);
house1.drawHouse(0, height-groundHeight-house1.h, true);
Door door2 = new Door(20, 40);
Window window2 = new Window(50, 62, true, Window.QUAD);
Roof roof2 = new Roof(Roof.GAMBREL);
House house2 = new House(100, 60, door2, window2, roof2, House.LEFT_DOOR);
house2.drawHouse(house1.x + house1.w, height-groundHeight-house2.h, true);
}
class Door{
//door properties
int x;
int y;
int w;
int h;
// for knob
int knobLoc = 1;
//constants
final static int RT = 0;
final static int LFT = 1;
// constructor
Door(int w, int h){
this.w = w;
this.h = h;
}
// draw the door
void drawDoor(int x, int y) {
rect(x, y, w, h);
int knobsize = w/10;
if (knobLoc == 0){
//right side
ellipse(x+w-knobsize, y+h/2, knobsize, knobsize);
}
else {
//left side
ellipse(x+knobsize, y+h/2, knobsize, knobsize);
}
}
// set knob position
void setKnob(int knobLoc){
this. knobLoc = knobLoc;
}
}
class Window{
//window properties
int x;
int y;
int w;
int h;
// customized features
boolean hasSash = false;
// single, double, quad pane
int style = 0;
//constants
final static int SINGLE = 0;
final static int DOUBLE = 1;
final static int QUAD = 2;
// constructor 1
Window(int w, int h){
this.w = w;
this.h = h;
}
// constructor 2
Window(int w, int h, int style){
this.w = w;
this.h = h;
this.style = style;
}
// constructor 3
Window(int w, int h, boolean hasSash, int style){
this.w = w;
this.h = h;
this.hasSash = hasSash;
this.style = style;
}
// draw the window
void drawWindow(int x, int y) {
//local variables
int margin = 0;
int winHt = 0;
int winWdth = 0;
if (hasSash){
margin = w/15;
}
switch(style){
case 0:
//outer window (sash)
rect(x, y, w, h);
//inner window
rect(x+margin, y+margin, w-margin*2, h-margin*2);
break;
case 1:
winHt = (h-margin*3)/2;
//outer window (sash)
rect(x, y, w, h);
//inner window (top)
rect(x+margin, y+margin, w-margin*2, winHt);
//inner windows (bottom)
rect(x+margin, y+winHt+margin*2, w-margin*2, winHt);
break;
case 2:
winWdth = (w-margin*3)/2;
winHt = (h-margin*3)/2;
//outer window (sash)
rect(x, y, w, h);
//inner window (top-left)
rect(x+margin, y+margin, winWdth, winHt);
//inner window (top-right)
rect(x+winWdth+margin*2, y+margin, winWdth, winHt);
//inner windows (bottom-left)
rect(x+margin, y+winHt+margin*2, winWdth, winHt);
//inner windows (bottom-right)
rect(x+winWdth+margin*2, y+winHt+margin*2, winWdth, winHt);
break;
}
}
// set window style (number of panes)
void setStyle(int style){
this.style = style;
}
}
class Roof{
//roof properties
int x;
int y;
int w;
int h;
// roof style
int style = 0;
//constants
final static int CATHEDRAL = 0;
final static int GAMBREL = 1;
final static int DOME = 2;
// default constructor
Roof(){
}
// constructor 2
Roof(int style){
this.style = style;
}
// draw the roof
void drawRoof(int x, int y, int w, int h) {
switch(style){
case 0:
beginShape();
vertex(x, y);
vertex(x+w/2, y-h/3);
vertex(x+w, y);
endShape(CLOSE);
break;
case 1:
beginShape();
vertex(x, y);
vertex(x+w/7, y-h/4);
vertex(x+w/2, y-h/2);
vertex(x+(w-w/7), y-h/4);
vertex(x+w, y);
endShape(CLOSE);
break;
case 2:
ellipseMode(CORNER);
arc(x, y-h/2, w, h, PI, TWO_PI);
line(x, y, x+w, y);
break;
}
}
// set roof style
void setStyle(int style){
this.style = style;
}
}
class House{
//house properties
int x;
int y;
int w;
int h;
//component reference variables
Door door;
Window window;
Roof roof;
//optional autosize variable
boolean AutoSizeComponents = false;
//door placement
int doorLoc = 0;
//constants
final static int MIDDLE_DOOR = 0;
final static int LEFT_DOOR = 1;
final static int RIGHT_DOOR = 2;
//constructor
House(int w, int h, Door door, Window window, Roof roof, int doorLoc) {
this.w = w;
this.h = h;
this.door = door;
this.window = window;
this.roof = roof;
this.doorLoc = doorLoc;
}
void drawHouse(int x, int y, boolean AutoSizeComponents) {
this.x = x;
this.y =y;
this.AutoSizeComponents = AutoSizeComponents;
//automatically sizes doors and windows
if(AutoSizeComponents){
//autosize door
door.h = h/4;
door.w = door.h/2;
//autosize windows
window.h = h/3;
window.w = window.h/2;
}
// draw bldg block
rect(x, y, w, h);
// draw door
switch(doorLoc){
case 0:
door.drawDoor(x+w/2-door.w/2, y+h-door.h);
break;
case 1:
door.drawDoor(x+w/8, y+h-door.h);
break;
case 2:
door.drawDoor(x+w-w/8-door.w, y+h-door.h);
break;
}
// draw windows
int windowMargin = (w-window.w*2)/3;
window.drawWindow(x+windowMargin, y+h/6);
window.drawWindow(x+windowMargin*2+window.w, y+h/6);
// draw roof
roof.drawRoof(x, y, w, h);
}
// catch drawHouse method without boolean argument
void drawHouse(int x, int y){
// recall with required 3rd argument
drawHouse(x, y, false);
}
}
>>
Taken from [[basic/neighborhood.html|http://ejohn.org/apps/processing.js/examples/basic/neighborhood.html]]
The noLoop() function causes draw() to only execute once. Without calling noLoop(), draw() executed continually.
<<Processing
// The statements in the setup() function
// execute once when the program begins
void setup()
{
size(200, 200); // Size should be the first statement
stroke(255); // Set line drawing color to white
frameRate(30);
noLoop();
}
float y = 100;
// The statements in draw() are executed until the
// program is stopped. Each statement is executed in
// sequence and after the last line is read, the first
// line is executed again.
void draw()
{
background(0); // Set the background to black
y = y - 1;
if (y < 0) { y = height; }
line(0, y, width, y);
}
>>
Taken from [[basic/noloop.html|http://ejohn.org/apps/processing.js/examples/basic/noloop.html]]
Using 1D Perlin Noise to assign location.
<<Processing
float xoff = 0.0;
float xincrement = 0.01;
void setup() {
size(200,200);
background(0);
frameRate(30);
smooth();
noStroke();
}
void draw()
{
// Create an alpha blended background
fill(0, 10);
rect(0,0,width,height);
//float n = random(0,width); // Try this line instead of noise
// Get a noise value based on xoff and scale it according to the window's width
float n = noise(xoff)*width;
// With each cycle, increment xoff
xoff += xincrement;
// Draw the ellipse at the value produced by perlin noise
fill(200);
ellipse(n,height/2,16,16);
}
>>
Taken from [[basic/noise1d.html|http://ejohn.org/apps/processing.js/examples/basic/noise1d.html]]
by Daniel Shiffman. Using 2D noise to create simple texture.
<<Processing
float increment = 0.02;
void setup() {
size(100,100);
noLoop();
}
void draw() {
background(0);
// Optional: adjust noise detail here
// noiseDetail(8,0.65f);
loadPixels();
float xoff = 0.0; // Start xoff at 0
// For every x,y coordinate in a 2D space, calculate a noise value and produce a brightness value
for (int x = 0; x < width; x++) {
xoff += increment; // Increment xoff
float yoff = 0.0; // For every xoff, start yoff at 0
for (int y = 0; y < height; y++) {
yoff += increment; // Increment yoff
// Calculate noise and scale by 255
//float bright = noise(xoff,yoff)*255;
// Try using this line instead
float bright = random(0,255);
// Set each pixel onscreen to a grayscale value
pixels[x+y*width] = color(bright);
}
}
updatePixels();
}
>>
Taken from [[basic/noise2d.html|http://ejohn.org/apps/processing.js/examples/basic/noise2d.html]]
Using 3D noise to create simple animated texture. Here, the third dimension ('z') is treated as time.
<<Processing
float increment = 0.01;
// The noise function's 3rd argument, a global variable that increments once per cycle
float zoff = 0.0;
// We will increment zoff differently than xoff and yoff
float zincrement = 0.02;
void setup() {
size(50,50);
frameRate(30);
}
void draw() {
background(0);
// Optional: adjust noise detail here
// noiseDetail(8,0.65f);
loadPixels();
float xoff = 0.0; // Start xoff at 0
// For every x,y coordinate in a 2D space, calculate a noise value and produce a brightness value
for (int x = 0; x < width; x++) {
xoff += increment; // Increment xoff
float yoff = 0.0f; // For every xoff, start yoff at 0
for (int y = 0; y < height; y++) {
yoff += increment; // Increment yoff
// Calculate noise and scale by 255
//float bright = noise(xoff,yoff,zoff)*255;
// Try using this line instead
float bright = random(0,255);
// Set each pixel onscreen to a grayscale value
pixels[x+y*width] = color(bright,bright,bright);
}
}
updatePixels();
zoff += zincrement; // Increment zoff
}
>>
Taken from [[basic/noise3d.html|http://ejohn.org/apps/processing.js/examples/basic/noise3d.html]]
by Daniel Shiffman. Using Perlin Noise to generate a wave-like pattern.
<<Processing
int xspacing = 8; // How far apart should each horizontal location be spaced
int w; // Width of entire wave
float yoff = 0.0f; // 2nd dimension of perlin noise
float[] yvalues; // Using an array to store height values for the wave (not entirely necessary)
void setup() {
size(200,200);
frameRate(30);
colorMode(RGB,255,255,255,100);
smooth();
w = width+16;
yvalues = new float[w/xspacing];
}
void draw() {
background(0);
calcWave();
renderWave();
}
void calcWave() {
float dx = 0.05f;
float dy = 0.01f;
float amplitude = 100.0f;
// Increment y ('time')
yoff += dy;
//float xoff = 0.0; // Option #1
float xoff = yoff; // Option #2
for (int i = 0; i < yvalues.length; i++) {
// Using 2D noise function
//yvalues[i] = (2*noise(xoff,yoff)-1)*amplitude; // Option #1
// Using 1D noise function
yvalues[i] = (2*noise(xoff)-1)*amplitude; // Option #2
xoff+=dx;
}
}
void renderWave() {
// A simple way to draw the wave with an ellipse at each location
for (int x = 0; x < yvalues.length; x++) {
noStroke();
fill(255,50);
ellipseMode(CENTER);
ellipse(x*xspacing,width/2+yvalues[x],16,16);
}
}
>>
Taken from [[basic/noisewave.html|http://ejohn.org/apps/processing.js/examples/basic/noisewave.html]]
by hbarragan Move the cursor across the image to change the speed and positions of the geometry. The class MRect defines a group of lines.
<<Processing
MRect r1, r2, r3, r4;
void setup()
{
size(200, 200);
fill(255, 204);
noStroke();
r1 = new MRect(1, 134.0, 0.532, 0.083*height, 10.0, 60.0);
r2 = new MRect(2, 44.0, 0.166, 0.332*height, 5.0, 50.0);
r3 = new MRect(2, 58.0, 0.332, 0.4482*height, 10.0, 35.0);
r4 = new MRect(1, 120.0, 0.0498, 0.913*height, 15.0, 60.0);
}
void draw()
{
background(0);
r1.display();
r2.display();
r3.display();
r4.display();
r1.move(mouseX-(width/2), mouseY+(height*0.1), 30);
r2.move((mouseX+(width*0.05))%width, mouseY+(height*0.025), 20);
r3.move(mouseX/4, mouseY-(height*0.025), 40);
r4.move(mouseX-(width/2), (height-mouseY), 50);
}
class MRect
{
int w; // single bar width
float xpos; // rect xposition
float h; // rect height
float ypos ; // rect yposition
float d; // single bar distance
float t; // number of bars
MRect(int iw, float ixp, float ih, float iyp, float id, float it) {
w = iw;
xpos = ixp;
h = ih;
ypos = iyp;
d = id;
t = it;
}
void move (float posX, float posY, float damping) {
float dif = ypos - posY;
if (abs(dif) > 1) {
ypos -= dif/damping;
}
dif = xpos - posX;
if (abs(dif) > 1) {
xpos -= dif/damping;
}
}
void display() {
for (int i=0; i<t; i++) {
rect(xpos+(i*(d+w)), ypos, w, height*h);
}
}
}
>>
Taken from [[basic/objects.html|http://ejohn.org/apps/processing.js/examples/basic/objects.html]]
<<Processing '
// All Examples Written by Casey Reas and Ben Fry
// unless otherwise stated.
void setup()
{
size(200, 200);
background(102);
smooth();
}
void draw()
{
// Call the variableEllipse() method and send it the
// parameters for the current mouse position
// and the previous mouse position
variableEllipse(mouseX, mouseY, pmouseX, pmouseY);
}
// The simple method variableEllipse() was created specifically
// for this program. It calculates the speed of the mouse
// and draws a small ellipse if the mouse is moving slowly
// and draws a large ellipse if the mouse is moving quickly
void variableEllipse(int x, int y, int px, int py)
{
float speed = abs(x-px) + abs(y-py);
stroke(speed);
ellipse(x, y, speed, speed);
}
'>>
By Ira Greenberg Uses the arc() function to generate a pie chart from the data stored in an array.
<<Processing
size(200, 200);
background(100);
smooth();
noStroke();
int diameter = 150;
int[] angs = {30, 10, 45, 35, 60, 38, 75, 67};
float lastAng = 0;
for (int i=0; i<angs.length; i++){
fill(angs[i] * 3.0);
arc(width/2, height/2, diameter, diameter, lastAng, lastAng+radians(angs[i]));
lastAng += radians(angs[i]);
}
>>
Taken from [[basic/piechart.html|http://ejohn.org/apps/processing.js/examples/basic/piechart.html]]
by Daniel Shiffman. Mouse horizontal location controls size of dots. Creates a simple pointillist effect using ellipses colored according to pixels in an image.
<<Processing
PImage a;
void setup()
{
a = loadImage("eames.jpg");
size(200,200);
noStroke();
background(255);
smooth();
}
void draw()
{
float pointillize = map(mouseX, 0, width, 2, 18);
int x = int(random(a.width));
int y = int(random(a.height));
color pix = a.get(x, y);
fill(pix, 126);
ellipse(x, y, pointillize, pointillize);
}
>>
Taken from [[basic/pointillism.html|http://ejohn.org/apps/processing.js/examples/basic/pointillism.html]]
Constructing a simple dimensional form with lines and rectangles. Changing the value of the variable 'd' scales the image. The four variables set the positions based on the value of 'd'.
<<Processing
int d = 40;
int p1 = d;
int p2 = p1+d;
int p3 = p2+d;
int p4 = p3+d;
size(200, 200);
background(0);
// Draw gray box
stroke(153);
line(p3, p3, p2, p3);
line(p2, p3, p2, p2);
line(p2, p2, p3, p2);
line(p3, p2, p3, p3);
// Draw white points
stroke(255);
point(p1, p1);
point(p1, p3);
point(p2, p4);
point(p3, p1);
point(p4, p2);
point(p4, p4);
>>
Taken from [[basic/pointslines.html|http://ejohn.org/apps/processing.js/examples/basic/pointslines.html]]
by Ira Greenberg. Using the convenient red(), green() and blue() component functions, generate an array of radial gradients.
<<Processing
void setup(){
size(50, 50);
background(0);
smooth();
// create a simple table of gradients
int columns = 1;
//int radius = (width/columns)/2;
int radius = width/2;
// create some gradients
for (int i=radius; i< width; i+=radius*2){
for (int j =radius; j< height; j+=radius*2){
createGradient(i, j, radius,
color(int(random(255)), int(random(255)), int(random(255))),
color(int(random(255)), int(random(255)), int(random(255))));
}
}
}
void createGradient (float x, float y, float radius, color c1, color c2){
float px = 0, py = 0, angle = 0;
// calculate differences between color components
float deltaR = red(c2)-red(c1);
float deltaG = green(c2)-green(c1);
float deltaB = blue(c2)-blue(c1);
// hack to ensure there are no holes in gradient
// needs to be increased, as radius increases
float gapFiller = 8.0;
for (int i=0; i< radius; i++){
for (float j=0; j<360; j+=1.0/gapFiller){
px = x+cos(radians(angle))*i;
py = y+sin(radians(angle))*i;
angle+=1.0/gapFiller;
color c = color(
(red(c1)+(i)*(deltaR/radius)),
(green(c1)+(i)*(deltaG/radius)),
(blue(c1)+(i)*(deltaB/radius))
);
set(int(px), int(py), c);
}
}
// adds smooth edge
// hack anti-aliasing
noFill();
strokeWeight(3);
ellipse(x, y, radius*2, radius*2);
}
>>
Taken from [[basic/radialgradient.html|http://ejohn.org/apps/processing.js/examples/basic/radialgradient.html]]
Random numbers create the basis of this image. Each time the program is loaded the result is different.
<<Processing
size(200, 200);
smooth();
background(0);
strokeWeight(10);
for(int i = 0; i < width; i++) {
float r = random(255);
float x = random(0, width);
stroke(r, 100);
line(i, 0, x, height);
}
>>
Taken from [[basic/random.html|http://ejohn.org/apps/processing.js/examples/basic/random.html]]
An image is recreated from its individual component colors. The many colors of the image are created through modulating the red, green, and blue values. This is an exageration of an LCD display.
<<Processing
size(200, 200);
noStroke();
background(0);
// Load an image from the data directory
PImage c;
c = loadImage("cait.jpg");
int xoff = 0;
int yoff = 0;
int p = 2;
int pix = p*3;
for(int i = 0; i < c.width*c.height; i += 1)
{
int here = c.pixels[i];
fill(red(here), 0, 0);
rect(xoff, yoff, p, pix);
fill(0, green(here), 0);
rect(xoff+p, yoff, p, pix);
fill(0, 0, blue(here));
rect(xoff+p*2, yoff, p, pix);
xoff+=pix;
if(xoff >= width-pix) {
xoff = 0;
yoff += pix;
}
}
>>
Taken from [[basic/reading.html|http://ejohn.org/apps/processing.js/examples/basic/reading.html]]
A demonstration of recursion, which means functions call themselves. Notice how the drawCircle() function calls itself at the end of its block. It continues to do this until the variable "level" is equal to 1.
<<Processing
void setup()
{
size(200, 200);
noStroke();
smooth();
noLoop();
}
void draw()
{
drawCircle(126, 170, 6);
}
void drawCircle(int x, int radius, int level)
{
float tt = 126 * level/4.0;
fill(tt);
ellipse(x, 100, radius*2, radius*2);
if(level > 1) {
level = level - 1;
drawCircle(x - radius/2, radius/2, level);
drawCircle(x + radius/2, radius/2, level);
}
}
>>
Taken from [[basic/recursion.html|http://ejohn.org/apps/processing.js/examples/basic/recursion.html]]
A demonstration of recursion, which means functions call themselves. Notice how the drawCircle() function calls itself at the end of its block. It continues to do this until the variable "level" is equal to 1.
<<Processing
void setup()
{
size(200, 200);
noStroke();
smooth();
drawCircle(100, 100, 80, 8);
}
void drawCircle(float x, float y, int radius, int level)
{
float tt = 126 * level/6.0;
fill(tt, 153);
ellipse(x, y, radius*2, radius*2);
if(level > 1) {
level = level - 1;
int num = int(random(2, 6));
for(int i=0; i<num; i++) {
float a = random(0, TWO_PI);
float nx = x + cos(a) * 6.0 * level;
float ny = y + sin(a) * 6.0 * level;
drawCircle(nx, ny, radius/2, level);
}
}
}
>>
Taken from [[basic/recursion2.html|http://ejohn.org/apps/processing.js/examples/basic/recursion2.html]]
The redraw() function makes draw() execute once. In this example, draw() is executed once every time the mouse is clicked.
<<Processing
// The statements in the setup() function
// execute once when the program begins
void setup()
{
size(200, 200); // Size should be the first statement
stroke(255); // Set line drawing color to white
noLoop();
}
float y = 100;
// The statements in draw() are executed until the
// program is stopped. Each statement is executed in
// sequence and after the last line is read, the first
// line is executed again.
void draw()
{
background(0); // Set the background to black
y = y - 1;
if (y < 0) { y = height; }
line(0, y, width, y);
}
void mousePressed()
{
redraw();
}
>>
Taken from [[basic/redraw.html|http://ejohn.org/apps/processing.js/examples/basic/redraw.html]]
Each color is perceived in relation to other colors. The top and bottom bars each contain the same component colors, but a different display order causes individual colors to appear differently.
<<Processing
color a, b, c, d, e;
void setup() {
size(200, 200);
noStroke();
a = color(165, 167, 20);
b = color(77, 86, 59);
c = color(42, 106, 105);
d = color(165, 89, 20);
e = color(146, 150, 127);
noLoop();
}
void draw() {
drawBand(a, b, c, d, e, 0, 4);
drawBand(c, a, d, b, e, height/2, 4);
}
void drawBand(color v, color w, color x, color y, color z, int ypos, int barWidth) {
int num = 5;
color[] colorOrder = { v, w, x, y, z };
for(int i = 0; i < width; i += barWidth*num) {
for(int j = 0; j < num; j++) {
fill(colorOrder[j]);
rect(i+j*barWidth, ypos, barWidth, height/2);
}
}
}
>>
Taken from [[basic/relativity.html|http://ejohn.org/apps/processing.js/examples/basic/relativity.html]]
Rotating a square around the Z axis. To get the results you expect, send the rotate function angle parameters that are values between 0 and PI*2 (TWO_PI which is roughly 6.28). If you prefer to think about angles as degrees (0-360), you can use the radians() method to convert your values. For example: scale(radians(90)) is identical to the statement scale(PI/2).
<<Processing
void setup()
{
size(200,200);
noStroke();
fill(255);
frameRate(30);
}
float angle;
float cosine;
float jitter;
void draw()
{
background(102);
if(second()%2 == 0){
jitter = (random(-0.1, 0.1));
}
angle = angle + jitter;
cosine = cos(angle);
translate(width/2, height/2);
rotate(cosine);
rectMode(CENTER);
rect(0, 0, 115, 115);
}
>>
Taken from [[basic/rotate.html|http://ejohn.org/apps/processing.js/examples/basic/rotate.html]]
Saturation is the strength or purity of the color and represents the amount of gray in proportion to the hue. A "saturated" color is pure and an "unsaturated" color has a large percentage of gray. Move the cursor vertically over each bar to alter its saturation.
<<Processing
int barWidth = 5;
int[] saturation;
void setup()
{
size(200, 200);
colorMode(HSB, 360, height, height);
saturation = new int[width/barWidth];
}
void draw()
{
int j = 0;
for (int i=0; i<=(width-barWidth); i+=barWidth) {
noStroke();
if ((mouseX > i) && (mouseX < i+barWidth)) {
saturation[j] = mouseY;
}
fill(i, saturation[j], height/1.5);
rect(i, 0, barWidth, height);
j++;
}
}
>>
Taken from [[basic/saturation.html|http://ejohn.org/apps/processing.js/examples/basic/saturation.html]]
by Denis Grutze. Paramenters for the scale() function are values specified as decimal percentages. For example, the method call scale(2.0) will increase the dimension of the shape by 200 percent. Objects always scale from the origin.
<<Processing
float a = 0.0;
float s = 0.0;
void setup()
{
size(200,200);
noStroke();
rectMode(CENTER);
frameRate(30);
}
void draw()
{
background(102);
a = a + 0.04;
s = cos(a)*2;
translate(width/2, height/2);
scale(s);
fill(51);
rect(0, 0, 50, 50);
translate(75, 0);
fill(255);
scale(s);
rect(0, 0, 50, 50);
}
>>
Taken from [[basic/scale.html|http://ejohn.org/apps/processing.js/examples/basic/scale.html]]
The draw() function creates a structure in which to write programs that change with time.
<<Processing
// The statements in the setup() function
// execute once when the program begins
void setup()
{
size(200, 200); // Size should be the first statement
stroke(255); // Set line drawing color to white
frameRate(30);
}
float y = 100;
// The statements in draw() are executed until the
// program is stopped. Each statement is executed in
// sequence and after the last line is read, the first
// line is executed again.
void draw()
{
background(0); // Set the background to black
y = y - 1;
if (y < 0) { y = height; }
line(0, y, width, y);
}
>>
Taken from [[basic/setupdraw.html|http://ejohn.org/apps/processing.js/examples/basic/setupdraw.html]]
Simple curves are drawn with simple equations. By using numbers with values between 0 and 1 in the equations, a series of elegant curves are created. The numbers are then scaled to fill the screen.
<<Processing
void setup() {
size(200, 200);
colorMode(RGB, 100);
background(0);
noFill();
noLoop();
}
void draw() {
stroke(40);
beginShape();
for(int i=0; i<width; i++) {
vertex(i, singraph((float)i/width)*height);
}
endShape();
stroke(55);
beginShape();
for(int i=0; i<width; i++) {
vertex(i, quad((float)i/width)*height);
}
endShape();
stroke(70);
beginShape();
for(int i=0; i<width; i++) {
vertex(i, quadHump((float)i/width)*height);
}
endShape();
stroke(85);
beginShape();
for(int i=0; i<width; i++) {
vertex(i, hump((float)i/width)*height);
}
endShape();
stroke(100);
beginShape();
for(int i=0; i<width; i++) {
vertex(i, squared((float)i/width)*height);
}
endShape();
}
float singraph(float sa) {
sa = (sa - 0.5) * 1.0; //scale from -1 to 1
sa = sin(sa*PI)/2 + 0.5;
return sa;
}
float quad(float sa) {
return sa*sa*sa*sa;
}
float quadHump(float sa) {
sa = (sa - 0.5); //scale from -2 to 2
sa = sa*sa*sa*sa * 16;
return sa;
}
float hump(float sa) {
sa = (sa - 0.5) * 2; //scale from -2 to 2
sa = sa*sa;
if(sa > 1) { sa = 1; }
return 1-sa;
}
float squared(float sa) {
sa = sa*sa;
return sa;
}
>>
Taken from [[basic/simplecurves.html|http://ejohn.org/apps/processing.js/examples/basic/simplecurves.html]]
Smoothly scaling size with the sin() function.
<<Processing
float spin = 0.0;
float diameter = 84.0;
float angle;
float angle_rot;
int rad_points = 90;
void setup()
{
size(200, 200);
noStroke();
smooth();
}
void draw()
{
background(153);
translate(130, 65);
fill(255);
ellipse(0, 0, 16, 16);
angle_rot = 0;
fill(51);
for(int i=0; i<5; i++) {
pushMatrix();
rotate(angle_rot + -45);
ellipse(-116, 0, diameter, diameter);
popMatrix();
angle_rot += PI*2/5;
}
diameter = 34 * sin(angle) + 168;
angle += 0.02;
if (angle > TWO_PI) { angle = 0; }
}
>>
Taken from [[basic/sine.html|http://ejohn.org/apps/processing.js/examples/basic/sine.html]]
Linear movement with sin() and cos(). Numbers between 0 and PI*2 (TWO_PI which is roughly 6.28) are put into these functions and numbers between -1 and 1 are returned. These values are then scaled to produce larger movements.
<<Processing
int i = 45;
int j = 225;
float pos1 = 0;
float pos2 = 0;
float pos3 = 0;
float pos4 = 0;
int sc = 40;
void setup()
{
size(200, 200);
noStroke();
smooth();
}
void draw()
{
background(0);
fill(51);
rect(60, 60, 80, 80);
fill(255);
ellipse(pos1, 36, 32, 32);
fill(153);
ellipse(36, pos2, 32, 32);
fill(255);
ellipse(pos3, 164, 32, 32);
fill(153);
ellipse(164, pos4, 32, 32);
i += 3;
j -= 3;
if(i > 405) {
i = 45;
j = 225;
}
float ang1 = radians(i); // convert degrees to radians
float ang2 = radians(j); // convert degrees to radians
pos1 = width/2 + (sc * cos(ang1));
pos2 = width/2 + (sc * sin(ang1));
pos3 = width/2 + (sc * cos(ang2));
pos4 = width/2 + (sc * sin(ang2));
}
>>
Taken from [[basic/sinecosine.html|http://ejohn.org/apps/processing.js/examples/basic/sinecosine.html]]
by Daniel Shiffman. Render a simple sine wave.
<<Processing
int xspacing = 8; // How far apart should each horizontal location be spaced
int w; // Width of entire wave
float theta = 0.0; // Start angle at 0
float amplitude = 75.0; // Height of wave
float period = 500.0; // How many pixels before the wave repeats
float dx; // Value for incrementing X, to be calculated as a function of period and xspacing
float[] yvalues; // Using an array to store height values for the wave (not entirely necessary)
void setup() {
size(200,200);
frameRate(30);
colorMode(RGB,255,255,255,100);
smooth();
w = width+16;
dx = (TWO_PI / period) * xspacing;
yvalues = new float[w/xspacing];
}
void draw() {
background(0);
calcWave();
renderWave();
}
void calcWave() {
// Increment theta (try different values for 'angular velocity' here
theta += 0.02;
// For every x value, calculate a y value with sine function
float x = theta;
for (int i = 0; i < yvalues.length; i++) {
yvalues[i] = sin(x)*amplitude;
x+=dx;
}
}
void renderWave() {
// A simple way to draw the wave with an ellipse at each location
for (int x = 0; x < yvalues.length; x++) {
noStroke();
fill(255,50);
ellipseMode(CENTER);
ellipse(x*xspacing,width/2+yvalues[x],16,16);
}
}
>>
Taken from [[basic/sinewave.html|http://ejohn.org/apps/processing.js/examples/basic/sinewave.html]]
by <a href="http://www.presstube.com">James Patterson</a>. Demonstrates loading and displaying a transparent GIF image. Created 27 January 2003.
<<Processing
PImage teddy;
float xpos;
float ypos;
float drag = 30.0;
void setup()
{
size(200,200);
teddy = loadImage("teddy.gif");
xpos = width/2;
ypos = height/2;
frameRate(60);
}
void draw()
{
background(102);
float difx = mouseX - xpos-teddy.width/2;
if(abs(difx) > 1.0) {
xpos = xpos + difx/drag;
xpos = constrain(xpos, 0, width-teddy.width);
}
float dify = mouseY - ypos-teddy.height/2;
if(abs(dify) > 1.0) {
ypos = ypos + dify/drag;
ypos = constrain(ypos, 0, height-teddy.height);
}
// Display the sprite at the position xpos, ypos
image(teddy, xpos, ypos);
}
>>
Taken from [[basic/sprite.html|http://ejohn.org/apps/processing.js/examples/basic/sprite.html]]
Statements are the elements that make up programs. The ";" (semi-colon) symbol is used to end statements. It is called the "statement terminator." Comments are used for making notes to help people better understand programs. A comment begins with two forward slashes ("//").
<<Processing
// The size function is a statement that tells the computer
// how large to make the window.
// Each function statement has zero or more parameters.
// Parameters are data passed into the function
// and used as values for specifying what the computer will do.
size(200, 200);
// The background function is a statement that tells the computer
// which color to make the background of the window
background(102);
>>
Taken from [[basic/statementscomments.html|http://ejohn.org/apps/processing.js/examples/basic/statementscomments.html]]
Move the mouse across the screen to change the position of the circles. The positions of the mouse are recorded into an array and played back every frame. Between each frame, the newest value are added to the end of each array and the oldest value is deleted.
<<Processing
int num = 60;
float mx[] = new float[num];
float my[] = new float[num];
void setup()
{
size(200, 200);
smooth();
noStroke();
fill(255, 153);
}
void draw()
{
background(51);
// Reads throught the entire array
// and shifts the values to the left
for(int i=1; i<num; i++) {
mx[i-1] = mx[i];
my[i-1] = my[i];
}
// Add the new values to the end of the array
mx[num-1] = mouseX;
my[num-1] = mouseY;
for(int i=0; i<num; i++) {
ellipse(mx[i], my[i], i/2, i/2);
}
}
>>
Taken from [[basic/storinginput.html|http://ejohn.org/apps/processing.js/examples/basic/storinginput.html]]
The translate() function allows objects to be moved to any location within the window. The first parameter sets the x-axis offset and the second parameter sets the y-axis offset.
<<Processing
float x, y;
float s = 40.0;
void setup()
{
size(200,200);
noStroke();
frameRate(30);
}
void draw()
{
background(102);
x = x + 0.8;
if (x > width + s) {
x = -s;
}
translate(x, height/2-s/2);
fill(255);
rect(-s/2, -s/2, s, s);
// Transforms accumulate.
// Notice how this rect moves twice
// as fast as the other, but it has
// the same parameter for the x-axis value
translate(x, s);
fill(0);
rect(-s/2, -s/2, s, s);
}
>>
Taken from [[basic/translate.html|http://ejohn.org/apps/processing.js/examples/basic/translate.html]]
Move the pointer left and right across the image to change its position. This program overlays one image over another by modifying the alpha value of the image with the tint() function.
<<Processing
PImage a, b;
float offset;
void setup()
{
size(200, 200);
a = loadImage("construct.jpg"); // Load an image into the program
b = loadImage("wash.jpg"); // Load an image into the program
frameRate(60);
}
void draw()
{
image(a, 0, 0);
float offsetTarget = map(mouseX, 0, width, -b.width/2 - width/2, 0);
offset += (offsetTarget-offset)*0.05;
tint(255, 153);
image(b, offset, 20);
}
>>
Taken from [[basic/transparency.html|http://ejohn.org/apps/processing.js/examples/basic/transparency.html]]
By Ira Greenberg Using rotate() and triangle() functions generate a pretty flower. Uncomment the line // rotate(rot+=radians(spin)); in the triBlur() function for a nice variation.
<<Processing
Point[]p = new Point[3];
float shift = 1.0;
float fade = 0;
float fillCol = 0;
float rot = 0;
float spin = 0;
void setup(){
size(200, 200);
background(0);
smooth();
fade = 255.0/(width/2.0/shift);
spin = 360.0/(width/2.0/shift);
p[0] = new Point(-width/2, height/2);
p[1] = new Point(width/2, height/2);
p[2] = new Point(0, -height/2);
noStroke();
translate(width/2, height/2);
triBlur();
}
void triBlur(){
fill(fillCol);
fillCol+=fade;
rotate(spin);
// another interesting variation: uncomment the line below
// rotate(rot+=radians(spin));
triangle(p[0].x+=shift, p[0].y-=shift/2, p[1].x-=shift, p[1].y-=shift/2, p[2].x, p[2].y+=shift);
if(p[0].x<0){
// recursive call
triBlur();
}
}
>>
Taken from [[basic/triangleflower.html|http://ejohn.org/apps/processing.js/examples/basic/triangleflower.html]]
By Ira Greenberg Generate a closed ring using vertex() function and beginShape(TRIANGLE_STRIP) mode. outerRad and innerRad variables control ring's outer/inner radii respectively. Trig functions generate ring.
<<Processing
size(200, 200);
background(204);
smooth();
int x = width/2;
int y = height/2;
int outerRad = 80;
int innerRad = 50;
float px = 0, py = 0, angle = 0;
float pts = 36;
float rot = 360.0/pts;
beginShape(TRIANGLE_STRIP);
for (int i=0; i<pts; i++) {
px = x+cos(radians(angle))*outerRad;
py = y+sin(radians(angle))*outerRad;
angle+=rot;
vertex(px, py);
px = x+cos(radians(angle))*innerRad;
py = y+sin(radians(angle))*innerRad;
vertex(px, py);
angle+=rot;
}
endShape();
>>
Taken from [[basic/trianglestrip.html|http://ejohn.org/apps/processing.js/examples/basic/trianglestrip.html]]
Boolean data is one bit of information. True or false. It is common to use Booleans with control statements to determine the flow of a program. In this example, when the boolean value "x" is true, vertical black lines are drawn and when the boolean value "x" is false, horizontal gray lines are drawn.
<<Processing
boolean x = false;
size(200, 200);
background(0);
stroke(0);
for (int i = 1; i < width; i += 2)
{
if (i < width/2) {
x = true;
} else {
x = false;
}
if (x) {
stroke(255);
line(i, 1, i, height-1);
}
if (!x) {
stroke(126);
line(width/2 , i, width-2, i);
}
}
>>
Taken from [[basic/truefalse.html|http://ejohn.org/apps/processing.js/examples/basic/truefalse.html]]
Variables may either have a global or local "scope". For example, variables declared within either the setup() or loop() functions may be only used in these functions. Global variables, variables declared outside of setup() and loop(), may be used anywhere within the program. If a local variable is declared with the same name as a global variable, the program will use the local variable to make its calculations within the current scope. Variables may be localized within classes, functions, and iterative statements.
<<Processing
int a = 20; // Create a global variable "a"
void setup()
{
size(200, 200);
background(51);
stroke(255);
noLoop();
}
void draw()
{
// Draw a line using the global variable "a"
line(a, 0, a, height);
// Create a new variable "a" local to the for() statement
for(int a=50; a<80; a += 2) {
line(a, 0, a, height);
}
// Create a new variable "a" local to the loop() method
int a = 100;
// Draw a line using the new local variable "a"
line(a, 0, a, height);
// Make a call to the custom function drawAnotherLine()
drawAnotherLine();
// Make a call to the custom function setYetAnotherLine()
drawYetAnotherLine();
}
void drawAnotherLine()
{
// Create a new variable "a" local to this method
int a = 185;
// Draw a line using the local variable "a"
line(a, 0, a, height);
}
void drawYetAnotherLine()
{
// Because no new local variable "a" is set,
// this lines draws using the original global
// variable "a" which is set to the value 20.
line(a+2, 0, a+2, height);
}
>>
Taken from [[basic/variablescope.html|http://ejohn.org/apps/processing.js/examples/basic/variablescope.html]]
Variables are used for storing values. In this example, changing the values of variables 'a' and 'b' significantly change the composition.
<<Processing
size(200, 200);
background(0);
stroke(153);
int a = 20;
int b = 50;
int c = a*8;
int d = a*9;
int e = b-a;
int f = b*2;
int g = f+e;
line(a, f, b, g);
line(b, e, b, g);
line(b, e, d, c);
line(a, e, d-e, c);
>>
Taken from [[basic/variables.html|http://ejohn.org/apps/processing.js/examples/basic/variables.html]]
The beginShape() function begins recording vertices for a shape and endShape() stops recording. A vertex is a location in space specified by X, Y, and sometimes Z coordinates. After calling the beginShape() function, a series of vertex() functions must follow. To stop drawing the shape, call the endShape() functions.
<<Processing
size(200, 200);
background(0);
noFill();
stroke(102);
beginShape();
curveVertex(168, 182);
curveVertex(168, 182);
curveVertex(136, 38);
curveVertex(42, 34);
curveVertex(64, 200);
curveVertex(64, 200);
endShape();
stroke(51);
beginShape(LINES);
vertex(60, 40);
vertex(160, 10);
vertex(170, 150);
vertex(60, 150);
endShape();
stroke(126);
beginShape();
vertex(60, 40);
bezierVertex(160, 10, 170, 150, 60, 150);
endShape();
stroke(255);
beginShape(POINTS);
vertex(60, 40);
vertex(160, 10);
vertex(170, 150);
vertex(60, 150);
endShape();
>>
Taken from [[basic/vertices.html|http://ejohn.org/apps/processing.js/examples/basic/vertices.html]]
by Ira Greenberg. Generate a gradient along a sin() wave.
<<Processing
size(50, 50);
background(200,200,200);
float angle = 0;
float px = 0, py = 0;
float amplitude = 30;
float frequency = 0;
float fillGap = 2.5;
color c;
for (int i =- 75; i < height+75; i++){
// reset angle to 0, so waves stack properly
angle = 0;
// increasing frequency causes more gaps
frequency+=.006;
for (float j=0; j<width+75; j++){
py = i+sin(radians(angle))*amplitude;
angle+=frequency;
c = color(abs(py-i)*255/amplitude, 255-abs(py-i)*255/amplitude, j*(255.0/(width+50)));
// hack to fill gaps. Raise value of fillGap
// if you increase frequency
for (int filler = 0; filler<fillGap; filler++){
set(int(j-filler), int(py)-filler, c);
set(int(j), int(py), c);
set(int(j+filler), int(py)+filler, c);
}
}
}
>>
Taken from [[basic/wavegradient.html|http://ejohn.org/apps/processing.js/examples/basic/wavegradient.html]]
The 'width' and 'height' variables contain the width and height of the display window as defined in the size() function.
<<Processing
size(200, 200);
background(127);
noStroke();
for(int i=0; i<height; i+=20) {
fill(0);
rect(0, i, width, 10);
fill(255);
rect(i, 0, 10, height);
}
>>
Taken from [[basic/widthheight.html|http://ejohn.org/apps/processing.js/examples/basic/widthheight.html]]
The text() function is used for writing words to the screen.
<<Processing
size(200, 200);
background(102);
// Load the font. Fonts are located within the
// main Processing directory/folder and they
// must be placed within the data directory
// of your sketch for them to load
PFont fontA = loadFont("Arial");
// Set the font and its size (in units of pixels)
textFont(fontA, 32);
int x = 30;
// Use fill() to change the value or color of the text
fill(0);
text("ichi", x, 60);
fill(51);
text("ni", x, 95);
fill(204);
text("san", x, 130);
fill(255);
text("shi", x, 165);
>>
Taken from [[basic/words.html|http://ejohn.org/apps/processing.js/examples/basic/words.html]]