import java.awt.Graphics; import java.awt.Color; import java.awt.*; import java.awt.event.*; import java.applet.Applet; import java.util.*; /** * The Walker will simulate a random walk. Finish all the methods and * the constructor so that Walker can do a 1-d walk and collect data. * * @author Mr. Merlis * @version June 10, 2006 */ public class Walker { // instance variables - state of the object private Random itsRandom; private Random randy; private int itsPosition; private int itsMaxDistance; private int itsStartPlace; private int[] itsTravels; // or Walker2 private Graphics p; //the page // 0 1 2 3 private String[] dir = {"NORTH", "SOUTH", "EAST", "WEST"}; private boolean initialDisplay = false; //change to true after caterpillar drawn after first time private int screenWIDTH; private int screenLENGTH; private long startingTime; private DirectionEffect[][] dirEffect = new DirectionEffect[4][3]; //---------------------- // MR MERLIS USING private int[][] basinLocs = new int[9][2]; private int[][] bodyLocs = new int[5][2]; private int[][] headLocs = new int[9][2]; // for the tank specifically private int tankXLoc = 0; private int tankYLoc = 0; private double gunAngle = 0; private int headAngle = 0; private int speed = 0; private final int MAXSPEED = 45; // Ending X,Y for the barrel of the gun private int gunBarrelEndX = 0; private int gunBarrelEndY = 0; private int gunTip = 0; //---- necessary for placing the bullets private int scaleFactor = 0; // necessary for correct tank sizing private int wheelAngle = 0; // will change when tank moves private String direction = "WEST"; /** * Constructor for the graphical display of our walker. */ public Walker(Graphics page, int initialPosition, int theScreenW, int theScreenH, int scaleF, int initX, int initY) { p = page; itsRandom = new Random(); randy = new Random(); itsPosition = initialPosition; itsStartPlace = initialPosition; itsMaxDistance = 0; startingTime = System.currentTimeMillis(); initDirEffect(); screenWIDTH = theScreenW; screenLENGTH = theScreenH; scaleFactor = scaleF; tankXLoc = initX; tankYLoc = initY; }//==================================================================================== public int calcSeconds() { return (int)((System.currentTimeMillis()- startingTime)/1000); }//==================================================================================== public void initDirEffect() { dirEffect[0][0] = new DirectionEffect(0, 15); dirEffect[0][1] = new DirectionEffect(0, 30); dirEffect[0][2] = new DirectionEffect(0, 45); dirEffect[1][0] = new DirectionEffect(0, -15); dirEffect[1][1] = new DirectionEffect(0, -30); dirEffect[1][2] = new DirectionEffect(0, -45); dirEffect[2][0] = new DirectionEffect(-15, 0); dirEffect[2][1] = new DirectionEffect(-30, 0); dirEffect[2][2] = new DirectionEffect(-45, 0); dirEffect[3][0] = new DirectionEffect(15, 0); dirEffect[3][1] = new DirectionEffect(30, 0); dirEffect[3][2] = new DirectionEffect(45, 0); } /** * Draws the background of the walker. (All black) */ public void drawBackground() { p.setColor(Color.white); p.fillRect(0, 0, 1000, 1000); // clear the screen Color brown = new Color(139,69,19); Color lightBlue = new Color(175,238,238); p.setColor(lightBlue); p.fillRect(0, 0, screenWIDTH, tankYLoc); drawCloud(600, 100); p.setColor(brown); p.fillRect(0,tankYLoc,screenWIDTH, screenLENGTH); p.setColor(Color.white); }//========================================================== public void displayControls() { int startX = 10; int startY = 10; int width = 200; int height = 100; int xOffSet = 10; int yOffSet = 5; p.setColor(Color.black); p.fillRect(startX, startY, width, height); Color interior = new Color(49, 79, 79); // p.setColor(interior); p.setColor(Color.red); p.fillRect(startX + xOffSet, startY + yOffSet, width-xOffSet-10, height-yOffSet-5); p.setColor(Color.white); Font f = new Font("TimesRoman",Font.BOLD,12); p.setFont(f); // g is Graphics object p.setColor(Color.black); p.drawString("INFORMATION PANEL", startX + xOffSet + 20, startY + yOffSet + 12); f = new Font("TimesRoman",Font.PLAIN,12); p.setColor(Color.yellow); drawSpeedPanel(startX+xOffSet + 8, startY + yOffSet + 42, 60); drawGunAnglePanel(startX+xOffSet + 76, startY + yOffSet + 22, 60); p.setColor(Color.yellow); }//======================== public void drawSpeedPanel(int x, int y, int diameter) { int radius = (int)(diameter/2.0); p.setColor(Color.white); //p.fillOval(x, y, 60, 60); p.fillArc(x, y, diameter, diameter, 0, 180); p.setColor(Color.black); p.drawString("Speed", x + 2, (int)(y + diameter/1.5)); int startX = x + radius; int startY = y + radius; // regarding the line below... note that by dividing by MAXSPEED, we set the maxspeed to be 180 degrees past 0 on the panel p.drawLine(startX, startY, (int)(startX - (Math.cos((speed)*Math.PI/MAXSPEED)*radius)), (startY - (int)(Math.sin((speed)*Math.PI/MAXSPEED)*radius))); // p.drawString("Speed " + speed+ " degrees ", 20, 330); }//============================================== public void drawGunAnglePanel(int x, int y, int diameter) { int radius = (int)(diameter/2.0); p.setColor(Color.white); //p.fillOval(x, y, 60, 60); p.fillArc(x, y, diameter, diameter, 90, 180); p.setColor(Color.black); p.drawString("Gun Angle", x + 2, (int)(y + diameter/1.5)); // p.setColor(panelBG); int startX = x + radius; int startY = y + radius; p.drawLine(startX, startY, (int)(startX - (Math.cos((gunAngle)*Math.PI/180)*radius)), (startY - (int)(Math.sin((gunAngle)*Math.PI/180)*radius))); // p.drawString("Gun Angle: " + gunAngle + " degrees ", 20, 230); p.setColor(Color.yellow); }//============================================== /**draws a cloud for the applet*/ public void drawCloud(int x, int y) { // default to use x = 400, y = 50 // you may want to play with the width and height for different effects // changing X and Y will move the starting location of the cloud int width = 40; int height = 40; p.setColor(Color.blue); p.fillOval(x, y, width, height); p.fillOval(x-20, y+10, width, height); p.fillOval(x-10, y-10, width, height); p.fillOval(x+10, y+5, width, height); p.fillOval(x+5, y+20, width, height); p.fillOval(x+20, y-15, width, height); p.fillOval(x+25, y, width, height); p.fillOval(x+5, y+20, width, height); p.fillOval(x+20, y-15, width, height); p.fillOval(x+25, y, width, height); p.fillOval(x+30, y+10, width, height); p.fillOval(x+40, y, width, height); p.fillOval(x+30, y-30, width, height); p.fillOval(x+50, y+20, width, height); p.fillOval(x+60, y-15, width, height); p.fillOval(x+70, y, width, height); p.fillOval(x+50, y-20, width, height); p.fillOval(x+60, y, width, height); p.fillOval(x+70, y+30, width, height); p.fillOval(x+80, y-30, width, height); } /** * Draws the walker. */ public boolean draw() { // tankXLoc-=speed; int x = tankXLoc; p.drawString("xLoc: " + x , 30, 500); int y = tankYLoc; drawWheelBasin(x, y, scaleFactor); for(int i = 0; i < 4; i++) { p.setColor(Color.white); drawWheel(x + (5 * i * scaleFactor), y - (4 * scaleFactor), scaleFactor); // "4" is the model size drawSpokes(x + (5 * i * scaleFactor), y - (4 * scaleFactor), scaleFactor); // "4" is the model size } drawBody(x + (-6 * scaleFactor), y + (-4 * scaleFactor), scaleFactor); drawHead(x + (6 * scaleFactor), y + (-10 * scaleFactor), scaleFactor); drawGunBarrel(x + (6 * scaleFactor), y + (int)(-11.5 * scaleFactor), scaleFactor); displayControls(); // drawGunBarrel(x + (-11 * scaleFactor), y + (int)(-11.5 * scaleFactor), scaleFactor); return true; }//==================================================================== public void drawGunShot() { int shotDiameter = 1 * scaleFactor; // note that the model has a diameter of 1 int shotStartingLocX = gunBarrelEndX; int shotStartingLocY = gunBarrelEndY; drawBullet(shotStartingLocX, shotStartingLocY); pause(1); }//======================================================================= public void drawBullet(int startX, int startY) { // p.fillRoundRect(x, y, barrelLength * scaleFactor, scaleFactor, 5, 7); int endX =0; int endY =0; int bulletSize = scaleFactor; // model size is 1 p.drawString("shooting", 100, 200); int barrelLength = 17; int halfBase = 7; int pivotX = startX + (halfBase * scaleFactor); startX = pivotX - (int)(Math.cos(headAngle*Math.PI/180)*halfBase * scaleFactor); // int endX = (int)(startX - (Math.cos((gunAngle)*Math.PI/180)*barrelLength*scaleFactor)); // int distanceBetween = scaleFactor*(halfBase + barrelLength); // pivotX - endX; endX = pivotX - (int)(Math.cos(headAngle*Math.PI/180)*distanceBetween); //calc correct X value gunTip = endX; /* int pivotX = x + (halfBase * scaleFactor); startX = pivotX - (int)(Math.cos(headAngle*Math.PI/180)*halfBase * scaleFactor); int endX = (int)(startX - (Math.cos((gunAngle)*Math.PI/180)*barrelLength*scaleFactor)); */ int shootingSpeed = 0; // NOT WORKING YET -- but setup for when i get around to it for(int k = 0; k < startX; k++) { // having k * speeds it up as it shoots through the air endX = startX - shootingSpeed - (int)(scaleFactor * Math.cos(gunAngle*Math.PI/180)); endY = startY + (k/8) - shootingSpeed - (int)(scaleFactor * Math.sin(gunAngle*Math.PI/180)); for(int w = 0; w < scaleFactor; w++) { p.setColor(Color.red); // p.drawLine(startX, startY+w,endX+15 ,endY + w); p.drawLine(startX, startY+w,endX ,endY + w); } pause(5); for(int w = 0; w < scaleFactor; w++) { p.setColor(Color.white); p.drawLine(startX, startY + w,endX ,endY + w); } startX = endX; startY = endY; } }//============================ public void drawGunBarrel(int x, int y, int scaleFactor) { int startX = x; int startY = y; int barrelLength = 17; int halfBase = 7; int pivotX = x + (halfBase * scaleFactor); startX = pivotX - (int)(Math.cos(headAngle*Math.PI/180)*halfBase * scaleFactor); int endX = (int)(startX - (Math.cos((gunAngle)*Math.PI/180)*barrelLength*scaleFactor)); gunTip = endX; // int distanceBetween = scaleFactor*(halfBase + barrelLength); // pivotX - endX; endX = pivotX - (int)(Math.cos(headAngle*Math.PI/180)*distanceBetween); //calc correct X value Font f = new Font("Arial",Font.PLAIN,12); p.setFont(f); // g is Graphics object p.setColor(Color.black); int xShift = 250; p.drawString("startX: " + startX, xShift, 100); p.drawString("speed: " + speed, xShift, 117); p.drawString("pivotX: " + pivotX, xShift, 133); p.drawString("Distance Btwn: " + distanceBetween, xShift, 149); p.drawString("BarrelEndX: " + endX, xShift, 166); p.drawString("GunAngle: " + gunAngle, xShift, 183); p.drawString("Angle of Head: " + headAngle, xShift, 200); gunBarrelEndX = endX; gunBarrelEndY = (startY - (int)(Math.sin((gunAngle)*Math.PI/180)*barrelLength*scaleFactor)); // p.drawString("cosine value: " + Math.cos(gunAngle), 60, 70); // p.fillRoundRect(x, y, barrelLength * scaleFactor, scaleFactor, 5, 7); for(int k = 0; k < scaleFactor; k++) p.drawLine(startX, startY + k, endX, (startY + k - (int)(Math.sin((gunAngle)*Math.PI/180)*barrelLength*scaleFactor))); // p.drawLine(x, y + k, gunBarrelEndX, gunBarrelEndY + k); // line 1; }//==================================================================== public void drawWheel(int x, int y, int scaleFactor) { int diameter = scaleFactor * 4; // 4 is the pixel size based upon the scale Merlis made p.fillOval(x, y, diameter, diameter); }//==================================================================== public void drawSpokes(int x, int y, int scaleFactor) { int modelRadius = 2; // 2 - based upon Merlis Merlis int spokeSize = scaleFactor * modelRadius; int numSpokes = 6; int interval = 360/numSpokes; p.setColor(Color.black); for(int h = 0; h < 1 || h < Math.abs(speed); h++) { for(int i = 0; i < 360; i+=interval) { p.drawLine(x + spokeSize, y+spokeSize, (int)(x + spokeSize + (Math.cos((i+wheelAngle)*Math.PI/180)*spokeSize)), (int)(y + spokeSize + (Math.sin((i+wheelAngle)*Math.PI/180)*spokeSize))); } // p.setColor(Color.white); // p.drawLine(x + spokeSize, y+spokeSize, (int)(x + spokeSize + (Math.cos((i+wheelAngle)*Math.PI/180)*spokeSize)), (int)(y + spokeSize + (Math.sin((i+wheelAngle)*Math.PI/180)*spokeSize))); // wheelAngle--; } } // draw the outline of the tank body public void drawHead(int x, int y, int scaleFactor) { populateHeadLocs(); // the model size has a base of 14 across, meaning halfway is 7 units // this will be used as the pivot point, or center of the overhead 'circle' for rotation int halfBase = 7; int pivotX = x + (halfBase * scaleFactor); int[][] coordinates = new int[headLocs.length][2]; int distanceBetween; coordinates[0][0] = pivotX - (int)(Math.cos(headAngle*Math.PI/180)*halfBase * scaleFactor); coordinates[0][1] = y; int newX = x; // determines where the X location SHOULD be (if 0 rotation) for(int k = 1; k < coordinates.length; k++) { newX += (headLocs[k][0] * scaleFactor); distanceBetween = pivotX - newX; coordinates[k][0] = pivotX - (int)(Math.cos(headAngle*Math.PI/180)*distanceBetween); //calc correct X value coordinates[k][1] = coordinates[k-1][1] + (scaleFactor * headLocs[k][1]); } createFilledPolygon(coordinates, Color.magenta); p.setColor(Color.black); /* for(int k = 0; k < coordinates.length -2 ; k++) p.drawLine(coordinates[k][0] , coordinates[k][1], coordinates[k+1][0], coordinates[k+1][1]); // line 1; */ p.drawOval(coordinates[coordinates.length-2][0]-2, coordinates[coordinates.length-2][1], 1*scaleFactor/2, 2*scaleFactor); }//==================================================================== /** * This is a helper method that will create filled polygons. * It takes a 2d array of coordinates and the color for the polygon. * It then creates separate arrays for both X and Y, then fills the shape. */ public void createFilledPolygon(int[][] coordinates, Color col) { int[] xCors = new int[coordinates.length]; int[] yCors = new int[coordinates.length]; for(int w = 0; w < xCors.length; w++) { xCors[w] = coordinates[w][0]; yCors[w] = coordinates[w][1]; } p.setColor(col); p.fillPolygon(xCors, yCors, xCors.length); p.setColor(Color.black); }//==================== //array for HEAD of tank coordinates public void populateHeadLocs() { headLocs[0][0] = 0; headLocs[0][0] = 0; headLocs[1][0] = 3; headLocs[1][1] = 2; headLocs[2][0] = 8; headLocs[2][1] = 0; headLocs[3][0] = 3; headLocs[3][1] = -2; headLocs[4][0] = 0; headLocs[4][1] = -2; headLocs[5][0] = -1; headLocs[5][1] = -1; headLocs[6][0] = -12; headLocs[6][1] = 0; headLocs[7][0] = -1; headLocs[7][1] = 1; headLocs[8][0] = 0; headLocs[8][1] = 2; }//================================================================ // draw the outline of the tank body public void drawBody(int x, int y, int scaleFactor) { populateBodyLocs(); int[][] coordinates = new int[bodyLocs.length][2]; coordinates[0][0] = x; coordinates[0][1] = y; for(int k = 1; k < coordinates.length; k++) { coordinates[k][0] = coordinates[k-1][0] + (scaleFactor * bodyLocs[k][0]); coordinates[k][1] = coordinates[k-1][1] + (scaleFactor * bodyLocs[k][1]); } createFilledPolygon(coordinates, Color.green); p.setColor(Color.black); /* for(int k = 0; k < coordinates.length -1 ; k++) p.drawLine(coordinates[k][0], coordinates[k][1], coordinates[k+1][0], coordinates[k+1][1]); // line 1; */ }//==================================================================== // draw the outline of the wheel basin public void drawWheelBasin(int x, int y, int scaleFactor) { populateBasinLocs(); int[][] coordinates = new int[9][2]; coordinates[0][0] = x; coordinates[0][1] = y; for(int k = 1; k < coordinates.length; k++) { coordinates[k][0] = coordinates[k-1][0] + (scaleFactor * basinLocs[k][0]); coordinates[k][1] = coordinates[k-1][1] + (scaleFactor * basinLocs[k][1]); } createFilledPolygon(coordinates, Color.black); p.setColor(Color.black); /* for(int k = 0; k < coordinates.length -1 ; k++) p.drawLine(coordinates[k][0], coordinates[k][1], coordinates[k+1][0], coordinates[k+1][1]); // line 1; */ }//==================================================================== //populates the array of locations for the coordinates of vertices in the body of the tank public void populateBodyLocs() { bodyLocs[0][0] = 0; bodyLocs[0][1] = 0; bodyLocs[1][0] = 31; bodyLocs[1][1] = 0; bodyLocs[2][0] = -2; bodyLocs[2][1] = -4; bodyLocs[3][0] = -20; bodyLocs[3][1] = 0; bodyLocs[4][0] = -9; bodyLocs[4][1] = 4; }//================================================================ //populates the array of locations for the coordinates of vertices in wheel basin public void populateBasinLocs() { basinLocs[0][0] = 0; basinLocs[0][1] = 0; basinLocs[1][0] = 20; basinLocs[1][1] = 0; basinLocs[2][0] = 3; basinLocs[2][1] = -2; basinLocs[3][0] = 0; basinLocs[3][1] = -1; basinLocs[4][0] = -1; basinLocs[4][1] = -1; basinLocs[5][0] = -23; basinLocs[5][1] = 0; basinLocs[6][0] = -3; basinLocs[6][1] = 1; basinLocs[7][0] = 0; basinLocs[7][1] = 1; basinLocs[8][0] = 4; basinLocs[8][1] = 2; }//================================================================ public String direction() { return direction; }//==== public void changeDirection(String newDirection) { direction = newDirection; }//-=========== public void changeHeadAngle(int headAngCh) { headAngle += headAngCh; }//======================================== public void changeGunAngle(double degreeChange) { double newAngle = gunAngle + degreeChange; if( Math.abs(newAngle) > 70) // NOT LEGAL p.drawString("too far!", 90, 100); else gunAngle += degreeChange; }//================== public void changeXLoc(int locChange) { //-------------account for the speed ------------------------- if(locChange == -1) // pressed the LEFT key { p.drawString("pressed -1", 70, 400); if(direction.equals("WEST")) // facing WEST, this is an inc. in speed { if(speed < MAXSPEED) // possible to go faster { speed++; } } else speed--; } if(locChange == 1) // pressed the RIGHT key { if(direction.equals("WEST")) // facing WEST, this is an inc. in speed speed--; else { if(speed < MAXSPEED) // possible to go faster { speed++; } } }// end of changing the speed //-----------end of speed --------------- tankXLoc += locChange; wheelAngle += locChange; }//======================================= /** * Used between drawing the different Walkers to provide * animation */ private static void pause (int wait) { long timeToQuit = System.currentTimeMillis() + wait; while (System.currentTimeMillis() < timeToQuit) { } // take no action } //====================== }