Saturday 18 October 2008

2D Bezier Curves Demo

I like this demo! Although not graphically very exciting - it does show the potential for Bezier curves in games - Paths for nasties, cars etc. You can see from my variables names within the code, where my inspiration came from!
http://www.javaimage.co.uk/bez.html

View Bez Demo


/*
Demo showing Objects moving over 2D space using Bezier curves -
JW October 18th 2008
http://www.javaimage.co.uk/bez.html

*/

public static final int BEZ_ARCFROMTOPLEFT = 0;
public static final int BEZ_ARCFROMTOPRIGHT = 1;
public static final int BEZ_UTURNFROMTOPLEFT = 2;
public static final int BEZ_UTURNFROMTOPRIGHT = 3;
public static final int BEZ_CENTRALTOPTWIRLRIGHT = 4;
public static final int BEZ_CENTRALTOPTWIRLLEFT = 5;
public static final int BEZ_HELIXFROMTOPLEFT = 6;
public static final int BEZ_HELIXFROMTOPRIGHT = 7;
public static final int BEZ_RBEND = 8;
public static final int BEZ_RBEND_INVERTED = 9;
public static final int BEZ_DOWN_RIGHT = 10;
public static final int BEZ_DOWN_LEFT = 11;
public static final int BEZ_FLAT_LEFT_23 = 12;
public static final int BEZ_FLAT_RIGHT_23 = 13;
public static final int BEZ_FLAT_LEFT_13 = 14;
public static final int BEZ_FLAT_RIGHT_13 = 15;
public static final int BEZ_UP_RIGHT = 16;
public static final int BEZ_UP_LEFT = 17;
public static final int BEZ_S = 18;
public static final int BEZ_S_INVERTED = 19;
public static final int BEZ_FLAT_LEFT_34 = 20;
public static final int BEZ_FLAT_RIGHT_34 = 21;
public static final int BEZ_UTURNFROMBOTTOMLEFT = 22;
public static final int BEZ_UTURNFROMBOTTOMRIGHT = 23;
public static final int BEZ_SWOOPTOPLEFT_TORIGHT = 24;
public static final int BEZ_SWOOPTOPRIGHT_TOLEFT = 25;
public static final int BEZ_REVERSESINEWAVE = 26;
public static final int BEZ_COSINEWAVE = 27;
public static final int BEZ_LEFTNOSE = 28;
public static final int BEZ_RIGHTNOSE = 29;
public static final int BEZ_CSHAPE = 30;
public static final int BEZ_CSHAPE_MIRROR = 31;
public static final int BEZ_DIAGONAL_FROMTOPLEFT = 32;
public static final int BEZ_DIAGONAL_FROMTOPRIGHT = 33;
public static final int BEZ_SHEARED_S = 34;
public static final int BEZ_SHEARED_S_MIRROR = 35;
public static final int BEZ_DOWN_CENTRE = 36;

public static final int NUM_BEZIERS = 37;



int displayWidth,displayHeight ;
String mode ;
BezierCP [] bez = new BezierCP[NUM_BEZIERS] ;

// Curve table

public class BezierCP {
float cx,cy ;
float cx2,cy2 ;
float cx3,cy3 ;
float cx4,cy4 ;
public BezierCP(float cx,float cy,float cx2, float cy2, float cx3, float cy3,float cx4,float cy4)
{
this.cx = cx ; this.cy = cy ;
this.cx2 = cx2 ; this.cy2 = cy2 ;
this.cx3 = cx3 ; this.cy3 = cy3 ;
this.cx4 = cx4 ; this.cy4 = cy4 ;




}

float getX(float t) {
return bezierPoint(cx,cx2,cx3,cx4,t) ;

}

float getY(float t) {
return bezierPoint(cy,cy2,cy3,cy4,t) ;

}

public void draw() {
bezier(cx,cy,cx2,cy2,cx3,cy3,cx4,cy4) ;
}


}


