APPENDIX B
MARBLES WORLD CLIENT CODE
import
java.awt.*;
import
java.applet.*;
import
java.util.*;
import
java.io.*;
import
java.net.*;
import
java.util.Date;
import
vrml.external.field.*;
import
vrml.external.Node;
import
vrml.external.Browser;
import
vrml.external.exception.*;
import
netscape.javascript.JSObject;
import
dtai.net.*;
// ball.e is currently as follows:
// #
// 0 - no effect
// 1 - non-collidable
// 2 - anti-gravity
// 3 - stop
// 4 - goal stealing
// 5 - add a fence
// 6 - bigger
//-------------------------------------------------------------------
// This is the main applet class
public
class Marbles extends Applet implements EventOutObserver {
TextArea output = null;
//Main Window for Controls
MainWindow b;
// Browser we're using
Browser browser;
// Root of the scene graph (to which we add
our clumps)
Node board = null;
Node pointer = null;
Node designer = null;
Node sides
= null;
Node slant = null;
Node pitem[] =
{null,null,null,null,null,null,null};
Node slqu[] = {null,null,null,null};
Node material = null;
EventInSFColor diffuseColor = null;
EventInMFNode addPI[] =
{null,null,null,null,null,null,null};
EventInMFNode removePI[] =
{null,null,null,null,null,null,null};
EventInMFNode addslqu[] =
{null,null,null,null};
EventInMFNode removeslqu[] =
{null,null,null,null};
Node gl[] =
{null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null};
EventInMFNode addGoal[] =
{null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null};
EventInMFNode removeGoal[] =
{null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null};
Node sensor[] =
{null,null,null,null,null,null,null};
Node slantSensor[] = {null,null,null,null};
Node wrapSensor = null;
Node root[] = {null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null};
EventInMFNode addChildren[] =
{null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null};
EventOutSFVec3f translation_changed[] =
{null,null,null,null,null,null,null,null,null,null};
EventOutSFVec3f pointer_changed = null;
EventInSFVec3f pointer_translation = null;
EventInMFNode addSides = null;
EventInMFNode removeSides = null;
EventInMFNode removeChildren[] =
{null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null};
EventInSFVec3f set_translation[] =
{null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null};
EventInSFVec3f slant_translation = null;
EventInSFVec3f set_scale[] =
{null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null};
EventInSFRotation slant_rotation = null;
EventOutSFTime touchTime[] =
{null,null,null,null,null,null,null};
EventOutSFTime slantTouchTime[] =
{null,null,null,null};
EventOutSFTime wrapTouchTime = null;
EventOutSFVec3f hitb = null;
EventOutSFVec3f hitt = null;
Node[] goalshape[] =
{null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null};
Node[] pshape[] =
{null,null,null,null,null,null,null,null,null,null};
Node[] qshape[] = {null,null,null,null};
Node[] shape = null;
Node[] bumpers = null;
Node[] pieceshape[] =
{null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null};
int marker=0;
int newpiecex=0, newpiecey=0;
int curnode=0;
int curtype=0;
double hitpoint[] = {0.0,0.0,0.0,0.0};
float
offsetx=0.0f,offsety=0.0f,oldx=0.0f,oldy=0.0f,oldz=0.0f;
int mode = 0;
boolean speedtest=true; //test the speed of the animator for each
client
int qno = 103;
boolean designing = false;
int lastmodesent = 0;
Player[] player = new Player[4]; // array of players
int pn; //client player number
int nump=0;
int numplay=0;
int turncolor=1;
int sim_type=1;
public final static int PORT=8765;
PieceList pl = new PieceList(7);
EffectList el = new EffectList(7);
Image
image[]={null,null,null,null,null,null,null};
PortToServer pts;
public void init() {
//
// Initialize connection to Cosmo Player
//
JSObject win = JSObject.getWindow(this);
JSObject doc = (JSObject)
win.getMember("document");
JSObject embeds = (JSObject)
doc.getMember("embeds");
browser = (Browser) embeds.getSlot(0);
try {
pts = new
PortToServer(this.getCodeBase().getHost(),PORT,this);
pts.start();
for(int x=0;x<100;x++) {
root[x] =
browser.getNode("T" + x);
addChildren[x] = (EventInMFNode)
root[x].getEventIn("addChildren");
removeChildren[x] = (EventInMFNode)
root[x].getEventIn("removeChildren");
set_translation[x] = (EventInSFVec3f)
root[x].getEventIn("translation");
set_scale[x] = (EventInSFVec3f)
root[x].getEventIn("scale");
}
for(int x=0;x<4;x++) {
slantSensor[x] =
browser.getNode("SS" + x);
slantTouchTime[x] = (EventOutSFTime)
slantSensor[x].getEventOut("touchTime");
slantTouchTime[x].advise(this, new
Integer(10 + x));
slqu[x] =
browser.getNode("SQ" + x);
addslqu[x] = (EventInMFNode)
slqu[x].getEventIn("addChildren");
removeslqu[x] = (EventInMFNode)
slqu[x].getEventIn("removeChildren");
}
for(int x=0;x<7;x++) {
pitem[x] =
browser.getNode("PI" + x);
addPI[x] = (EventInMFNode)
pitem[x].getEventIn("addChildren");
removePI[x] = (EventInMFNode)
pitem[x].getEventIn("removeChildren");
}
for(int x=0;x<30;x++) {
gl[x] = browser.getNode("G"
+ x);
addGoal[x] = (EventInMFNode)
gl[x].getEventIn("addChildren");
removeGoal[x] = (EventInMFNode)
gl[x].getEventIn("removeChildren");
}
board =
browser.getNode("TSB");
slant = browser.getNode("BOARD");
wrapSensor =
browser.getNode("WRAP");
wrapTouchTime = (EventOutSFTime)
wrapSensor.getEventOut("touchTime");
wrapTouchTime.advise(this, new
Integer(14));
pointer =
browser.getNode("T100");
pointer_translation = (EventInSFVec3f)
pointer.getEventIn("translation");
slant_rotation = (EventInSFRotation)
slant.getEventIn("rotation");
slant_translation = (EventInSFVec3f)
slant.getEventIn("translation");
pointer_changed = (EventOutSFVec3f)
pointer.getEventOut("translation_changed");
designer =
browser.getNode("TSD");
sides =
browser.getNode("SIDES");
addSides = (EventInMFNode)
sides.getEventIn("addChildren");
removeSides = (EventInMFNode)
sides.getEventIn("removeChildren");
for(int x=0;x<7;x++) {
sensor[x] =
browser.getNode("TS" + x);
touchTime[x] = (EventOutSFTime)
sensor[x].getEventOut("touchTime");
touchTime[x].advise(this, new
Integer(x+1));
}
// Get the material node...
material =
browser.getNode("MAT");
// Get the diffuseColor EventIn
diffuseColor = (EventInSFColor)
material.getEventIn("set_diffuseColor");
// Get Hit Point for Board
hitb = (EventOutSFVec3f)
board.getEventOut("translation_changed");
hitt = (EventOutSFVec3f)
designer.getEventOut("hitPoint_changed");
// Set up the callback
hitb.advise(this, new Integer(0));
hitt.advise(this, new Integer(7));
}
catch (InvalidVrmlException e) {
showStatus("PROBLEMS!: " + e);
}
catch (InvalidEventInException e) {
showStatus("PROBLEMS!: " + e);
}
catch (InvalidEventOutException e) {
showStatus("PROBLEMS!: " + e);
}
catch (IOException e) {
showStatus("PROBLEMS!: " +
e.toString());
}
b = new
MainWindow("Controls",true,this);
b.resize(250,480);
if(sim_type==0) {b.show();}
b.start();
for(int x=0;x<4;x++) {
addPlayer(new Player());
}
for(int ww=0;ww<4;ww++) {
addSlQu(ww,0,true);
}
for(int xx=1;xx<8;xx++) {
pl.AddtoPieceList(xx);
el.AddtoEffectList(xx);
}
}
public
void callback(EventOut who, double when, Object which) {
Integer whichNum = (Integer) which;
if
(whichNum.intValue()>0 && whichNum.intValue()<10 ) {
if(!designing && turncolor==pn
&& sim_type==0){
float[] val = hitb.getValue();
offsetx = val[0];
offsety = val[1];
UpdatePointer(0,0,0,30,0,0,0,0);
oldx = 0;
oldy = 0;
}
}
if
(whichNum.intValue()==0) {
float[] val = hitb.getValue();
UpdateVRML(4,curnode,oldx,oldy,oldz,val[0],val[1],offsetx,offsety);
UpdatePointer(1,oldx,oldy,oldz,val[0],val[1],offsetx,offsety);
}
else if (whichNum.intValue()>0
&& whichNum.intValue()<8) {
int iv=whichNum.intValue()-1;
if (mode==1 && !designing
&& pl.l[iv]>0 && turncolor==pn && sim_type==0) {
if(pl.l[iv]==1 || pl.l[iv]==6 ||
pl.l[iv]==7) {
curnode=b.anim.num;
} else {
curnode=50+b.anim.numo;
}
curtype=pl.l[iv];
addNode(curnode,curtype,0,0,0,0,0);
designing = true;
} else if (mode==2) {
b.anim.ars.AddToArsenal(el.l[iv]);
} else if (mode==3){
String eventstring = "3"
+ ((100*pn) + b.anim.ars.TakeFromArsenal(iv));
eventstring = eventstring +
(b.anim.count+b.anim.eql);
pts.writeToServer(eventstring);
ReplaceNode(0,iv,LoadString());
eventstring = "3" + (100*pn);
eventstring = eventstring +
(b.anim.count+b.anim.eqd);
pts.writeToServer(eventstring);
}
}
else if (whichNum.intValue()>=10
&& whichNum.intValue()<=13) {
//if animating, slant added to queue
if(mode==1 && lastmodesent==0)
{ //ignore request for mode change if already made a request -- only server
updates mode
pts.writeToServer("92");
lastmodesent++;
//Paletize(2);
}
else if(mode==2 &&
lastmodesent==1) {
pts.writeToServer("93");
if(designing==true) {
removeChildren[curnode].setValue(pieceshape[curnode]);
designing=false;
}
UpdatePointer(0,0,0,30,0,0,0,0);
lastmodesent++;
Bumpers(1);
b.anim.wrapon = false;
//Paletize(3);
}
else
if(mode==3&&turncolor==pn) {
pts.writeToServer("2" +
(whichNum.intValue()-9));
}
}
else if (whichNum.intValue()==14) {
if(mode==0) {
pts.writeToServer("6"
+ pn); //request goals for next round
Paletize(1);
mode=1;
UpdateColor(0,turncolor);
//Four Corner Balls
b.anim.ball[0].x=500;
b.anim.ball[0].y=100; b.anim.ball[0].m=b.anim.bm;
addNode(0,0,20,1,1,0,0);
//if(b.anim.rules.roundtype==0)
{ addNode(0,0,20,1,1,0,0); }
//else if(b.anim.rules.roundtype==1)
{ addNode(0,0,20,0,1,0,0); }
//else
if(b.anim.rules.roundtype==2) { addNode(0,0,20,0,0,1,0); }
b.anim.ball[1].x=100;
b.anim.ball[1].y=500; b.anim.ball[1].m=b.anim.bm;
addNode(1,0,20,1,0,0,0);
//if(b.anim.rules.roundtype==0)
{ addNode(1,0,20,1,0,0,0); }
//else
if(b.anim.rules.roundtype==1) { addNode(1,0,20,.6,1,0,0); }
//else
if(b.anim.rules.roundtype==2) { addNode(1,0,20,1,0,0,0); }
b.anim.ball[2].x=900;
b.anim.ball[2].y=500; b.anim.ball[2].m=b.anim.bm;
addNode(2,0,20,0,0,1,0);
//if(b.anim.rules.roundtype==0)
{ addNode(2,0,20,0,0,1,0); }
//else
if(b.anim.rules.roundtype==1) { addNode(2,0,20,0,1,.6,0); }
//else
if(b.anim.rules.roundtype==2) { addNode(2,0,20,1,.4,0,0); }
b.anim.ball[3].x=500;
b.anim.ball[3].y=900; b.anim.ball[3].m=b.anim.bm;
addNode(3,0,20,0,1,0,0);
//if(b.anim.rules.roundtype==0)
{ addNode(3,0,20,0,1,0,0); }
//else
if(b.anim.rules.roundtype==1) { addNode(3,0,20,0,1,.4,0); }
//else
if(b.anim.rules.roundtype==2) { addNode(3,0,20,0,.6,1,0); }
}
else if(mode>1) {
//Do nothing
} else {
if(sim_type==0) {
removeChildren[curnode].setValue(pieceshape[curnode]);
pts.writeToServer("4" + pn + "" + curtype + (100 +
curnode) + (1000 + newpiecex) + (1000 + newpiecey));
designing = false;
}
}
}
}
public
String LoadString() {
String shapestring;
shapestring = "Transform
{\n" +
" children [\n" +
" Shape {\n" +
" appearance Appearance {\n";
shapestring = shapestring + "
material Material { diffuseColor " + b.anim.ps.GetPiecesString(0);
shapestring = shapestring + " }\n]}\n";
return shapestring;
}
public
void UpdateVRML (int f, int m, float x, float y, float z, float px, float py,
float opx, float opy) {
float[] val = new float[3];
if(f==0) {
val[0] = 6.0f;
val[1] = y + py - opy;
val[2] = z - px + opx;
set_translation[m].setValue(val);
}
else if (f==1 || f==4) {
val[0] = x + px - opx;
val[1] = y + py - opy;
if (m==101){
val[2] = z;
slant_translation.setValue(val);
} else {
val[2] = 0.35f;
set_translation[m].setValue(val);
}
if(f==4) {
newpiecex = (int)val[0];
//prepare for final location to send to other players
newpiecey = (int)val[1];
}
}
else if (f==2) {
val[0] = 0.0f;
val[1] = 0.0f;
val[2] = -400.0f;
slant_translation.setValue(val);
}
else if (f==3) {
val[0] = x;
val[1] = y;
val[2] = 0.35f;
set_translation[m].setValue(val);
}
}
public
void UpdatePointer (int f, float x, float y, float z, float px, float py, float
opx, float opy) {
float[] val = new float[3];
if(f==0) {
val[0] = 0.0f;
val[1] = 0.0f;
val[2] = z;
pointer_translation.setValue(val);
}
else if (f==1) {
val[0] = x + px - opx;
val[1] = y + py - opy;
val[2] = 30.0f;
pointer_translation.setValue(val);
}
}
public
void UpdateRotation (int m, int f) {
float[] val = new float[4];
if (f==0) {
val[0] = 1.0f;
val[1] = 0.0f;
val[2] = 0.0f;
val[3] = -0.4f;
slant_rotation.setValue(val);
}
else if (f==1) {
val[0] = 0.0f;
val[1] = 1.0f;
val[2] = 0.0f;
val[3] = 0.4f;
slant_rotation.setValue(val);
}
else if (f==2) {
val[0] = 1.0f;
val[1] = 0.0f;
val[2] = 0.0f;
val[3] = 0.4f;
slant_rotation.setValue(val);
}
else if (f==3) {
val[0] = 0.0f;
val[1] = 1.0f;
val[2] = 0.0f;
val[3] = -0.4f;
slant_rotation.setValue(val);
}
else {
val[0] = 1.0f;
val[1] = 0.0f;
val[2] = 0.0f;
val[3] = 0.0f;
slant_rotation.setValue(val);
}
}
public
void UpdateColor (int m, int i) {
float[] val = new float[3];
if(i==0) {
val[0] = 1.0f;
val[1] = 1.0f;
val[2] = 1.0f;
}
else if (i==1) {
val[0] = 1.0f;
val[1] = 0.0f;
val[2] = 0.0f;
}
else if (i==2) {
val[0] = 0.0f;
val[1] = 0.0f;
val[2] = 1.0f;
}
else if (i==3) {
val[0] = 0.0f;
val[1] = 1.0f;
val[2] = 0.0f;
}
else if (i==4) {
val[0] = 1.0f;
val[1] = 1.0f;
val[2] = 0.0f;
}
else {
val[0] = 1.0f;
val[1] = 1.0f;
val[2] = 1.0f;
}
if(m==0) { diffuseColor.setValue(val); }
}
public
void UpdateScale (int i, float x) {
float[] val = new float[3];
val[0] = x;
val[1] = x;
val[2] = x;
set_scale[i].setValue(val);
}
public void Paletize(int mode) {
String shapestring = "";
int n=0;
int slot=0;
for(int nn=0;nn<7;nn++) {
if(mode==1) { n=pl.l[nn]; } else
if(mode==2) { n=el.l[nn]; } else { n=nn; }
shapestring =
"Transform {\n" +
" children [\n" +
" Shape {\n" +
" appearance Appearance {\n";
if(mode==1||mode==4) {
shapestring = shapestring
+ " material Material { diffuseColor " +
b.anim.ps.GetPiecesString(n);
} else if(mode==2) {
shapestring = shapestring
+ " material Material { diffuseColor " +
b.anim.es.GetEffectsString(n);
} else if (mode==3) {
shapestring = shapestring
+ " material Material { diffuseColor " +
b.anim.es.GetEffectsString(b.anim.ars.ReadFromArsenal(n));
}
if((mode==1||mode==4)&&n==4) {
shapestring = shapestring +
" }\n] rotation 0 0 1 .78
}\n";
} else
if((mode==1||mode==4)&&n==5) {
shapestring = shapestring +
" }\n] rotation 0 0 1 -.78
}\n";
} else {
shapestring = shapestring +
" }\n]}\n";
}
if(mode==1&&b.anim.round==1) {
ReplaceNode(2,slot++,shapestring);
} else {
ReplaceNode(0,slot++,shapestring);
}
}
}
public void addNode(int whichnode, int index,
double radius, double bx, double by, double ex, double ey) {
String shapestring = "";
try {
if(whichnode >= 100) { return; }
shapestring = "Transform
{\n" +
"
children [\n" +
" Shape {\n" +
" appearance Appearance {\n" +
" material Material { diffuseColor
";
if(index==1 || index==6) {
shapestring = shapestring +
b.anim.ps.GetPiecesString(index) +
" }\n" +
"] translation 0 0
15 }\n";
}
if(index==0) {
shapestring =
shapestring + " " + bx + " " + by + " " +
ex + " }\n" +
" }\n" +
" geometry Sphere {radius " +
radius + " }\n" +
" }\n" +
"]}\n";
}
else if(index==4) {
shapestring = shapestring +
b.anim.ps.GetPiecesString(2) +
" }\n" +
"] rotation 0 0 1
.78 }\n";
}
else if(index==5) {
shapestring = shapestring +
b.anim.ps.GetPiecesString(2) +
" }\n" +
"] rotation 0 0 1
-.78 }\n";
}
else {
shapestring = shapestring +
b.anim.ps.GetPiecesString(index) +
" }\n" +
"]}\n";
}
ReplaceNode(1,whichnode,shapestring);
curnode=whichnode;
}
catch (InvalidNodeException e) {
}
catch (InvalidEventInException e) {
}
catch (InvalidVrmlException e) {
}
}
public void ReplaceNode(int where, int ndx,
String str) {
String shapestring = "";
try {
if(where==0) { //Palette Piece Replace
removePI[ndx].setValue(pshape[ndx]);
pshape[ndx] =
browser.createVrmlFromString(str);
addPI[ndx].setValue(pshape[ndx]);
} else if(where==1) { //Add a Board
Piece
pieceshape[ndx] =
browser.createVrmlFromString(str);
addChildren[ndx].setValue(pieceshape[ndx]);
} else if(where==2) { //Pallete Piece
New
pshape[ndx] =
browser.createVrmlFromString(str);
addPI[ndx].setValue(pshape[ndx]);
}
}
catch (InvalidNodeException e) {
}
catch (InvalidEventInException e) {
}
catch (InvalidVrmlException e) {
}
}
public void addGoal(int whichgoal, int color,
double goalx, double goaly) {
String shapestring = "";
String colorstring = "";
try {
if(whichgoal >= b.anim.maxg) {
return; }
if(color==0) {
colorstring = "1 1 0";
}
else if (color==1) {
colorstring = "1 0 0";
} else if (color==2) {
colorstring = "0 0 1";
} else if (color==3) {
colorstring = "0 1 0";
} else colorstring = "0 0 0";
shapestring = "Transform
{\n" +
" children [\n" +
" Shape {\n" +
" appearance Appearance {\n" +
" material Material { diffuseColor
" + colorstring + " }\n"
+
" }\n" +
" geometry Cylinder {radius 20 height 5
}\n" +
" }\n" +
"] translation " +
goalx + " " + goaly + " 0 \n" +
" rotation 1 0 0 1.57 }\n";
goalshape[whichgoal] =
browser.createVrmlFromString(shapestring);
addGoal[whichgoal].setValue(goalshape[whichgoal]);
}
catch (InvalidNodeException e) {
}
catch (InvalidEventInException e) {
}
catch (InvalidVrmlException e) {
}
}
public void addSlQu(int whichslqu, int color,
boolean initial) {
String shapestring = "";
String colorstring = "";
String coordstring = "";
String transstring = "";
try {
if(whichslqu >= 4 || whichslqu <
0) {
return;
} else if (whichslqu==0) {
transstring = "-200 300 0";
} else if (whichslqu==1) {
transstring = "-200 400 0";
} else if (whichslqu==2) {
transstring = "-200 500 0";
} else {
transstring = "-200 600 0";
}
if (color==1) {
colorstring = "0 1 0";
coordstring = "point [ 0 0 25,
100 0 25, 100 100 -25, 0 100 -25 ]";
} else if (color==2) {
colorstring = "0 0 1";
coordstring = "point [ 0 0 25,
100 0 -25, 100 100 -25, 0 100 25 ]";
} else if(color==3) {
colorstring = "1 1 0";
coordstring = "point [ 0 0 -25,
100 0 -25, 100 100 25, 0 100 25 ]";
} else if (color==4) {
colorstring = "1 0 0";
coordstring = "point [ 0 0 -25,
100 0 25, 100 100 25, 0 100 -25 ]";
} else {
colorstring = "0 0 0
transparency 1";
}
if(!initial) {
removeslqu[whichslqu].setValue(qshape[whichslqu]);
}
shapestring = "Transform
{\n" +
" children [\n" +
" Shape {\n" +
" appearance Appearance {\n" +
" material Material { diffuseColor
" + colorstring + " }\n"
+
" }\n" +
" geometry IndexedFaceSet {\n" +
" coord Coordinate {\n" +
" " + coordstring +
"\n" +
" }\n" +
" coordIndex [ 0, 1, 2, 3 ]\n"
+
" }\n" +
" }\n" +
" ] translation " + transstring + "\n" +
"}\n";
qshape[whichslqu] =
browser.createVrmlFromString(shapestring);
addslqu[whichslqu].setValue(qshape[whichslqu]);
}
catch (InvalidNodeException e) {
}
catch (InvalidEventInException e) {
}
catch (InvalidVrmlException e) {
}
}
public void Bumpers(int whichmode) {
String colorstring = "";
if(pn==1){colorstring = " 1 0 0
";}
else if(pn==2){colorstring = " 0 0 1
";}
else if(pn==3){colorstring = " 0 1 0
";}
else if(pn==4){colorstring = " 1 1 0
";}
try {
if(whichmode == 1) { //Ball
bumpers =
browser.createVrmlFromString("Transform {\n" +
" children [\n" +
" Transform {\n" +
" children [\n" +
" DEF Bumper Shape {\n" +
" appearance Appearance {\n" +
" material Material { diffuseColor
" + colorstring + "}\n" +
" }\n" +
" geometry Box {}\n" +
" }\n" +
" ]\n" +
" scale 30 500 30\n" +
" translation -30 500 2\n" +
" },\n" +
" Transform {\n" +
" children [\n" +
" USE Bumper\n" +
" ]\n" +
" scale 30 500 30\n" +
" translation 1030 500 2\n" +
" },\n" +
" Transform {\n" +
" children [\n" +
" USE Bumper\n" +
" ]\n" +
" scale 560 30 30\n" +
" translation 500 1030 2\n" +
" },\n" +
" Transform {\n" +
" children [\n" +
" USE Bumper\n" +
" ]\n" +
" scale 560 30 30\n" +
" translation 500 -30 2\n" +
" },\n" +
"]}\n");
addSides.setValue(bumpers);
}
else {
removeSides.setValue(bumpers);
}
}
catch (InvalidNodeException e) {
}
catch (InvalidEventInException e) {
}
catch (InvalidVrmlException e) {
}
}
public void addPlayer(Player p) {
if (nump<4) player[nump++] = p;
}
public void stop() {
if (b!=null) b.stop();
}
//{{DECLARE_CONTROLS
//}}
}
//-------------------------------------------------------------------
// This class controls the main window
class
MainWindow extends Frame {
Animator anim;
Ticker tick;
Thread anim_thread;
Thread tick_thread;
boolean is_applet;
Marbles i;
MyFrame pwindow;
Scrollbar mgrav,fric,rest;
TextField grav;
Label
label1,label2,label3,label4,label5,label6,label7,label8,label9,inst;
Checkbox
trace,collide,mush,wrap,smooth,filled,cb1,cb2,cb3,cb4,cb5,cb6,cb7,cb8,cb9;
//
This method creates layout and main objects.
MainWindow(String title, boolean isapp,
Marbles i_in) {
super(title);
is_applet = isapp;
i = i_in;
Panel p = new Panel(); // control panel
Label n = new Label("Marbles
1.0");
p.setLayout(new GridLayout(0,1)); //
vertical layout
p.setFont(new
Font("Helvetica",Font.BOLD,12));
n.setFont(new
Font("TimesRoman",Font.BOLD,16));
p.add(n);
p.add(new Button("quit"));
p.add(inst=new Label(""));
p.add(grav=new TextField(40));
grav.setText("");
p.add(label1=new Label(""));
p.add(cb1=new Checkbox(""));
p.add(label2=new Label(""));
p.add(cb2=new Checkbox(""));
p.add(label3=new Label(""));
p.add(cb3=new Checkbox(""));
p.add(label4=new Label(""));
p.add(cb4=new Checkbox(""));
p.add(label5=new Label(""));
p.add(cb5=new Checkbox(""));
p.add(label6=new Label(""));
p.add(cb6=new Checkbox(""));
p.add(label7=new Label(""));
p.add(cb7=new Checkbox(""));
p.add(label8=new Label(""));
p.add(cb8=new Checkbox(""));
p.add(label9=new Label(""));
p.add(cb9=new Checkbox(""));
//Qgov();
Qctime();
tick = new Ticker(p); // pace maker for
the animator
anim = new Animator(tick,p,this);
setLayout(new BorderLayout(2,2));
add("Center",anim);
add("West",p);
pwindow = new MyFrame("Choose
Pieces",i);
pwindow.resize(400,480);
pwindow.hide();
}
//
This starts the threads.
public void start() {
if (anim_thread==null) {
anim_thread = new Thread(anim);
anim_thread.start(); //
start new thread
}
if (tick_thread==null) {
tick_thread = new Thread(tick);
tick_thread.start(); // start new thread
}
}
//
This stops the threads.
public void stop() {
if (anim_thread!=null) {
anim_thread.stop(); //
kill the thread
anim_thread = null; //
release object
}
if (tick_thread!=null) {
tick_thread.stop(); //
kill the thread
tick_thread = null; //
release object
}
}
//
These handle user input events.
public boolean action(Event e, Object arg) {
if (e.target instanceof Button) {
if
(((String)arg).equals("quit")) {
stop();
hide(); // I don't know if all this is necessary.
removeAll();
dispose();
if (!is_applet) System.exit(0);
}
else return false;
return true;
}
if(cb1.getState()==true) {
i.pts.writeToServer("1" +
i.qno + "" + i.pn + "0");
cb1.setState(false);
}
else if(cb2.getState()==true) {
i.pts.writeToServer("1" +
i.qno + "" + i.pn + "1");
cb2.setState(false);
}
else if(cb3.getState()==true) {
i.pts.writeToServer("1" +
i.qno + "" + i.pn + "2");
cb3.setState(false);
}
else if(cb4.getState()==true) {
i.pts.writeToServer("1" +
i.qno + "" + i.pn + "3");
cb4.setState(false);
}
else if(cb5.getState()==true) {
i.pts.writeToServer("1" +
i.qno + "" + i.pn + "4");
cb5.setState(false);
}
else if(cb6.getState()==true) {
i.pts.writeToServer("1" +
i.qno + "" + i.pn + "5");
cb6.setState(false);
}
else if(cb7.getState()==true) {
i.pts.writeToServer("1" +
i.qno + "" + i.pn + "6");
cb7.setState(false);
}
else if(cb8.getState()==true) {
i.pts.writeToServer("1" +
i.qno + "" + i.pn + "7");
cb8.setState(false);
}
else if(cb9.getState()==true) {
i.pts.writeToServer("1" +
i.qno + "" + i.pn + "8");
cb9.setState(false);
}
return false;
}
protected void Qgov() {
labelCheckBoxes("What Government
Type?","Democratic","Democratic Hi-Lo",
"Autocratic","","","","","","");
}
protected void Qlibrary() {
labelCheckBoxes("Library Game or
Players Rules","Library","Players",
"","","","","","","");
}
protected void Qchange() {
labelCheckBoxes("Which Do You Want
To Change Next Round?","Government","Objects",
"Events","Physics","Rules","Winning","","","");
}
protected void QnumEvents() {
labelCheckBoxes("How Many Event
Types Would You Like?","1","2",
"3","4","5","6","7","","");
}
protected void QnumPieces() {
labelCheckBoxes("How Many Piece
Types Would You Like?","1","2",
"3","4","5","6","7","","");
}
protected void QnumArsenal() {
labelCheckBoxes("How Many Arsenal
Items Would You Like?","1","2",
"3","4","5","6","7","","");
}
protected void Qctime() {
labelCheckBoxes("How Much Time To
Make Choices?","5 seconds","10 seconds",
"15
seconds","20 seconds","25 seconds","30
seconds","45 seconds",
"1
minute","2 minutes");
}
protected void QslantQtype() {
labelCheckBoxes("How Should the
Slant Queue Work?","Take Turns",
"FIFO","Random","","","","","","");
}
protected void QslantQwrap() {
labelCheckBoxes("Should the Slant
Queue Wrap to Next Round?","YES",
"NO","","","","","","","");
}
protected void QslantQtime() {
labelCheckBoxes("How Often Should
Slant Change?","20 frames","40 frames",
"60
frames","80 frames","100 frames","120
frames","150 frames",
"","");
}
protected void Qbumpers() {
labelCheckBoxes("Should There Be
Bumpers?","YES",
"NO","Change
w/Turns","","","","","","");
}
protected void Qwinning() {
labelCheckBoxes("How Compensated
for Winning?","More Goals","Bigger Ball",
"More
Points/Goal","","","","","","");
}
protected void QnextRound() {
labelCheckBoxes("What Type of
Round Next?","Competitive","Collaborative",
"Teams of
2","","","","","","");
}
protected void QeventQlag() {
labelCheckBoxes("How Many Frames
for Event Queue Lag?","20 frames","30 frames",
"40
frames","50 frames","60 frames","70
frames","","","");
}
protected void QeventDuration() {
labelCheckBoxes("How Many Frames
Is Event Active?","40 frames","60 frames",
"80
frames","100 frames","120 frames","150
frames","","","");
}
protected void Qgravity() {
labelCheckBoxes("How High Gravity
(1-low,9-high)?","1","2",
"3","4","5","6","7","8","9");
}
protected void Qrestitution() {
labelCheckBoxes("How High
Restitution (1-low,9-high)?","1","2",
"3","4","5","6","7","8","9");
}
protected void Qmass() {
labelCheckBoxes("How High Mass
(1-low,9-high)?","1","2",
"3","4","5","6","7","8","9");
}
protected void Qviscosity() {
labelCheckBoxes("How High
Viscosity (1-low,9-high)?","1","2",
"3","4","5","6","7","8","9");
}
protected void Qpieces() {
for(int x=1;x<7;x++) {
i.image[x-1]=i.getImage(i.getCodeBase(), "images/" + x +
".gif");
}
pwindow.label11.setText("Small
Spherical Barrier");
pwindow.label12.setText("Horizontal Stick Barrier");
pwindow.label13.setText("Vertical
Stick Barrier");
pwindow.label14.setText("Vertical
Rotated 45 Degrees");
pwindow.label15.setText("Vertical
Rotated -45 Degrees");
pwindow.label16.setText("Variable
Size Spherical Barrier");
pwindow.label17.setText("Pendulum");
pwindow.label18.setText("Rotating
Cross");
pwindow.label19.setText("");
pwindow.label20.setText("");
pwindow.show(); //.hide() will hide the
window.
}
protected void Qeffects() {
for(int x=1;x<7;x++) {
i.image[x-1]=null;
i.image[x-1]=i.getImage(i.getCodeBase(), "images/10" + x +
".gif");
}
pwindow.label11.setText("No
Collisions");
pwindow.label12.setText("Anti-Gravity");
pwindow.label13.setText("Stop");
pwindow.label14.setText("Grab A
Goal");
pwindow.label15.setText("Create a
New Barrier");
pwindow.label16.setText("Double
Ball Radius");
pwindow.label17.setText("");
pwindow.label18.setText("");
pwindow.label19.setText("");
pwindow.label20.setText("");
pwindow.show(); //.hide() will hide the
window.
}
protected void labelCheckBoxes(String txt,
String cblbl1, String cblbl2, String cblbl3,
String
cblbl4, String cblbl5, String cblbl6,
String
cblbl7, String cblbl8, String cblbl9) {
inst.setText(txt);
label1.setText(cblbl1);
label2.setText(cblbl2);
label3.setText(cblbl3);
label4.setText(cblbl4);
label5.setText(cblbl5);
label6.setText(cblbl6);
label7.setText(cblbl7);
label8.setText(cblbl8);
label9.setText(cblbl9);
}
//{{DECLARE_CONTROLS
//}}
//{{DECLARE_MENUS
//}}
}
class
MyFrame extends Frame {
Checkbox
cb11,cb12,cb13,cb14,cb15,cb16,cb17,cb18,cb19,cb20;
Label
label11,label12,label13,label14,label15,
label16,label17,label18,label19,label20;
MyCanvas pPictures;
Marbles m;
int fmode=0;
MyFrame(String title, Marbles m_in) {
super(title);
m = m_in;
setLayout(new GridLayout(1,3,0,0));
Panel one=new Panel();
Panel three=new Panel();
add("first",one);
pPictures = new MyCanvas(this);
pPictures.setBackground(Color.black);
add(pPictures);
add("third",three);
one.setLayout(new
GridLayout(11,1,0,0));
one.add(cb11=new
Checkbox(""));
one.add(cb12=new
Checkbox(""));
one.add(cb13=new
Checkbox(""));
one.add(cb14=new Checkbox(""));
one.add(cb15=new
Checkbox(""));
one.add(cb16=new
Checkbox(""));
one.add(cb17=new
Checkbox(""));
one.add(cb18=new
Checkbox(""));
one.add(cb19=new
Checkbox(""));
one.add(cb20=new
Checkbox(""));
//one.add(new Button("OK"));
three.setLayout(new
GridLayout(11,1,0,0));
three.add(label11=new
Label(""));
three.add(label12=new
Label(""));
three.add(label13=new
Label(""));
three.add(label14=new
Label(""));
three.add(label15=new
Label(""));
three.add(label16=new
Label(""));
three.add(label17=new
Label(""));
three.add(label18=new
Label(""));
three.add(label19=new
Label(""));
three.add(label20=new
Label(""));
}
public boolean action(Event e, Object arg)
{
if(cb11.getState()==true) {
m.pts.writeToServer("1" +
m.qno + "" + m.pn + "1");
cb11.setState(false);
}
if(cb12.getState()==true) {
m.pts.writeToServer("1" +
m.qno + "" + m.pn + "2");
cb12.setState(false);
}
if(cb13.getState()==true) {
m.pts.writeToServer("1" +
m.qno + "" + m.pn + "3");
cb13.setState(false);
}
if(cb14.getState()==true) {
m.pts.writeToServer("1" +
m.qno + "" + m.pn + "4");
cb14.setState(false);
}
if(cb15.getState()==true) {
m.pts.writeToServer("1" +
m.qno + "" + m.pn + "5");
cb15.setState(false);
}
if(cb16.getState()==true) {
m.pts.writeToServer("1" +
m.qno + "" + m.pn + "6");
cb16.setState(false);
}
if(cb17.getState()==true) {
m.pts.writeToServer("1" +
m.qno + "" + m.pn + "7");
cb17.setState(false);
}
if(cb18.getState()==true) {
m.pts.writeToServer("1" +
m.qno + "" + m.pn + "8");
cb18.setState(false);
}
return true;
}
//{{DECLARE_CONTROLS
//}}
//{{DECLARE_MENUS
//}}
}
class
MyCanvas extends Canvas {
MyFrame f;
MyCanvas(MyFrame f_in) {
f=f_in;
}
public void drawPieces() {
}
public void paint(Graphics g) {
for(int x=0;x<6;x++) {
g.drawImage(f.m.image[x],5,(x*40)+5,this);
}
}
}
//-------------------------------------------------------------------
// This class performs the animation in the
main canvas.
class
Animator extends Canvas implements Runnable {
final int max = 50;
final int maxeg = 30;
final int maxp = 20;
int maxg = 10;
int num=0; // number of balls
int numo=0; // number of obstacles
int numg=0; // number of goals
int
captg=0; // number of captured
goals
int round=1;
Ball[] ball = new Ball[max]; // array of balls
Obstacle[] obstacle = new Obstacle[max]; // array of obstacles
SlantQueue sq = new SlantQueue(60);
EffectsQueue eq = new EffectsQueue(60);
Effects es = new Effects(20);
Arsenal ars = new Arsenal(7);
Pieces ps = new Pieces(20);
Goal[] goal = new Goal[maxeg]; //
array of goals
int goalvalue[]={100,100,100,100}; //current goal values
int[] rs = {0,0,0,0}; // round
scores
Physics[] phys = new Physics[maxp]; // array
of physics
Ticker tick;
long starttime;
boolean timeOK=true;
Date theDate;
long count=0;
MainWindow mw;
Rules rules = new Rules(); // Rules Structure
boolean clearAll;
//
The following are some "physical" properties. Each property
//
has a value and a control. The
values are updated once per
//
animation loop (this is for efficiency).
public double g,vg,hg,mg,f,r,bm;
public boolean trc,col,mu,wrapon,sm;
public int xsize,ysize,sqt,eql,eqd;
Animator(Ticker t, Panel p, MainWindow m) {
tick = t;
mw = m;
setBackground(Color.black);
xsize = 1000; //width of playing board
ysize = 1000; //height of playing board
vg = 0.0;
hg = 0.0;
sqt = 100;
eql = 50;
eqd = 150;
f = .50;
//effect of viscosity
g = .25;
//effect of gravity
r = .75;
//effect of restitution
bm = 64;
//ball mass
col = true;
wrapon = true;
loadPhysics();
}
//
The run method updates the locations of the balls.
public void run() {
while(true) {
while (captg<numg || numg==0) {
if(mw.i.mode>2 || mw.i.speedtest) {
if(mw.i.speedtest && count==0)
{
addBall(new
Ball(64,20,Color.blue,500,100,0.0,0.0,this,0));
mw.i.addNode(num-1,0,20,1,1,1,0);
addBall(new
Ball(64,20,Color.blue,100,500,0.0,0.0,this,0));
mw.i.addNode(num-1,0,20,1,1,1,0);
addBall(new
Ball(64,20,Color.blue,900,500,0.0,0.0,this,0));
mw.i.addNode(num-1,0,20,1,1,1,0);
addBall(new
Ball(64,20,Color.blue,500,900,0.0,0.0,this,0));
mw.i.addNode(num-1,0,20,1,1,1,0);
vg=.33;
theDate = new Date();
starttime =
theDate.getTime();
}
for (int i=0; i<num; ++i) {
if(ball[i].e!=1) { //e=1 means not
collidable
for (int j=0; j<numo; ++j) { //look for collisions with obstacles
ball[i].interact(obstacle[j]);
}
for (int j=i+1; j<num; ++j) { //look for collisions with balls
ball[i].interact(ball[j]);
}
}
if(i<4) { //ball is one of the
players
for (int j=0; j<numg; ++j) {
//look for collisions with goals
if (ball[i].interact(goal[j])) {
if(goal[j].c > 3 || ball[i].e==4) { //ball effect=4
is goal stealing
mw.i.removeGoal[j].setValue(mw.i.goalshape[j]);
if(goal[j].c > 3) {captg++;}
if(rules.roundtype==0)
{ goal[j].c = i; }
else
if(rules.roundtype==1) { goal[j].c=3; }
else
if(rules.roundtype==2) {
if(i==0||i==3) {
goal[j].c=2;
} else {
goal[j].c=1; }
}
rs[i]=rs[i]+goalvalue[i]; //value for each goal
mw.i.addGoal(j,goal[j].c,goal[j].x,goal[j].y);
}
}
}
}
}
for (int j=0; j<num; ++j) {
if(ball[j].t==0) {
if(ball[j].e==3) { //e=3 is ball stoppage
ball[j].vx = 0.0;
ball[j].vy = 0.0;
} else {
ball[j].update();
}
}
if(ball[j].t==1) {
ball[j].vx = 0.0;
ball[j].vy = 0.0;
}
if(ball[j].t==2||ball[j].t==8) {
//Pendulum
if(count%40==0) {
if(ball[j].t==2){
for(int k=1;k<5;k++) {
ball[j+k].x=ball[j].x-(21.25*k);
ball[j+k].y=ball[j].y-(10*k);
ball[j+k].vx=phys[k].x[0];
ball[j+k].vy=phys[k].y[0];
}
} else {
ball[j+1].y=ball[j].y+60;
ball[j+2].x=ball[j].x+60;
ball[j+3].y=ball[j].y-60;
ball[j+4].x=ball[j].x-60;
for(int k=1;k<5;k++)
{
ball[j+k].vx=phys[k].x[0];
ball[j+k].vy=phys[k].y[0];
}
}
} else {
int index=0;
while(count%40>=phys[1].t[index]) {
index++;
}
for(int k=1;k<5;k++) {
if(ball[j].t==2){
ball[j+k].vx=phys[k].x[index];
ball[j+k].vy=phys[k].y[index];
} else {
ball[j+k].vx=phys[k+5].x[index];
ball[j+k].vy=phys[k+5].y[index];
}
}
}
for(int k=0;k<5;k++) {
ball[j+k].y +=
ball[j+k].vy;
ball[j+k].x +=
ball[j+k].vx;
mw.i.UpdateVRML(3,j+k,(float)ball[j+k].x,(float)ball[j+k].y,0,0,0,0,0);
}
j=j+4;
}
if(ball[j].t==3) {
//Increasing Scale
ball[j].vx = 0.0;
ball[j].vy = 0.0;
ball[j].z *= 1.1;
mw.i.UpdateScale(j,(float)(ball[j].z/40));
if(ball[j].z > 40.0) {
ball[j].t = 4;
}
}
if(ball[j].t==4) {
//Decreasing Scale
ball[j].vx = 0.0;
ball[j].vy = 0.0;
ball[j].z *= (1/1.1);
mw.i.UpdateScale(j,(float)(ball[j].z/40));
if(ball[j].z < 2.0) {
ball[j].t = 3;
}
}
}
}
DrawBalls();
tick.poll(); // wait for tick
if (mw.i.mode>2 || mw.i.speedtest) {
if (count%sqt==0) {
int qs=sq.TakeFromSlantQueue();
if (qs==1) {
vg = g;
hg = 0.0;
mw.i.UpdateRotation(0,0);
mw.i.UpdateVRML(1,101,0,0,100,0,0,0,0);
}
else if (qs==2) {
vg = 0.0;
hg = g;
mw.i.UpdateRotation(0,1);
mw.i.UpdateVRML(1,101,0,0,100,0,0,0,0);
}
else if (qs==3) {
vg = -g;
hg = 0.0;
mw.i.UpdateRotation(0,2);
mw.i.UpdateVRML(2,101,0,0,0,0,0,0,0);
}
else if (qs==4) {
vg = 0.0;
hg = -g;
mw.i.UpdateRotation(0,3);
mw.i.UpdateVRML(2,101,0,0,0,0,0,0,0);
}
int val=sq.InterrogateSlantQueue(0);
if((val==-1)&&(mw.i.pn==mw.i.turncolor)&&(mw.i.mode>2))
{
val=(int)((Math.random()*4)+1);
mw.i.pts.writeToServer("2" + val); //can't have an empty slant
queue at any point in time
}
mw.i.addSlQu(0,val,false); //show
next queue
val=-1;
for(int ww=1;ww<4;ww++) { //Show
upcoming slants
val=sq.InterrogateSlantQueue(ww);
if(val>=0 &&
val<=4) { mw.i.addSlQu(ww,val,false); }
else if(val==-1) {
mw.i.addSlQu(ww,0,false); }
}
}
//HandleEventsQueue
if
(eq.GetEffectsQueueTime(0)<count) {
int cureffect =
eq.GetEffectsQueueEffect(0);
//cureffect is ball number plus event -- example: 101
int curballno = cureffect/100;
if(ball[curballno].e==6) { //e=6 is
grow marble
ball[curballno].z =
ball[curballno].z/2;
mw.i.UpdateScale(curballno,1);
}
ball[curballno].e =
eq.TakeFromEffectsQueue()%100;
if(ball[curballno].e==5) { //e=5 is add an obstacle
mw.i.curnode=50+numo;
mw.i.removeChildren[mw.i.curnode].setValue(mw.i.pieceshape[mw.i.curnode]);
mw.i.pts.writeToServer("4" + mw.i.pn + "" +
"2" + (100 + mw.i.curnode) +
(1000 + (int)
ball[curballno].x) + (1000 + (int) ball[curballno].y-25));
} else if(ball[curballno].e==6) {
//e=6 is make ball bigger
ball[curballno].z =
ball[curballno].z*2;
mw.i.UpdateScale(curballno,2);
}
}
count++;
if(count%50==0 &&
!mw.i.speedtest) { //coordinate speed
with server
theDate = new Date();
mw.i.pts.writeToServer("8" + mw.i.pn + "" +
(count/50 + 100) + "" + (theDate.getTime() - starttime));
starttime=theDate.getTime();
//timeOK=false;
//} else if((count-40)%100==0
&& !mw.i.speedtest) { //make
sure have a valid time back
//
if(timeOK=false){ tick.speed=2000; } //someone has not reported in yet
} else if(mw.i.speedtest &&
count==50) {
theDate = new Date();
mw.i.pts.writeToServer("8" + mw.i.pn + "100" +
(theDate.getTime() - starttime));
mw.i.speedtest=false;
count=0;
mw.i.UpdateColor(0,mw.i.pn); //show player who they are
for(int xz=0;xz<4;xz++) {
mw.i.removeChildren[xz].setValue(mw.i.pieceshape[xz]);
ball[xz].vx=0.0;
ball[xz].vy=0.0;
}
vg=0.0;
}
mw.i.showStatus("count= " +
count + " speed " + tick.speed);
if(count==2000) { //too long to wait
-- end turn
mw.i.pts.writeToServer("98" + captg);
numg=captg;
}
}
} //end while loop
if(count<2000) { //write out number of
frames to finish
mw.i.pts.writeToServer("99"
+ count);
}
ResetGame();
round++;
}
}
public void ResetGame() { //HGC
double share=0.0;
//TALLY RESULTS FROM LAST ROUND
for(int i=0;i<4;i++) {
if(rules.roundtype==0) {
mw.i.player[i].IncreasePlayerScore(rs[i]); }
else
if(rules.roundtype==1&&rules.winning==0) {
if(numg/maxg>.8) {
if(maxg<29) { maxg=maxg+2; } }
else if(numg/maxg>.5) {
if(maxg<30) { maxg++; } }
else if(numg/maxg>.2) {
if(maxg>2) { maxg=maxg-1; } }
else { if(maxg>3) { maxg=maxg-2; } }
}
else if(rules.roundtype==2) {
if(i==0||i==3) {
mw.i.player[i].IncreasePlayerScore((rs[0] + rs[3])/2);
} else {
mw.i.player[i].IncreasePlayerScore((rs[1] + rs[2])/2);
}
}
}
if(rules.winning==1) {
for(int i=0;i<4;i++) {
if(rules.roundtype==0) {
share=rs[i]/((rs[0]+rs[1]+rs[2]+rs[3])/4);
if(share==0) {
ball[i].z=ball[i].z*.7; }
else if(share<.15) {
ball[i].z=ball[i].z*.85; }
else if(share<.35) { } //No
Change
else if(share<.55) {
ball[i].z=ball[i].z/.85; }
else if(share<=1) { ball[i].z=ball[i].z/.7; }
}
else if(rules.roundtype==1) {
if(numg/maxg>.8) {
if(maxg<29) { ball[i].z=ball[i].z/.7; } }
else if(numg/maxg>.5) {
if(maxg<30) { ball[i].z=ball[i].z/.85; } }
else if(numg/maxg>.35) {
if(maxg>2) { } }
else if(numg/maxg>.2) {
if(maxg>2) { ball[i].z=ball[i].z*.85;} }
else { if(maxg>3) {
ball[i].z=ball[i].z*.7; } }
}
else if(rules.roundtype==2) {
if(i==0||i==3) {
share=(rs[0]+rs[3])/((rs[0]+rs[1]+rs[2]+rs[3])/4);
}
else {
share=(rs[1]+rs[2])/((rs[0]+rs[1]+rs[2]+rs[3])/4);
}
if(share==0) {
ball[i].z=ball[i].z*.7; }
else if(share<.3) { ball[i].z=ball[i].z*.85; }
else if(share<.7) { } //No
Change
else if(share<1) {
ball[i].z=ball[i].z/.85; }
else if(share==1) { ball[i].z=ball[i].z/.7; }
}
}
}
else if(rules.winning==2) {
for(int i=0;i<4;i++) {
if(rules.roundtype==0) {
share=rs[i]/((rs[0]+rs[1]+rs[2]+rs[3])/4);
if(share==0) {
goalvalue[i]=goalvalue[i]-16; }
else if(share<.15) {
goalvalue[i]=goalvalue[i]-8; }
else if(share<.35) { } //No
Change
else if(share<.55) {
goalvalue[i]=goalvalue[i]+8; }
else if(share<=1) { goalvalue[i]=goalvalue[i]+16; }
}
else if(rules.roundtype==1) {
if(numg/maxg>.8) {
goalvalue[i]=goalvalue[i]+16; }
else if(numg/maxg>.5) {
goalvalue[i]=goalvalue[i]+8; }
else if(numg/maxg>.35) { }
else if(numg/maxg>.2) {
goalvalue[i]=goalvalue[i]-8; }
else {
goalvalue[i]=goalvalue[i]-16; }
}
else if(rules.roundtype==2) {
if(i==0||i==3) {
share=(rs[0]+rs[3])/((rs[0]+rs[1]+rs[2]+rs[3])/4);
}
else {
share=(rs[1]+rs[2])/((rs[0]+rs[1]+rs[2]+rs[3])/4);
}
if(share==0) {
goalvalue[i]=goalvalue[i]-16; }
else if(share<.3) {
goalvalue[i]=goalvalue[i]-8; }
else if(share<.7) { } //No
Change
else if(share<1) {
goalvalue[i]=goalvalue[i]+8; }
else if(share==1) { goalvalue[i]=goalvalue[i]+16; }
}
}
}
mw.i.showStatus("Team Score
Time: " + count + " Captured
Goals: " + captg);
//mw.i.showStatus("Current
Score: Yellow " +
mw.i.player[0].GetPlayerScore() +
// " Red " +
mw.i.player[1].GetPlayerScore() +
// " Blue " +
mw.i.player[2].GetPlayerScore() +
// " Green " +
mw.i.player[3].GetPlayerScore());
for(int xx=0;xx<4;xx++) {
rs[xx]=0;
}
mw.i.mode=0;
mw.i.lastmodesent=0;
for(int x=0;x<50;x++) { //put balls
and obstacles back
if(x>3) {
mw.i.removeChildren[x].setValue(mw.i.pieceshape[x]);
ball[x]=null;
}
mw.i.removeChildren[x+50].setValue(mw.i.pieceshape[x+50]);
obstacle[x]=null;
}
for(int j=0; j<numg; ++j) { //put goals back
mw.i.removeGoal[j].setValue(mw.i.goalshape[j]);
goal[j]=null;
}
ball[0].x = 500;
ball[0].vx = 0.0;
ball[0].y = 100;
ball[0].vy = 0.0;
mw.i.UpdateVRML(3,0,(float)ball[0].x,(float)ball[0].y,0,0,0,0,0);
ball[1].x = 100;
ball[1].vx = 0.0;
ball[1].y = 500;
ball[1].vy = 0.0;
mw.i.UpdateVRML(3,1,(float)ball[1].x,(float)ball[1].y,0,0,0,0,0);
ball[2].x = 900;
ball[2].vx = 0.0;
ball[2].y = 500;
ball[2].vy = 0.0;
mw.i.UpdateVRML(3,2,(float)ball[2].x,(float)ball[2].y,0,0,0,0,0);
ball[3].x = 500;
ball[3].vx = 0.0;
ball[3].y = 900;
ball[3].vy = 0.0;
mw.i.UpdateVRML(3,3,(float)ball[3].x,(float)ball[3].y,0,0,0,0,0);
numo=0; num=4; numg=0; captg=0;
mw.i.UpdateRotation(0,4);
mw.i.UpdateVRML(1,101,0,0,0,0,0,0,0);
if(rules.slantQclear==true) { //reset
slant queue if chosen
for(int zz=0;zz<60;zz++) {
sq.t[zz]=-1;
sq.size=0;
sq.head=0;
sq.tail=0;
}
for(int xx=0;xx<4;xx++) {
mw.i.addSlQu(xx,0,false);
}
}
for(int yy=0;yy<60;yy++) { //reset
event queue
eq.t[yy]=-1;
eq.e[yy]=-1;
eq.size=0;
eq.head=0;
eq.tail=0;
}
mw.i.Paletize(4);
mw.i.Bumpers(1);
wrapon=false;
mw.i.UpdatePointer(0,0,0,30,0,0,0,0);
mw.i.pts.goalcount=0;
//mw.i.lst.createGoals(maxg);
}
//
The DrawBalls method displays objects.
public void DrawBalls() {
int j=0;
float x=0,y=0;
for (j=0; j<num; ++j) {
x = (float) (ball[j].x);
y = (float) (ball[j].y);
if(ball[j].t<1)
mw.i.UpdateVRML(1,j,x,y,0,0,0,0,0);
}
}
//
These adds balls
public void addMoving(int m,int r,float
x,float y,int t,int c0,int c1,int c2) {
addBall(new
Ball(m,r,Color.pink,x,y,0.0,0.0,this,t));
mw.i.addNode(num-1,0,r,c0,c1,c2,0);
x=(float)ball[num-1].x;
y=(float)ball[num-1].y;
addBall(new
Ball(m,r,Color.pink,x,y,3.0,1.5,this,t));
mw.i.addNode(num-1,0,r,c0,c1,c2,0);
mw.i.UpdateVRML(1,num-1,x,y,0,0,0,0,0);
addBall(new
Ball(m,r,Color.pink,x,y,6.0,3.0,this,t));
mw.i.addNode(num-1,0,r,c0,c1,c2,0);
mw.i.UpdateVRML(1,num-1,x,y,0,0,0,0,0);
addBall(new
Ball(m,r,Color.pink,x,y,9.0,4.5,this,t));
mw.i.addNode(num-1,0,r,c0,c1,c2,0);
mw.i.UpdateVRML(1,num-1,x,y,0,0,0,0,0);
addBall(new Ball(m,r,Color.pink,x,y,12.0,6.0,this,t));
mw.i.addNode(num-1,0,r,c0,c1,c2,0);
mw.i.UpdateVRML(1,num-1,x,y,0,0,0,0,0);
}
public void addBall(Ball b) {
if (num<max) ball[num++] = b;
}
//
This adds obstacles.
public void addObstacle(Obstacle o) {
if (numo<max) obstacle[numo++] = o;
}
public void addGoal(Goal g) {
if (numg<maxg) goal[numg++] = g;
if(numg==1) {
sq.AddtoSlantQueue((int)((goal[0].x%4)+1)); //start with a random slant
(can't be empty)
sq.AddtoSlantQueue((int)((goal[0].y%4)+1)); //and one random slant in
queue (can't be empty)
for(int ww=0;ww<4;ww++) { //Show
upcoming slants
int
val=sq.InterrogateSlantQueue(ww);
if(val>=0 && val<=4)
{ mw.i.addSlQu(ww,val,false); }
else if(val==-1) {
mw.i.addSlQu(ww,0,false); }
}
}
}
public void loadPhysics() {
phys[0] = new
Physics(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
10,20,30,40,0,0,0,0);
phys[1] = new
Physics(2.125,2.125,-2.125,-2.125,0.0,0.0,0.0,0.0,
-1.0,1.0,-1.0,1.0,0.0,0.0,0.0,0.0,
10,20,30,40,0,0,0,0);
phys[2] = new
Physics(4.25,4.25,-4.25,-4.25,0.0,0.0,0.0,0.0,
-2.0,2.0,-2.0,2.0,0.0,0.0,0.0,0.0,
10,20,30,40,0,0,0,0);
phys[3] = new
Physics(6.375,6.375,-6.375,-6.375,0.0,0.0,0.0,0.0,
-3.0,3.0,-3.0,3.0,0.0,0.0,0.0,0.0,
10,20,30,40,0,0,0,0);
phys[4] = new
Physics(8.5,8.5,-8.5,-8.5,0.0,0.0,0.0,0.0,
-4.0,4.0,-4.0,4.0,0.0,0.0,0.0,0.0,
10,20,30,40,0,0,0,0);
phys[5] = new
Physics(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
10,20,30,40,0,0,0,0);
phys[6] = new
Physics(6.0,-6.0,-6.0,6.0,0.0,0.0,0.0,0.0,
-6.0,-6.0,6.0,6.0,0.0,0.0,0.0,0.0,
10,20,30,40,0,0,0,0);
phys[7] = new
Physics(-6.0,-6.0,6.0,6.0,0.0,0.0,0.0,0.0,
-6.0,6.0,6.0,-6.0,0.0,0.0,0.0,0.0,
10,20,30,40,0,0,0,0);
phys[8] = new
Physics(-6.0,6.0,6.0,-6.0,0.0,0.0,0.0,0.0,
6.0,6.0,-6.0,-6.0,0.0,0.0,0.0,0.0,
10,20,30,40,0,0,0,0);
phys[9] = new
Physics(6.0,6.0,-6.0,-6.0,0.0,0.0,0.0,0.0,
6.0,-6.0,-6.0,6.0,0.0,0.0,0.0,0.0,
10,20,30,40,0,0,0,0);
}
//
This returns the index of the ball nearest to x,y
//
excluding ex. (wrap is not taken
into account).
int nearestBall(int x, int y, int ex) {
double d=1e20,t; int j=0;
for (int i=0; i<num; ++i) {
t = Ball.hypot(x - ball[i].x, y -
ball[i].y);
if (t < d && i!=ex) { d = t;
j = i; }
}
return j;
}
void rotate(int j) {
double d,mm,dx,dy,tt;
d =
Ball.hypot(ball[j].x-ball[j-1].x,ball[j].y-ball[j-1].y);
if
(d<1e-20) return; // too close
mm = ball[j].m + ball[j-1].m;
if (mm<1e-50 && mm>-1e-50)
return; // too small
tt = Math.sqrt(20/mm/d)/d;
dy = tt*(ball[j].x - ball[j-1].x); // perpendicular direction vector
dx = tt*(ball[j-1].y - ball[j].y);
ball[j].vx = - dx*ball[j-1].m;
ball[j].vy = - dy*ball[j-1].m;
}
// This adjusts the frame of reference so
that the total momentum becomes zero.
void zeroMomentum() {
double mx=0,my=0,M=0;
for (int i=0; i<num; ++i) {
mx += ball[i].vx * ball[i].m;
my += ball[i].vy * ball[i].m;
M += ball[i].m;
}
if (M != 0)
for (int i=0; i<num; ++i) {
ball[i].vx -= mx/M;
ball[i].vy -= my/M;
}
}
//
This adjusts the centroid to the center of the canvas.
//
Note, the "while" loops here could be simply use %= but some
//
interpreters have bugs with %=.
void centerMass() {
double x,y,cx=0,cy=0,M=0;
for (int i=0; i<num; ++i) {
x = ball[i].x; y = ball[i].y;
if (wrapon) { // if wrap, convert the top 1/4 to negative
if (x > xsize*0.75) x -= xsize;
if (y > ysize*0.75) y -= ysize;
}
cx += ball[i].x * ball[i].m;
cy += ball[i].y * ball[i].m;
M += ball[i].m;
}
if (M != 0)
for (int i=0; i<num; ++i) {
ball[i].x += xsize/2 - cx/M;
ball[i].y += ysize/2 - cy/M;
while (ball[i].x < 0) ball[i].x +=
xsize;
while (ball[i].x > xsize) ball[i].x
-= xsize;
while (ball[i].y < 0) ball[i].y +=
ysize;
while (ball[i].y > ysize) ball[i].y
-= ysize;
}
}
}
//--------------------------------------------------------------------------------------------
// The Ball class
class
Ball {
double x,y;
// location
double z; // radius
double vx,vy; // velocity
Color c; // color
double m; // mass
boolean hit;
// scratch field
double ox,oy; // old location (for smooth redraw)
final double vmin = 1e-20;
// a weak force to prevent overlapping
Animator a;
boolean iok;
// image is ok.
Image img;
// a bitmap to use in "filled" mode
int t; // type of Ball
int e; // current effect on the ball
Ball(double mass, double radius, Color
color,
double px, double py, double sx, double
sy, Animator an, int typ) {
m=mass; z=radius-0.5; c=color; t=typ;
if (z<0.5) z =
Math.min(Math.sqrt(Math.abs(m)),Math.min(px,py));
if (z<0.5) z=0.5;
x=px; y=py; vx=sx; vy=sy;
iok = false;
a = an;
e = 0;
if(color==Color.white) t=1;
}
//
This updates a ball according to the physical universe.
//
The reason I exempt a ball from gravity during a hit is
//
to simulate "at rest" equilibrium when the ball is resting
//
on the floor or on another ball.
void UpdateBall(double dx, double dy) {
x=dx; y=dy;
}
void AddBallEffect(int ex) {
e=ex;
}
public void update() {
x += vx;
if (x+z > a.xsize)
if (a.wrapon) {
x -= a.xsize;
} else {
if (vx > 0) vx *= a.r; // restitution
vx = -Math.abs(vx)-vmin; // reverse velocity
x = a.xsize-z;
hit = true;
//
Check if location is completely off screen
if (x-z > a.xsize) x = a.xsize + z;
}
if (x-z < 0)
if (a.wrapon) x += a.xsize;
else {
if (vx < 0) vx *= a.r; // restitution
vx = Math.abs(vx)+vmin; // reverse velocity
x = z;
hit = true;
if (x+z < 0) x = -z;
}
y += vy;
if (y+z > a.ysize) {
if (a.wrapon) y -= a.ysize;
else {
vy = -1*vy;
y = a.ysize-z;
}
}
if (y-z < 0) {
if (a.wrapon) {
y += a.ysize;
}
else {
vy = -1*vy;
y = z;
}
}
if (a.f > 0 && m != 0) { // viscosity
double t = 100/(100 +
a.f*hypot(vx,vy)*z*z/m);
vx *= t; vy *= t;
}
if (!hit) {
if (e==2) { // effect of 2 means anti-gravity
vy -= a.vg; // if not hit, exert anti-gravity
vx -= a.hg;
} else {
vy += a.vg; // if not hit, exert gravity
vx += a.hg;
}
}
hit = false; // reset flag
}
//
This computes the interaction of two balls, either collision
//
or gravitational force.
public boolean interact(Goal g) {
double p = g.x - x;
double q = g.y - y;
double h2 = p*p + q*q;
double h = Math.sqrt(h2);
if (h < z+g.r) { // HIT
hit = true;
return true;
} else {
return false;
}
}
public boolean interact(Ball b) {
double p = b.x - x;
double q = b.y - y;
if (a.wrapon) { // wrap around, use shortest distance
if (p > a.xsize/2) p-=a.xsize;
else if (p < -a.xsize/2) p+=a.xsize;
if (q > a.ysize/2) q-=a.ysize;
else if (q < -a.ysize/2) q+=a.ysize;
}
double h2 = p*p + q*q;
double h = Math.sqrt(h2);
if (a.col) { // collisions enabled
if (h < z+b.z) { // HIT
hit = b.hit = true;
if (h > 1e-10) {
// Compute the elastic collision
of two balls.
double v1,v2,r1,r2,s,t2,v;
p /= h;
q /= h; //
normalized impact direction
v1 = vx*p + vy*q;
v2 = b.vx*p + b.vy*q; // impact velocity
r1 = vx*q - vy*p;
r2 = b.vx*q - b.vy*p; // remainder velocity
if (v1<v2) return false;
s = m + b.m; //
total mass
if (s==0) return false;
t2 = (v1*m + v2*b.m)/s;
if(t==0) {
v = t2 + a.r*(v2 - v1)*b.m/s;
vx = v*p + r1*q;
vy = v*q - r1*p;
}