xxxxxxxxxx
//// OO example: Quarks move and collide.
//// Swap velocities, when balls hit.
//// Expandable version -- change many to add balls.
String title="Colliding quarks.";
String author="BAM 3B15";
int numButtons=10;
Button[] b = new Button[numButtons];
Quark[] salad;
int many=3;
int score=0;
int speed=30;
int num=0;
float dd=50; // Distance from walls.
float x1,x2, y1,y2; // Boundaries of table.
void setup() {
//// Setup: 600x400 (for 500x300 table).
size(600,400);
x1=50; x2=width-50;
y1=50; y2=height-50;
initialize();
frameRate( speed );
// Make the buttons
b[0]= new Button( "MORE", 50, 100, 255,0,0 );
b[1]= new Button( "FEWER", 50, 150, 0,255,0 );
b[2]= new Button( "ZERO", 50, 250, 255,0,255 );
b[3]= new Button( "RESET", 50, 250, 255,0,255 );
b[4]= new Button( "0", 50, 250, 255,0,255 );
b[5]= new Button( "1", 50, 300, 128,255,0 );
b[6]= new Button( "reset", 50, 350, 128,128,255 );
//
b[7]= new Button( "FASTER", width-50, 200, 255,255,0 );
b[8]= new Button( "SLOWER", width-50, 250, 255,0,255 );
//
b[9]= new Button( "QUIT", width-50, height-50, 0,255,255 );
b[9].w= 75;
b[9].kind= 1;
}
/*
if (key=='S') { speed++; }
if (key=='s') { if (speed>0) speed--; }
//
if (key=='+') { many++; initialize(); }
if (key=='-') { many--; many= many<1 ? 1 : many; initialize(); }
if (key=='0') { many=0; initialize(); }
if (key=='1') { many=0; initialize(); }
*/
void initialize() {
//// Give each quark a starting position.
salad = new Quark[many]; // New array!
num=0;
//// Initialize each quark with a random color.
for (int j=0; j<salad.length; j++) {
salad[j]= new Quark( num );
num++;
}
}
void keyPressed() {
//// "Q" quits game.
if (key=='Q') {
exit();
}
//// Restart.
if (key=='R') {
initialize();
}
if (key=='S') { speed++; }
if (key=='s') { if (speed>0) speed--; }
//
if (key=='+') { many++; initialize(); }
if (key=='-') { many--; many= many<1 ? 1 : many; initialize(); }
if (key=='0') { many=0; initialize(); }
if (key=='1') { many=0; initialize(); }
}
void mousePressed() {
////
if ( b[0].isOver(mouseX,mouseY) ) { many++; initialize(); }
if ( b[1].isOver(mouseX,mouseY) ) { many--; }
if ( b[2].isOver(mouseX,mouseY) ) { many=0; initialize(); }
if ( b[3].isOver(mouseX,mouseY) ) { initialize(); }
if ( b[7].isOver(mouseX,mouseY) ) { speed++; }
if ( b[8].isOver(mouseX,mouseY) ) { speed--; }
if ( b[9].isOver(mouseX,mouseY) ) { exit(); }
/*
//// Restart.
if ( b[0].click(mouseX,mouseY) ) { initialize(); }
if (key=='S') { speed++; }
if (key=='s') { if (speed>0) speed--; }
//
if (key=='+') { many++; initialize(); }
if (key=='-') { many--; many= many<1 ? 1 : many; initialize(); }
if (key=='0') { many=0; initialize(); }
if (key=='1') { many=0; initialize(); }
*/
}
void draw() {
//// Table, with billiard balls.
frameRate( speed );
scene();
action();
display();
//// Draw the buttons
for (int j=0; j<numButtons; j++) {
b[j].show();
}
//// Text on screen ////
fill(0);
textSize(20);
text( title, width/3, 20);
textSize(12);
text( "many = "+many, 10, 10 );
text( author, 10, height-20);
//
text( "R to restart with " +many+ " quarks", width*2/3, height-25);
text( "+/-/0 to increase/decrease/zero", width*2/3, height-10);
text( "speed = "+speed, width/3, height-25);
text( "S/s for speed-up/slow-down", width/3, height-10);
//
fill( 255,0,0);
text( "SCORE: "+score, 400, 15 );
fill( 255,255,255);
}
void scene() {
//// Draw the table.
background( 200,150,100 ); // Tan bg.
fill( 0,0,200);
//// Table:
fill( 150,200,150 ); // Light-green table.
stroke( 100,50,50 ); // Brown (wood) rail.
strokeWeight(25);
rectMode(CORNER);
rect(50,50, 500,300); // Table (with rail);
}
void display() {
//// Draw all quarks.
for (int i=0; i<many; i++) {
salad[i].show();
}
}
void action() {
//// Move each object, based on its velocity (dx,dy),
for (int i=0; i<many; i++) {
salad[i].move();
}
//// Check for collisions.
for (int j=0; j<many; j++) {
for (int k=j+1; k<many; k++) { // Start with NEXT quark.
if (hit( salad[j], salad[k] )) {
//// Check for collisions; reverse both if hit.
salad[j].counter++;
salad[k].counter++;
score -= 10;
salad[j].dx *= -1;
salad[j].dy *= -1;
salad[k].dx *= -1;
salad[k].dy *= -1;
salad[j].timer=30;
salad[k].timer=30;
fill(0); text( j +" HIT "+ k, salad[j].x+20, salad[j].y-10 );
//// Add extra move (bouncing away), to avoid "ringing"
salad[j].move(); salad[j].move();
salad[k].move(); salad[k].move(); salad[k].move();
}// End collision code.//
}// End inner loop.//
}// End outer loop.//
//// Proclaim the winner:
int winner=0;
for (int j=1; j<many; j++) {
if (salad[j].counter > salad[winner].counter) { winner=j; }
}
fill(0,0,0);
text( "Winner is "+winner, 10,30 );
}
boolean hit( Quark p, Quark q ) {
//// True if p hits q
return dist( p.x,p.y, q.x,q.y) < p.d/2 ;
}
class Quark {
float x=0,y=0; // Position of this ball.
float dx=3,dy=2; // Velocity (pixels per frame).
int r,g,b; // Color (RGB)
int number;
String name="";
float d=30; // diameter
int counter=0;
int timer=0;
//// CONSTRUCTORS ////
Quark( int r, int g, int b ) {
this.r=r; this.g=g; this.b=b;
}
Quark( int num ) {
this.r= int(random(255));
this.g= int(random(255));
this.b= int(random(255));
x= random( x1+dd, x2-dd );
y= random( y1+dd, y2-dd );
number= num;
}
/*
salad[j]= new Quark( int(random(255)), int(random(255)), int(random(255)) );
salad[j].x= random( x1+dd, x2-dd );
salad[j].y= random( y1+dd, y2-dd );
salad[j].number= num++;
*/
//// METHODS ////
void move() {
//// Move quark by (dx,dy)
x= x + dx;
y= y + dy;
// Bounce off walls.
if (x < x1+d ) { dx= -dx; }
if (x > x2-d ) { dx= -dx; }
if (y < y1+d ) { dy= -dy; }
if (y > y2-d ) { dy= -dy; }
}
void show() {
//// Draw at (x,y)
fill(r,g,b);
noStroke();
ellipseMode(CENTER);
ellipse(x,y, d,d );
fill( (r+128)%256, (g+128)%256, (b+128)%256 ); // Contrasting color.
textSize(18);
text(number, x-8, y+3);
textSize(12);
//// Check timer for red ring.
if (timer>0) {
stroke(r,g,b);
strokeWeight(6);
fill(255,0,0, constrain( timer*5,0,255 ) );
ellipse( x, y, d*2, d*2 );
timer--;
fill(0);
text(timer,x+45,y);
}
}
}//class//
class Button {
//// Different kinds of button ////
int kind=2; // 1 for ellipse, 2 for rect, 3 for triangle, 4 for square.
float x=25, y;
float w=80,h=30;
String s="";
int r,g,b;
float size=1;
//// CONSTRUCTORS ////
Button( String s, float x, float y, int r, int g, int b ) {
this.s= s;
this.x= x;
this.y= y;
this.r= r;
this.g= g;
this.b= b;
}
//// METHODS ////
void show() {
// Draw it //
stroke(0);
strokeWeight(2);
fill( r, g, b );
//
size=1;
if ( isOver(mouseX,mouseY) ) { size=1.25; }
if (kind == 1 ) {
ellipseMode( CENTER );
ellipse(x,y, w*size,h*size);
} else if (kind == 2 || kind == 4) {
rectMode( CENTER );
rect(x,y, w*size,h*size);
} else if (kind == 3) {
triangle( x-w/2,y+h/2, x+w/2,y+h/2, x,y=h/2 );
} else {
text( "NO SUCH KIND OF BUTTON "+kind, x, y );
}
fill( 0 );
text( s, x-w/2+20, y );
}
boolean isOver( float xx, float yy ) {
// True if mouseX, mouseY iis over this button.
if (kind == 1 ) return dist(xx,yy, x,y) < w;
if (xx < x-w) return false;
if (xx > x+w) return false;
if (yy < y-h) return false;
if (yy > y+h) return false;
return true;
}
}// class Button //