public class Galaxian {

float time, duration ;
BezierCP gbez ; // bezier curve this Galaxian follows
boolean randomchoice = false ;
color col = color(random(255),random(255),random(255),255) ; // random colour

// Default Glaxian contructor

public Galaxian() {
time = 0f ;
duration = 4.0 ;
gbez = bez[0] ;
randomchoice = true ;
}

public Galaxian(BezierCP gbez,float duration) {
this.duration = duration ;
time = 0f ;
this.gbez = gbez ;

}
public Galaxian(int bezidx,float duration) {
this(bez[bezidx],duration) ;
}

public void update(float dt) {


if (time > duration) {
// Galaxian has finished - start again
time = 0f ;
if (randomchoice)
gbez = bez[(int)random(NUM_BEZIERS)] ;

} else {


}

time = time + dt ;

}

public void draw() {

debug() ; // Draw Curve the Galaxian is following.


if (time < duration) {

float t = time/duration ;
float xpos = gbez.getX(t) ;
float ypos = gbez.getY(t) ;
fill(col) ;
rect(xpos,ypos,20,20) ;
}

}

public void debug() {
noFill() ;
stroke(col) ;
gbez.draw() ;
}


}



/*
Create a global Array of Bezier Objects -
This object is just a wrapper for a Processing Bezier Object for storing control points.

*/

