Emerge is a 2-player infinite-racing 3D game. It features reflective water and efficient procedural content generation and rendering. The objective is for each player to avoid the obstacles in their path the longest.
The showcase player uses a modified version of Processing.js in combination with jsweet to let students program their apps in Java code while still allowing for browser support.
Content created by students is scaled to fit the showcase frame while maintaining aspect ratio and cursor position. This is why some projects may appear blurry in fullscreen, or why some small details may not be visible on a small screen
boolean sd=false,wo=false;float po=0,tp=0,x2=5,x3=-5,z1=0,z3=0,x1=-1,i2=-1,td=0;float sy=millis(),dt=0;float ts=-1;Ck fc,lc;Ob fo,lo;int st;PImage bg;boolean dp=false,ap=false,lp=false,r2=false;String wt="\n";class Ck{Ck n;int t;float[][]b;int s=1000;void ge(){t=floor(random(3));if(t==0||t==1){b=new float[70][7];float y=10;if(t==1)y=30;for(int i=0; i<b.length; i++){if(random(1)>0.5){b[i]=new float[]{ random(-50,-20),y,random(i*10,i*10+10),random(6),random(100)+y,random(6),0 };}else{b[i]=new float[]{ random(20,50),y,random(i*10,i*10+10),random(6),random(100)+y,random(6),0 };}b[i][6]=color(random(30,150));}}else{b=new float[8][7];float c=color(random(30,150));b[0]=new float[]{ 0,100,s/2,100,10,s,c };b[1]=new float[]{ -50,25,s/2+1,10,90,s,c };b[2]=new float[]{ 50,25,s/2+1,10,90,s,c };for(int i=3; i<8; i++){b[i]=new float[]{ 0,95,(i-3)*200,100,10,10,color(255,255,200)};}}}int gs(){if(n==null)return 1;else return n.gs()+1;}void rn(){if(t==0){fill(0,100,0);um();translate(0,10);rotateX(3*PI/2);rect(-100,-1000,200,1000);om();}for(int i=0; i<b.length; i++){int c=(int)b[i][6];fill(c);um();translate(b[i][0],b[i][1]-b[i][4]/2,b[i][2]);box(b[i][3],b[i][4],b[i][5]);om();}translate(0,0,-s);if(n !=null){n.rn();}}}class Ob{Ob nt;int cz;float x,z;int getSize(){if(nt==null)return 1;else return nt.getSize()+1;}void gg(float f){cz=color(random(255),100,random(255),200);z=f+random(-10,10);x=random(-10,10);}void rd(){um();fill(cz);translate(x,-2,z);box(4);om();if(nt !=null)nt.rd();}}void setup(){size(800,600,P3D);frameRate(60);}void gn(){st=millis();po=0;fc=new Ck();fc.ge();lc=new Ck();lc.ge();fc.n=lc;fo=new Ob();fo.gg(0);lo=new Ob();lo.gg(-50);fo.nt=lo;bg=createImage(800,305,RGB);float r=random(250,300),g=random(300,400);for(int x=0; x<bg.pixels.length; x++){bg.pixels[x]=color(x*r/bg.pixels.length,x*g/bg.pixels.length,200);}bg.updatePixels();}void draw(){background(0);fill(255);if(fc==null)gn();um();float cameraZ=((height/2f)/tan(PI*60f/360f));perspective(PI/3f,width/height,cameraZ/100f,cameraZ*2f);if(sd){float dt=(millis()-st)/5f;po+=dt;td+=dt;st=millis();if(lp&&x2>-10)x2 -=0.3;if(r2&&x2<10)x2+=0.3;if(ap&&x3>-10)x3 -=0.3;if(dp&&x3<10)x3+=0.3;}if(po>=fc.s){po -=fc.s;fc=fc.n;}if(fc.gs()<4){Ck l=new Ck();l.ge();lc.n=l;lc=l;}if(-200+td+fo.z>200){fo=fo.nt;}if(fo.getSize()<30){Ob o=new Ob();o.gg(lo.z-50);lo.nt=o;lo=o;}noStroke();um();hint(DISABLE_DEPTH_TEST);image(bg,0,0);scale(1,-1);image(bg,0,-610);hint(ENABLE_DEPTH_TEST);om();ambientLight(255,255,255);translate(400+(x2+x3)/-2,300);um();translate(0,50,0);scale(1,-1);rp();om();hint(DISABLE_DEPTH_TEST);fill(0,0,100,100);rect(-400,5,800,295);hint(ENABLE_DEPTH_TEST);rp();om();hint(DISABLE_DEPTH_TEST);if(!sd){um();perspective();rotateY(radians(tp-150));if(ts<0){if(tp==0)tp=1;else if(tp<180&&tp>50)tp+=(180-tp)/20f;else if(tp<=50){tp+=tp/5f;}}else{tp=(1-pow((2000-ts)/2000,2))*180;}textSize(100);fill(0,200,255);dt+=millis()-sy;if(ts>0){ts -=millis()-sy;if(ts<=0){ts=-1;sd=true;st=millis();}}sy=millis();translate(360,0);rotateX(PI/12);for(int i=0; i<10; i++){text(wt+ " Emerge\nP1: A/D\nP2: Right/Left Arrows\nClick to play",-120,0);translate(0,0,1);}if(mousePressed&&ts==-1){ts=2000;}om();}hint(ENABLE_DEPTH_TEST);if(wo){wo=false;sd=false;ts=-1;tp=0;x2=5;x3=-5;z1=0;z3=0;x1=-1;i2=-1;dp=false;ap=false;lp=false;r2=false;ts=-1;tp=0;x1=5000;i2=5000;}}void rp(){if(!sd){if(ts<0)rotateY(tp*2*PI/600);}um();translate(0,0,po+fc.s);fc.rn();om();um();fill(100,100,100,200);translate(0,9.9f);rotateX(3*PI/2);rect(-10,-600,20,2000);om();if(sd){float dt=millis()-sy;sy=millis();if(x1>=0)x1 -=dt;if(i2>=0)i2 -=dt;z1 -=dt/10000f;if(z1<0)z1=0;z3 -=dt/10000f;if(z3<0)z3=0;}Ob o=fo;for(int i=0; i<5; i++){float z=-200+td+o.z;if(z>-4&&z<=0){if(x2>o.x-2&&x2<o.x+2&&x1<0){o.cz=color(0);z1+=5;x1=1000;if(z1>20){wt="Player 1 Wins!\n";wo=true;}}if(x3>o.x-2&&x3<o.x+2&&i2<0){o.cz=color(0);z3+=5;i2=1000;if(z3>20){wt=wo?"It's a tie!\n":"Player 2 Wins!\n";wo=true;}}}o=o.nt;if(o==null)break;}fill(0);translate(0,9.8f,480);um();translate(0,0,-200+td);fo.rd();om();um();translate(x2,0,0);if(lp)rotateY(PI/12);if(r2)rotateY(-PI/12);ds(x1>0?x1%255:255,0,z1*10);om();translate(x3,0,0);if(ap)rotateY(PI/12);if(dp)rotateY(-PI/12);ds(0,i2>0?i2%255:255,z3*10);}void ds(float r,float b,float c){fill(r,0,b,255-c);stroke(255,255,255);beginShape(TRIANGLES);v(0,-0.3f,0);v(-1.6f,0,3.3f);v(0,-0.6f,3.3f);v(0,-0.3f,0);v(1.6f,0,3.3f);v(0,-0.6f,3.3f);v(-1.6f,0,3.3f);v(0,-0.6f,3.3f);v(0,-0.3f,3.3f);v(1.6f,0,3.3f);v(0,-0.6f,3.3f);v(0,-0.3f,3.3f);v(-0.3f,-0.3f,0);v(-1.6f,0,3.3f);v(0,-0.3f,0);v(0.3f,-0.3f,0);v(1.6f,0,3.3f);v(0,-0.3f,0);endShape();fill(255);line(-1.6f,0,3.3f,-1.6f,0,100f);line(1.6f,0,3.3f,1.6f,0,100f);noStroke();}void keyPressed(){if(key=='a')ap=true;if(key=='d')dp=true;if(keyCode==RIGHT)r2=true;if(keyCode==LEFT)lp=true;}void keyReleased(){if(key=='a')ap=false;if(key=='d')dp=false;if(keyCode==RIGHT)r2=false;if(keyCode==LEFT)lp=false;}void v(float a,float b,float c){vertex(a,b,c);}void um(){pushMatrix();}void om(){popMatrix();}