# ProcessingJS - Template --{{0}}-- A simple template for executing Processing.js in [LiaScript](https://LiaScript.github.io). You can use it to build more sophisticated Tutorials ... Just check out, how this File gets rendered by LiaScript: __Try it on LiaScript:__ https://liascript.github.io/course/?https://raw.githubusercontent.com/liaTemplates/processingjs/master/README.md __See the project on Github:__ https://github.com/liaTemplates/processingjs --{{1}}-- There are three ways to use this template. The easiest way is to use the `import` statement and the url of the raw text-file of the master branch or any other branch or version. But you can also copy the required functionionality directly into the header of your Markdown document, see therefor the [Implementation](#3). And of course, you could also clone this project and change it, as you wish. {{1}} 1. Load the macros via `import: https://raw.githubusercontent.com/liaTemplates/processingjs/master/README.md` 2. Copy the definitions into your Project 3. Clone this repository on GitHub ## `@Processing.eval` --{{0}}-- Currently there is only one macro, simply add `@Processing.eval` to the end of your Processing code-block to make it executable. Since there is only one "Processing-thread", your program will run until you restart it, go to another section, or start another program. ```cpp void setup() { size(480, 120); } void draw() { if (mousePressed) { fill(0); } else { fill(255); } ellipse(mouseX, mouseY, 80, 80); } ``` @Processing.eval ## Implementation --{{0}}-- There are two macros, `@Processing.eval` and a hidden one, which actually defines all code required. The function defined in `@onload` is used to stop the currently running thread, if the user goes to another slide. ```html script: https://cdnjs.cloudflare.com/ajax/libs/processing.js/1.6.6/processing.min.js @Processing.eval: @Processing._eval_(@uid) @Processing._eval_
@end @onload window.stop_processing = function() { if(window["running"]) { window["processing"][window["running"]].exit(); document.getElementById("sketch-container-"+window["running"]).innerHTML = ""; window["running"] = null; } } @end ``` --{{1}}-- If you want to minimize loading effort in your LiaScript project, you can also copy this code and paste it into your main comment header, see the code in the raw file of this document. {{1}} https://raw.githubusercontent.com/liaTemplates/processingjs/master/README.md ## Demos > Because it is so beautiful, I added some more examples, to demonstrate how > beautiful Processing.js is ... ### Getting started ``` cpp // Global variables float radius = 50.0; int X, Y; int nX, nY; int delay = 16; // Setup the Processing Canvas void setup(){ size( 400, 200 ); strokeWeight( 10 ); frameRate( 15 ); X = width / 2; Y = height / 2; nX = X; nY = Y; } // Main draw loop void draw(){ radius = radius + sin( frameCount / 4 ); // Track circle to new destination X+=(nX-X)/delay; Y+=(nY-Y)/delay; // Fill canvas grey background( 100 ); // Set fill-color to blue fill( 0, 121, 184 ); // Set stroke-color white stroke(255); // Draw circle ellipse( X, Y, radius, radius ); } // Set circle's next destination void mouseMoved(){ nX = mouseX; nY = mouseY; } ``` @Processing.eval ### PVector ``` cpp float x = 100; float y = 100; float xspeed = 1; float yspeed = 3.3; void setup() { size(200,200); smooth(); background(255); } void draw() { noStroke(); fill(255,10); rect(0,0,width,height); // Add the current speed to the location. x = x + xspeed; y = y + yspeed; // Check for bouncing if ((x > width) || (x < 0)) { xspeed = xspeed * -1; } if ((y > height) || (y < 0)) { yspeed = yspeed * -1; } // Display at x,y location stroke(0); fill(175); ellipse(x,y,16,16); } ``` @Processing.eval ### Abstract ``` cpp int DONT_INTERSECT = 0; int COLLINEAR = 1; int DO_INTERSECT = 2; float x =0, y=0; void setup(){ size(200,200); fill(255,0,0); } void draw(){ int intersected; background(255); // lignes stroke(0); // ligne fixe line(20,height/2, width-20, (height/2)-20); // ligne en mouvement line(10,10,mouseX, mouseY); intersected = intersect(20, height/2, width-20, (height/2)-20, 10, 10, mouseX, mouseY); // dessiner le point d'intersection noStroke(); if (intersected == DO_INTERSECT) ellipse(x, y, 5, 5); } int intersect(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4){ float a1, a2, b1, b2, c1, c2; float r1, r2 , r3, r4; float denom, offset, num; // Compute a1, b1, c1, where line joining points 1 and 2 // is "a1 x + b1 y + c1 = 0". a1 = y2 - y1; b1 = x1 - x2; c1 = (x2 * y1) - (x1 * y2); // Compute r3 and r4. r3 = ((a1 * x3) + (b1 * y3) + c1); r4 = ((a1 * x4) + (b1 * y4) + c1); // Check signs of r3 and r4. If both point 3 and point 4 lie on // same side of line 1, the line segments do not intersect. if ((r3 != 0) && (r4 != 0) && same_sign(r3, r4)){ return DONT_INTERSECT; } // Compute a2, b2, c2 a2 = y4 - y3; b2 = x3 - x4; c2 = (x4 * y3) - (x3 * y4); // Compute r1 and r2 r1 = (a2 * x1) + (b2 * y1) + c2; r2 = (a2 * x2) + (b2 * y2) + c2; // Check signs of r1 and r2. If both point 1 and point 2 lie // on same side of second line segment, the line segments do // not intersect. if ((r1 != 0) && (r2 != 0) && (same_sign(r1, r2))){ return DONT_INTERSECT; } //Line segments intersect: compute intersection point. denom = (a1 * b2) - (a2 * b1); if (denom == 0) { return COLLINEAR; } if (denom < 0){ offset = -denom / 2; } else { offset = denom / 2 ; } // The denom/2 is to get rounding instead of truncating. It // is added or subtracted to the numerator, depending upon the // sign of the numerator. num = (b1 * c2) - (b2 * c1); if (num < 0){ x = (num - offset) / denom; } else { x = (num + offset) / denom; } num = (a2 * c1) - (a1 * c2); if (num < 0){ y = ( num - offset) / denom; } else { y = (num + offset) / denom; } // lines_intersect return DO_INTERSECT; } boolean same_sign(float a, float b){ return (( a * b) >= 0); } ``` @Processing.eval ### ABSTRACT01js ``` cpp ABSTRACT01js int num,cnt,px,py,fadeInterval; Particle[] particles; boolean initialised=false,doClear=false; float lastRelease=-1,scMod,fadeAmount; void setup() { size(400,300); background(255); smooth(); rectMode(CENTER_DIAMETER); ellipseMode(CENTER_DIAMETER); cnt=0; num=150; particles=new Particle[num]; for(int i=0; i0) particles[i].update(); } void reinit() { doClear=true; scMod=random(1,1.4); fadeInterval=(int)random(220,300); fadeAmount=random(30,60); // println("fadeInterval "+fadeInterval+" scMod "+nf(scMod,0,3)+ // " fadeAmount "+nf(fadeAmount,0,3)); for(int i=0; i95) ageGoal*=1.25; age=-(int)random(50,150); pos=new Vec2D(random(width-100)+50,random(height-100)+50); dir=(int)random(36)*10; type=0; if(random(100)>60) type=1; interval=(int)random(2,5); if(type==1) { interval=1; dir=degrees(atan2(-(pos.y-height/2),pos.x-width/2)); } dirD=random(1,2); if(random(100)<50) dirD=-dirD; speed=random(3,6); sc=random(0.5,1); if(random(100)>90) sc=random(1.2,1.6); dirCnt=random(20,35); if(type==0) { if(random(100)>95) sc=random(1.5,2.25); else sc=random(0.8,1.2); } sc*=scMod; speed*=sc; } void update() { age++; if(age<0) return; else if(age>ageGoal) reinit(); else { if(type==1) { pos.add( cos(radians(dir))*speed,sin(radians(dir))*speed); dir+=dirD; dirD+=random(-0.2,0.2); dirCnt--; if(dirCnt<0) { dirD=random(1,5); if(random(100)<50) dirD=-dirD; dirCnt=random(20,35); } } if(age%interval==0) newParticle(); if(pos.x<-50 || pos.x>width+50 || pos.y<-50 || pos.y>height+50) reinit(); } } void newParticle() { int partNum,i; if(type==0) dir=int(random(36))*10; i=0; while(i50) offs=-offs; particles[i].init(dir+offs,pos.x,pos.y,sc); break; } i++; } px=mouseX; py=mouseY; } } class Particle { Vec2D v,vD; float dir,dirMod,speed,sc; int col,age,stateCnt; int type; Particle() { v=new Vec2D(0,0); vD=new Vec2D(0,0); age=0; } void init(float _dir,float mx,float my,float _sc) { dir=_dir; sc=_sc; float prob=random(100); if(prob<80) age=15+int(random(30)); else if(prob<99) age=45+int(random(50)); else age=100+int(random(100)); if(random(100)<80) speed=random(2)+0.5; else speed=random(2)+2; if(random(100)<80) dirMod=20; else dirMod=60; v.set(mx,my); initMove(); dir=_dir; stateCnt=10; if(random(100)>50) col=0; else col=1; type=(int)random(30000)%2; } void initMove() { if(random(100)>50) dirMod=-dirMod; dir+=dirMod; vD.set(speed,0); vD.rotate(radians(dir+90)); stateCnt=10+int(random(5)); if(random(100)>90) stateCnt+=30; } void update() { age--; if(age>=30) { vD.rotate(radians(1)); vD.mult(1.01f); } v.add(vD); if(col==0) fill(255-age,0,100,150); else fill(100,200-(age/2),255-age,150); if(type==1) { if(col==0) fill(255-age,100,0,150); else fill(255,200-(age/2),0,150); } pushMatrix(); scale(sc); translate(v.x,v.y); rotate(radians(dir)); rect(0,0,1,16); popMatrix(); if(age==0) { if(random(100)>50) fill(200,0,0,200); else fill(00,200,255,200); float size=2+random(4); if(random(100)>95) size+=5; size*=sc; ellipse(v.x*sc,v.y*sc,size,size); } if(v.x<0 || v.x>width || v.y<0 || v.y>height) age=0; if(age<30) { stateCnt--; if(stateCnt==0) { initMove(); } } } } // General vector class for 2D vectors class Vec2D { float x,y; Vec2D(float _x,float _y) { x=_x; y=_y; } Vec2D(Vec2D v) { x=v.x; y=v.y; } void set(float _x,float _y) { x=_x; y=_y; } void set(Vec2D v) { x=v.x; y=v.y; } void add(float _x,float _y) { x+=_x; y+=_y; } void add(Vec2D v) { x+=v.x; y+=v.y; } void sub(float _x,float _y) { x-=_x; y-=_y; } void sub(Vec2D v) { x-=v.x; y-=v.y; } void mult(float m) { x*=m; y*=m; } void div(float m) { x/=m; y/=m; } float length() { return sqrt(x*x+y*y); } float angle() { return atan2(y,x); } void normalise() { float l=length(); if(l!=0) { x/=l; y/=l; } } Vec2D tangent() { return new Vec2D(-y,x); } void rotate(float val) { // Due to float not being precise enough, double is used for the calculations double cosval=Math.cos(val); double sinval=Math.sin(val); double tmpx=x*cosval - y*sinval; double tmpy=x*sinval + y*cosval; x=(float)tmpx; y=(float)tmpy; } } ``` @Processing.eval