void InitBezier(int width,int height)
{


bez[BEZ_ARCFROMTOPLEFT] =
new BezierCP( 0, 100,
width, 0,
width/2, height/2,
width, height);

bez[BEZ_ARCFROMTOPRIGHT] =
new BezierCP( width, 100,
0, 0,
width/2, height/2,
0, height);

bez[BEZ_UTURNFROMTOPLEFT] =
new BezierCP( 100, -100,
100, 100.0f +height/2,
width-100, 100.0f + height/2,
width-100, 0);

bez[BEZ_UTURNFROMTOPRIGHT] =
new BezierCP( width-100, -100,
width-100, +200.0f + height/2,
100, +200.0f + height/2,
100, 0);

bez[BEZ_CENTRALTOPTWIRLRIGHT] =
new BezierCP( width/2, 0,
width, height*0.25f,
0, height*0.75f,
width/2, height);

bez[BEZ_CENTRALTOPTWIRLLEFT] =
new BezierCP( width/2, 0,
0, height*0.25f,
width, height*0.75f,
width/2, height);

bez[BEZ_HELIXFROMTOPLEFT] =
new BezierCP( 0, 0,
0, height/2,
width, height/2,
width, height);

bez[BEZ_HELIXFROMTOPRIGHT] =
new BezierCP( width, 0,
width, height/2,
0, height/2,
0, height);

bez[BEZ_RBEND] =
new BezierCP( width, height*0.25f,
width, height*0.25f,
100, height*0.25f,
100, height);
bez[BEZ_RBEND_INVERTED] =
new BezierCP( 0, height*0.25f,
width, height*0.25f,
width, height*0.25f,
width, height*0.25f);
bez[BEZ_DOWN_RIGHT] =
new BezierCP( width*0.75f, 0,
width*0.75f, 0,
width*0.75f, height,
width*0.75f, height);
bez[BEZ_DOWN_LEFT] =
new BezierCP( width*0.25f, 0,
width*0.25f, 0,
width*0.25f, height,
width*0.25f, height);
bez[BEZ_FLAT_LEFT_23] =
new BezierCP( width, height*0.33f,
width, height*0.33f,
0, height*0.33f,
0, height*0.33f);
bez[BEZ_FLAT_RIGHT_23] =
new BezierCP( 0, height*0.33f,
0, height*0.33f,
width, height*0.33f,
width, height*0.33f);
bez[BEZ_FLAT_LEFT_34] =
new BezierCP( width, height*0.25f,
width, height*0.25f,
0, height*0.25f,
0, height*0.25f);
bez[BEZ_FLAT_RIGHT_34] =
new BezierCP( 0, height*0.25f,
0, height*0.25f,
width, height*0.25f,
width, height*0.25f);
bez[BEZ_FLAT_LEFT_13] =
new BezierCP( width, height*0.66f,
width, height*0.66f,
0, height*0.66f,
0, height*0.66f);
bez[BEZ_FLAT_RIGHT_13] =
new BezierCP( 0, height*0.66f,
0, height*0.66f,
width, height*0.66f,
width, height*0.66f);
bez[BEZ_UP_RIGHT] =
new BezierCP( width*0.75f, height,
width*0.75f, height,
width*0.75f, 0,
width*0.75f, 0);
bez[BEZ_UP_LEFT] =
new BezierCP( width*0.25f, height,
width*0.25f, height,
width*0.25f, 0,
width*0.25f, 0);
bez[BEZ_S] =
new BezierCP( width/2, 0,
0, 0,
width, height*0.66f,
width/2, height);
bez[BEZ_S_INVERTED] =
new BezierCP( width/2, 0,
width, 0,
0, height*0.66f,
width/2, height);

bez[BEZ_UTURNFROMBOTTOMLEFT] =
new BezierCP( 0, height,
0, -100,
width, -100,
width+100, height+100);

bez[BEZ_UTURNFROMBOTTOMRIGHT] =
new BezierCP( width, height+100,
width, -100,
0, -100,
-100, height+100);

bez[BEZ_SWOOPTOPLEFT_TORIGHT] =
new BezierCP( 100, -100,
200, height-400,
200, height-400,
width+100, height-200);

bez[BEZ_SWOOPTOPRIGHT_TOLEFT] =
new BezierCP( width-100, -100,
width-200, height-400,
width-200, height-400,
-100, height-200);

bez[BEZ_REVERSESINEWAVE] =
new BezierCP( width+100, 100,
200, 100,
width+100, height-200,
-100, height-200);

bez[BEZ_COSINEWAVE] =
new BezierCP( -100, 100,
width+100, 100,
200, height-200,
width+100, height-200);

bez[BEZ_LEFTNOSE] =
new BezierCP( width/2 - 100, -100,
width/2 + 200, 200,
-800, 400,
width+100, height-200);

bez[BEZ_RIGHTNOSE] =
new BezierCP( width/2 + 100, -100,
width/2 - 200, 200,
width+800, 400,
-100, height-200);

bez[BEZ_CSHAPE] =
new BezierCP( width + 100, 0,
-200, 0,
-200, height-100,
width+100, height-100);

bez[BEZ_CSHAPE_MIRROR] =
new BezierCP( -100, 0,
width+200, 0,
width+200, height-100,
-100, height-100);

bez[BEZ_DIAGONAL_FROMTOPLEFT] =
new BezierCP( -100, 0,
-100, 0,
width/2, height+100,
width/2, height+100);

bez[BEZ_DIAGONAL_FROMTOPRIGHT] =
new BezierCP( width+100, 0,
width+100, 0,
width/2, height+100,
width/2, height+100);

bez[BEZ_SHEARED_S_MIRROR] =
new BezierCP( -100, 50,
width+600, 180,
-1000, 360,
width+100, height-50);

bez[BEZ_SHEARED_S] =
new BezierCP( width+100, 50,
-600, 180,
width+1000, 360,
-100, height-50);

bez[BEZ_DOWN_CENTRE] =
new BezierCP( width/2, -100,
width/2, -100,
width/2, height+100,
width/2, height+100);


}



/*
Define some Galaxians
*/

int MAX_GALAXIANS = 20 ;

Galaxian [] galaxians = new Galaxian[MAX_GALAXIANS] ;

void setup() {

mode = JAVA2D ;

displayHeight = screen.height/2 ;
displayWidth = screen.width/2 ;
InitBezier(displayWidth,displayHeight) ;

for (int i = 0 ; i < galaxians.length ; i++) {
galaxians[i] = new Galaxian((int)random(NUM_BEZIERS),2.0f + random(4.0f)) ; // pick a random Bezier 'curve' and a random duration between 2 and 6 seconds

}


size(displayWidth, displayHeight,mode);
loop() ;

}




void draw() {
background(255);
float dt = 1/frameRate ; // We should calculate dt - time passed since last update-draw
// but this should be approx equal to 1 / frameRate

// Update the Galaxians
for (int i = 0 ; i < galaxians.length ; i++) {
galaxians[i].update(dt) ;
}


// Draw Galaxians

for (int i = 0 ; i < galaxians.length ; i++) {
galaxians[i].draw() ;
}


}

1 comment:

lazydog said...

John, I have downloaded the IDE and got it working with your Bezier code! Looks good!

I see the top left corner of the rectangles is the origin.

b e n