xxxxxxxxxx
// Roo Racing -- OO arrays
// bam:0405
String title="Kangaroo Race (roo4)",
author= "Prof.BAM",
filename= "k1_roorace.pde",
version= "20413";
String news=".", test=".";
String[] knames = { "Hoppy", "Thumper",
"Pogo", "Bouncy", "Mate" };
int nr = knames.length; // Number of Roo's.
int ba=nr, br=nr+1; // 2 more buttons.
int nb = nr + 2;
Roo[] roos = new Roo[nr];
Track[] tracks = new Track[nr];
Button[] butts = new Button[nb];
float start=100, finish=700;
float trackY=150, trackDY=100;
float bw=60, bh=30, bx=20; // Button size.
boolean debug=false;
int leader=-1, winner=-1, count=0;
int fps=30; // Frames per second;
void setup() {
size( 800, 600 );
finish= width-100;
frameRate(fps);
makeObjects();
reset();
}
void reset() {
for (int i=0; i<nr; ++i) {
roos[i].reset();
}
for (int i=0; i<nr; ++i) {
butts[i].c = roos[i].c; // Same color for button
}
news = "(Reset all.)";
leader=winner=-1;
}
void makeObjects() {
// Instatiate & construct the objects (roos & buttons)
butts[ba] = new Button( "All jump!", 30, GREEN );
butts[ba].cn=0;
//// Tracks, Roos, and Buttons.
float y=trackY;
for (int i=0; i<nr; ++i) {
tracks[i] = new Track( y );
roos[i] = new Roo( i, knames[i], y );
butts[i] = new Button( knames[i], y-30, roos[i].c );
y += trackDY; // Next track.
}
butts[br] = new Button( "Reset all", height-50, MAGENTA );
butts[br].x = width-80;
}
void draw() {
background( #EEFFFF );
show();
action ();
messages();
}
void show() {
// show tracks, roos, buttons. //
for (int i=0; i<nr; ++i) {
fill( 100, 0, 0 );
tracks[i].show();
roos[i].show();
butts[i].show();
}
butts[ba].show();
butts[br].show();
}
void action() {
if (key == '?') { help(); return; }
if (winner>=0) return;
for (int i=0; i<nr; ++i) {
roos[i].move();
}
check(); // Check for leader/winner.
}
void check() {
if (winner>0) { cheer( roos[winner] ); return; }
int who=0;
for (int i=1; i<nr; ++i) {
if (roos[i].x >= roos[who].x) {
who=i; // New leader.
}
}
if (roos[who].x < start+100) return; // Not until 100.
leader = who;
cheer( roos[leader] );
}
void cheer( Roo k ) {
news = k.name + " is in the lead (at " +(int)k.x+ ")";
//// Red circle around the leader (or winner).
stroke(RED);
strokeWeight(1);
fill( 0, 0, 0, 0 );
if (k.x > finish) {
//// WE have a winner!!! ////
news = "The winner is: " + k.name;
winner=leader; // (stops further moving.)
strokeWeight( 10 ); // BIG circle
}
ellipse( k.x+25, k.y-50, 150, 160 );
strokeWeight(1);
text( "WINNER", width-50, k.y );
stroke(0);
}
//////// OBJECT CLASSES ////////
class Track {
float y;
Track( float ynew ) { y=ynew; }
void show() {
fill(0);
rect( start, y, finish-start, 10 );
}
}
class Button {
//// DATA ////
float x=bx, y=trackY, w=bw, h=bh;
color c=BROWN, cn=WHITE;
String name= "?";
//// CONSTRUCTORS ////
Button( String name, float y, color c ) {
this.name=name;
this.y=y;
this.c =c;
}
//// METHODS ////
void show() {
fill (c);
rect( x, y, w, h );
fill(cn);
text( name, x+5, y+20 );
}
boolean clicked() { // True iff mouse clicked button. //
return hit( mouseX, mouseY );
}
boolean hit( float x2, float y2 ) {
// True if (x2,y2) is within this button. //
if (x2<x) return false;
if (x2>x+bw) return false;
if (y2<y) return false;
if (y2>y+bh) return false;
return true;
}
}// class Button //
class Roo {
//// DATA ////
float x=start, y, z, next=x, steps=10;
float howfar, hop, dx, dy;
float w=60, h=80; // Size
String name="";
color c=BROWN, cn=WHITE;
int r,g,b;
int number;
//// CONSTRUCTORS ////
Roo( int n, String n0, float y0 ) {
number=n;
y=y0;
z=y; // Initial y (track)
name= n0;
println( "Roo: " + name, y0, y, z );
rancolor();
w= random( 40,70);
h= random(60,90);
}
void show() {
fill( c );
float xhead= x+w*5/6, yhead=y-h;
quad( x, y, x+w/10, y-h/2, xhead, yhead, x+w, y-h/3 );
rect( x, y, w, -h/10 ); // feet
float ytail = z - h/2 - 2*(y-z);
ytail = ytail > z ? y : ytail;
triangle( x, y, x-w/2, ytail, x+w/6, y-h/6 ); // tail
// Head & nose
ellipse( xhead, yhead, 30, 20 ); // head
ellipse( xhead-12, yhead-12, 6, 20 ); // ears
ellipse( xhead-6, yhead-12, 6, 20 );
// ears
fill(255);
ellipse( xhead-5, yhead-3, 6, 6 ); // eye
fill(0);
ellipse( xhead+18, yhead, 10, 10 ); // nose
//
fill(cn);
text( name, x+8, y+6+-h/2 );
text( (int)(16*dy), x+15, y+24-h/2 );
if (debug) peek();
//
if (x<150) return;
fill(c);
text( (int)x, width-50, y );
if (number==winner) text( "WINNER!", width-65, y-20 );
else if (number==leader) text( "(Leader)", width-65, y-20 );
println( number, leader, winner );
}
void peek( ) {
fill(0);
text( (int)x+ "\n" +(int)y, x+5, y+22 );
text( r+ "\n" +g+ "\n" +b, x-25, y+22 );
}
void jump( float d ) {
howfar = d;
next = x + howfar; // Destination
dx = howfar / steps;
dy = dx; // (45-degree slope)
}
void jump( ) { jump(random(10,50)); }
void move() {
if (winner>0) return;
if ( x < next-dx/2) { // UP
x += dx;
y -= dy;
} else if ( x < next) { // DOWN
x += dx;
y += dy;
} else { // DONE
//--if (next>finish) next=finish;
x=next;
y=z; // Put back on track.
hop=dx=0;
}
}
void rancolor() {
r= (int)random(200, 255);
g= (int)random(0, 180);
b= (int)random(0, 120);
c = color( r, g, b );
//-- println( name, "COLOR: ", r,g,b,c );
}
void reset() {
x=next=start;
dx=dy=0;
y=z;
rancolor();
w= random( 40,70);
h= random(60,90);
}
boolean clicked() {
// True if mouse clicked on this button. //
return hit( mouseX, mouseY );
}
boolean hit( float x2, float y2 ) {
// True if (x2,y2) is near
float d = dist( x2,y2, x,y );
boolean result = d < w;
if (debug) { fill( RED, 200 ); ellipse( x+w/2,y-h/2, w,w ); }
return dist( x2,y2, x+w/2,y-h/2 ) < w;
}
}// class Roo //
//// COLOR NAMES ////
color RED=#FF0000, GREEN=#00FF00, BLUE=#0000FF;
color YELLOW=#FFFF00, CYAN=#00FFFF, MAGENTA=#FF00FF;
color BROWN=#800000, DARK=#009900, GRASS=#33CC00, WHITE=#FFFFFF;
float brx=100, bry=600;
void messages() {
fill( #CC0066 );
textSize( 24 );
text( title, width/3, 30 );
textSize( 16 );
if (winner>=0) news = roos[winner].name + " is the WINNER!";
text( news, 10+width/3, 50 );
text( test, width/2, 50 );
text( author, 20, height-20 );
textSize( 12 );
text( "? for help; q to quit.", width/2, height-20 );
}
void help() {
String s=".";
s += "\n Button moves Kangaroo forward; clicking moves it backward!";
s += "\n q to quit, r to reset, SPACE bar moves all Kangaroos";
s += "\n d to display debugging data;";
s += "\n < or > changes frameRate. ( / resets to 30.)";
float x=width/3, y=80;
fill( 155,100,155, 150 );
rect( x-10,y-10, width*2/3, width/2 );
fill(YELLOW);
textSize(16);
text( s, x,y );
textSize(12);
}
//////// EVENT HANDLERS ////////
void keyPressed() {
news=""+key;
if (key == 'q') exit();
if (key == 'r') reset();
if (key == ' ') allJump();
if (key == '>') frameRate( fps *= 1.20 );
if (key == '<') frameRate( fps *= 0.80 );
if (key == '/') frameRate( fps = 30 );
if (key == 'c') { rancolors(); }
if (key == 'm') { makeObjects(); }
if (key == 'd') { debug = ! debug; }
//// Cheat keys for roos[0]. //
if (key == '0') roos[0].jump( random(10, 50) );
if (key == '1') roos[0].jump( random(10, 100) );
if (key == '2') roos[0].jump( random(10, 200) );
if (key == '3') roos[0].jump( random(10, 300) );
if (key == 'z') roos[0].jump( (finish-roos[0].x) / 2);
if (key == '+') roos[0].next = roos[0].x += 1;
if (key == '-') roos[0].next = roos[0].x -= 1;
//
if (key == '!') { finished=true; }
}
void mousePressed() {
news=".";
for (int i=0; i<nr; ++i) {
if ( butts[i].clicked() ) roos[i].jump();
}
if ( butts[ba].clicked() ) { allJump(); }
if ( butts[br].clicked() ) { reset(); }
//
//-- println( "\nCheck for clicks on Roos:" );
for (int i=0; i<nr; ++i) {
if ( roos[i].clicked() ) roos[i].jump( - random(20,50) );
}
}
boolean buttonClick( float x, float y ) {
//// Return true iff click on object. ////
if (mouseX<x) return false;
if (mouseX>x+bw) return false;
if (mouseY<y) return false;
if (mouseY>y+bh) return false;
return true;
}
void allJump() {
for (int i=0; i<nr; ++i) { roos[i].jump( ); }
}
void rancolors() {
for (int i=0; i<nr; ++i) {
roos[i].rancolor();
butts[i].c= roos[i].c;
}
}