Hunt The Wumpus
<< Worm Game | FinalProjectsTrailIndex | Gridworld Dice Games >>
The code here has a fairly complete user interface that has a 3D Dodectrahedron (You need red-blue 3d glasses). To fuly implement the game, you need to make a Room class that can be filled with bats, pits and a smelly wumpus. Look for "//todo" in the code for details. The Room needs to be able to report if it has
- gold
- a bottomless pit
- bats that transport the player to a random room
- a deadly wumpus that will eat the player
You would also need to a write a method in the WumpusApplet that will randomly place these hazards in the the 20 Rooms.
The UI demonstrates rotation around axes controlled by a click and drag, and double buffering that removes a flicker that occurs in Windows.
For a complete description of this classic game see the Wikipeadia article
To see a working demo of the user interface, click here
WumpusApplet.java
import java.applet.Applet; import java.awt.Button; import java.awt.Color; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.Image; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.util.ArrayList; public class WumpusApplet extends Applet implements ActionListener, MouseMotionListener, MouseListener { private Button forward,turnL, turnR, grab, shoot,help, look; private String direction, message, message2, contents, turn; private int loc, nextLoc, gold; private Dodectrahedron d; private ArrayList<Button> btns; private Rectangle view1, view2; //double buffering to remove Windows flicker: private Image screen2; private Graphics g2; // mouse drag to rotate private int startX = -1, startY = -1; private int curX = -1, curY = -1; private boolean inDrag=false; private int yAng, xAng, dX, dY, deaths, kills; private ArrayList<Integer> shot,visited; private static final boolean ORTHO = true; private static final double LEFT = 0;// Degree separation for left view private static final double RIGHT = 4.0;// Degree separation for right view private static final double LOW = .14; // HEIGHT of spikes and Dot private static final Color cyan = new Color(0, 255,255,50); private static final Color red = new Color (255, 0,0,50); //todo: private Room[] rooms; public void init(){ setUpGame(); int deaths=0; int kills=0; gold=0; this.setLayout(new FlowLayout()); setUpButtons(); view1= new Rectangle(425, 300, 250,250 ); view2= new Rectangle(75, 300, 250,250 ); yAng=0;//rot around yAxis xAng=0;//rot around xAxis dX=dY=0;//slope of the mouse dragging this.addMouseListener(this); this.addMouseMotionListener(this); } private void setUpGame() { direction="straight ahead"; contents ="You seem to be in an empty room"; message="Hunt the Wumpus!"; message2=""; turn="left"; loc=0; nextLoc=0; d=new Dodectrahedron(); shot=new ArrayList<Integer>(); visited=new ArrayList<Integer>(); //todo: Initialize 20 rooms //todo: Randomly fill the rooms with bats, pits and a wupus. } private void setUpButtons() { forward = new Button("Go Forward"); turnL = new Button("Turn Left"); turnR = new Button("Turn Right"); grab = new Button("Grab"); shoot = new Button("Shoot Arrow"); help = new Button("Help"); look = new Button("Look"); btns = new ArrayList<Button>(); btns.add(forward); btns.add(turnL); btns.add(turnR); btns.add(grab); btns.add(shoot); btns.add(help); btns.add(look); for(Button b:btns){ b.addActionListener(this); add(b); } } public void paint(Graphics g){ int width=getWidth(); int height=getHeight(); screen2 = createImage(width,height); g2 = screen2.getGraphics(); g2.setColor(Color.WHITE); g2.fillRect(0, 0, width, height); g2.setColor(Color.BLACK); g2.drawString(message, 20, 120); g2.drawString(message2, 20, 140); g2.drawString("You are facing "+direction, 20, 180); g2.drawString(contents, 20, 200); g2.drawString("You have "+gold+" gold", 20, 220); g2.drawString("You have been killed "+deaths+" times", 20, 240); g2.drawString("You have killed a wumpus "+gold+" times", 20, 260); g2.drawString("y axis angle ="+(d.getyAxisAngle()), 350, 260); g2.drawString("x axis angle ="+d.getxAxisAngle(), 350, 280); g2.drawRect(view1.x, view1.y, view1.width, view1.height); g2.drawRect(view2.x, view2.y, view2.width, view2.height); drawStereo(g2, view1); drawOrtho(g2, view2); //draw g2 to screen g.drawImage(screen2, 0,0,this); } private void drawStereo(Graphics g, Rectangle view) { //left cyan g.setColor(cyan); for (int i=0; i<12; i++){ g.drawPolygon(d.getFace(i).getOrthoPolygon(view, yAng+dY, xAng+dX)); } d.drawEdges(g, view, ORTHO); d.spikeVertex(g, view, 0, LOW, ORTHO, LEFT); d.drawDot(g, view, loc, LOW, ORTHO, LEFT); d.point2Vertex(g, view, loc, nextLoc, ORTHO, LEFT); //right red g.setColor(red); for (int i=0; i<12; i++){ g.drawPolygon(d.getFace(i).getOrthoPolygon(view, yAng+dY+RIGHT, xAng+dX)); } //d.drawEdgesOrtho(g, screenR); d.spikeVertex(g, view, loc, 1.0, ORTHO, RIGHT); d.drawDot(g, view, loc, LOW, ORTHO, RIGHT); d.point2Vertex(g, view, loc,nextLoc, ORTHO, RIGHT); } private void drawOrtho(Graphics g, Rectangle view) { for (int i=0; i<12; i++){ g.setColor(d.getFace(i).getColor()); g.fillPolygon(d.getFace(i).getOrthoPolygon(view, yAng+dY, xAng+dX)); } g.setColor(Color.BLACK); d.drawEdges(g, view, ORTHO); d.spikeVertex(g, view, loc, LOW, ORTHO, LEFT); d.spikeVertex(g, view, loc,LOW, ORTHO, LEFT); d.drawDot(g, view, loc, LOW, ORTHO, LEFT); d.point2Vertex(g, view, loc, nextLoc, ORTHO, LEFT); //indicate the rooms you shot into with red g.setColor(Color.MAGENTA); for(Integer i:shot){ d.spikeVertex(g, view, i, LOW, ORTHO, LEFT); } //indicate the rooms you visited g.setColor(Color.GREEN); for(Integer i:visited){ d.spikeVertex(g, view, i, LOW, ORTHO, LEFT); } } public void update(Graphics g){ paint(g); } @Override public void mouseDragged(MouseEvent e) { curX=e.getX(); curY=e.getY(); if (inDrag){ dY = (startX-curX)/2;//y axis delta dX = (startY-curY)/2;//x axis delta d.setyAxisAngle((yAng+dY)%360); d.setxAxisAngle((xAng+dX)%360); repaint(); } } @Override public void mouseMoved(MouseEvent e) {} @Override public void mouseClicked(MouseEvent e) { } @Override public void mousePressed(MouseEvent e) { inDrag=true; startX = curX = e.getX(); startY = curY = e.getY(); } @Override public void mouseReleased(MouseEvent e) { inDrag=false; xAng+=dX; yAng+=dY; dX=dY=0; repaint(); } @Override public void mouseEntered(MouseEvent e) {} @Override public void mouseExited(MouseEvent e) {} @Override public void actionPerformed(ActionEvent e) { Object src = e.getSource(); if(src==grab){ //todo: use room method getGold message="Nothing to Grab here."; message2="You have "+gold+" gold."; }else if(src==turnL){ message="You turn left."; turn="left"; nextLoc=d.getLeft(loc, nextLoc); direction=" a passage to room "+nextLoc; //todo: use Room method hasWupus(nextLoc)-- message2="You smell a wumpus" //todo: use Room method hasPit(nextLoc)--message2="You fell a breeze" //todo: use Room method hasBats(nextLoc)==message2="You hear flapping wings" message2=""; }else if(src==turnR){ message="You turn right."; turn="right"; nextLoc=d.getRight(loc, nextLoc); direction=" a passage to room "+nextLoc; //todo: use Room method hasWupus(nextLoc)-- message2="You smell a wumpus" //todo: use Room method hasPit(nextLoc)--message2="You fell a breeze" //todo: use Room method hasBats(nextLoc)==message2="You hear flapping wings" message2=""; }else if(src==look){ //todo:check for contents in nextLoc // you might smell a wumpus, feel a draft, or hear bats //todo: use Room method hasWupus(nextLoc)-- message2="You smell a wumpus" //todo: use Room method hasPit(nextLoc)--message2="You fell a breeze" //todo: use Room method hasBats(nextLoc)==message2="You hear flapping wings" message2=""; message="You look around. You see a sign with the number "+loc+" on the wall"; message2=""; }else if(src==help){ message= "You want to find gold and kill the wupus with your crooked arrows."; message2 ="Avoid drafty bottomless pits, bats that relocate you, and going into a wumpus infested room."; }else if (src==shoot){ message="You shoot in the direction of room "+nextLoc; int[] rooms = d.getFaceNodes(loc, nextLoc, turn); if (rooms!=null){ for(int i:rooms) shot.add(i); //todo: check to see if you killed the wumpus // needs Room method hasWumpus() message2="You may have shot something"; }else{ message2="Without aim you wasted an arrow"; } }else if (src==forward){ if (loc!=nextLoc){ message="You go down the passage to room "+nextLoc; //todo: use Room method hasWupus(nextLoc)-- message2="You are eaten by wumpus" //todo: use Room method hasPit(nextLoc)--message2="You fell into a bottomless pit" //todo: use Room method hasBats(nextLoc)==message2="Bats fly you to a random room" message2=""; visited.add(loc); }else{ message="You walk into a wall and hit your head"; } //change current room loc=nextLoc; message2=""; direction="straight ahead"; } //todo: update graphics repaint(); } }
Vertex.java
import java.awt.Point; import java.awt.Rectangle; public class Vertex implements Comparable { private double x,y,z; public static final double CamX=0;//3d viewpoint coords public static final double CamY=0;//3d viewpoint coords public static final double CamZ=-3;//3d viewpoint coords //public int xfac=90, zfac=90; public static final double RADIANS=Math.PI/180.0;//degree to radian conversion public Vertex(double x, double y, double z){ this.x=x; this.y=y; this.z=z; } public boolean equals(Vertex o) { return x==o.getX() && y==o.getY() && z==o.getZ(); } public double getZ() { return z; } public double getY() { return y; } public double getX() { return x; } @Override public int compareTo(Object o) { return (int)(Math.round(distance((Vertex)o))); } public double distance(Vertex o) { return Math.sqrt( Math.pow(x-o.getX(), 2)+ Math.pow(y-o.getY(), 2)+ Math.pow(z-o.getZ(), 2) ); } public int screenX(Rectangle r){ double x0 = r.width/2*(x - CamX) /(z-CamZ); return r.x+r.width/2+(int)Math.round(x0); } public int screenY(Rectangle r){ double y0 = r.height/2*(y - CamY) /(z-CamZ); return r.y+r.height/2-(int)Math.round(y0); } public Point screenXY(Rectangle r, double yAxis, double xAxis){ double a = 2*yAxis*RADIANS; double b = 2*xAxis*RADIANS; //rotation around y axis double z0 = z*Math.cos(a)-x*Math.sin(a); double x0 = z*Math.sin(a)+x*Math.cos(a); //rotation around x axis double y0 = y*Math.cos(b)-z0*Math.sin(b); double z1 = y*Math.sin(b)+z0*Math.cos(b); //projection double px = r.width/2*(x0 - CamX) /(z1-CamZ); double py = r.height/2*(y0 - CamY) /(z1-CamZ); int sy = r.y+r.height/2-(int)Math.round(py); int sx = r.x+r.width/2+(int)Math.round(px); return new Point(sx,sy); } public Point orthoXY(Rectangle r, double yAxis, double xAxis){ double a = 2*yAxis*RADIANS; double b = 2*xAxis*RADIANS; //rotation around y axis double z0 = z*Math.cos(a)-x*Math.sin(a); double x0 = z*Math.sin(a)+x*Math.cos(a); //rotation around x axis double y0 = y*Math.cos(b)-z0*Math.sin(b); double z1 = y*Math.sin(b)+z0*Math.cos(b); //orthogonal projection of x0,y0,z1 double theta= Math.PI/8; double phi= -1*Math.PI/15; double s=r.width/4; double xf=s*.89; double zf=s*.68; double px = xf*Math.cos(phi)*(x0 - CamX) + zf*Math.cos(theta)*(z1-0); double py = s*(y0 - CamY) + zf*Math.sin(theta)*(z1-0)+xf*Math.sin(phi)*(x0 - CamX); int sy = r.y+r.height/2-(int)Math.round(py); int sx = r.x+r.width/2+(int)Math.round(px); return new Point(sx,sy); } /** * change the point by rotation around the y axis * @param degrees */ public void rotateAxisY(double degrees){ double a = 2*degrees*RADIANS; double z0 = z*Math.cos(a)-x*Math.sin(a); double x0 = z*Math.sin(a)+x*Math.cos(a); z=z0; x=x0; } public void rotateAxisX(double degrees){ double a = 2*degrees*RADIANS; double y0 = y*Math.cos(a)-z*Math.sin(a); double z0 = y*Math.sin(a)+z*Math.cos(a); y=y0; z=z0; } public static Vertex midpoint(Vertex v1, Vertex v2){ double xm = 0.5*(v1.getX()+v2.getX()); double ym = 0.5*(v1.getY()+v2.getY()); double zm = 0.5*(v1.getZ()+v2.getZ()); return new Vertex(xm,ym,zm); } public static Vertex spike(Vertex v1, Vertex v2){ double xm = 0.5*(v1.getX()+v2.getX()); double ym = 0.5*(v1.getY()+v2.getY()); double zm = 0.5*(v1.getZ()+v2.getZ()); return new Vertex(v2.getX()+xm/2,v2.getY()+ym/2,v2.getZ()+zm/2); } /** * * @param v1 * @param percent of vertex to origin * @return a vertex a percentage away from origin */ public static Vertex spike(Vertex v1, double percent){ double xm = percent*(v1.getX()); double ym = percent*(v1.getY()); double zm = percent*(v1.getZ()); return new Vertex(v1.getX()+xm,v1.getY()+ym,v1.getZ()+zm); } public String toString(){ return String.format("(%.3f, %.3f, %.3f)", x,y,z); } }
Face.java
import java.awt.Color; import java.awt.Point; import java.awt.Polygon; import java.awt.Rectangle; public class Face implements Comparable<Face> { private Vertex[] v; private Color color; public Face(Vertex v0, Vertex v1, Vertex v2, Vertex v3, Vertex v4){ setColor(Color.WHITE); v = new Vertex[5]; v[0]=v0; v[1]=v1; v[2]=v2; v[3]=v3; v[4]=v4; } public Polygon polygon(Rectangle screen, double scale){ Polygon p = new Polygon(); for (int i=0; i<5; i++) p.addPoint(v[i].screenX(screen), v[i].screenY(screen)); return p; } public String toString(){ String s="["; for (Vertex n:v) s+=n.toString()+" "; return s+"]"; } @Override public int compareTo(Face o) { return (int)(100.0*this.distanceToViewpoint()-100*o.distanceToViewpoint()); } public double distanceToViewpoint(){ return center().distance(new Vertex(Vertex.CamX, Vertex.CamY, Vertex.CamZ)); } public Vertex center(){ double x,y,z; x=y=z=0; for(Vertex n:v){ x+=n.getX(); y+=n.getY(); z+=n.getZ(); } return new Vertex(x/5.0, y/5.0, z/5.0); } public Polygon getPolygon(Rectangle screen, double yAxis, double xAxis){ Polygon p = new Polygon(); for (int i=0; i<5; i++){ Point pt = v[i].screenXY(screen, yAxis, xAxis); p.addPoint(pt.x, pt.y); } return p; } public Polygon getOrthoPolygon(Rectangle screen, double yAxis, double xAxis){ Polygon p = new Polygon(); for (int i=0; i<5; i++){ Point pt = v[i].orthoXY(screen, yAxis, xAxis); p.addPoint(pt.x, pt.y); } return p; } public Color getColor() { return color; } public Color getCyan() { return new Color(0, 0, color.getBlue(), color.getTransparency()); } public Color getRed() { return new Color(color.getRed(),0, 0, color.getTransparency()); } public void setColor(Color color) { this.color = new Color(color.getRed(), color.getGreen(), color.getBlue(), 128); } }
Dodectrahedron.java
import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.awt.Polygon; import java.awt.Rectangle; import java.awt.event.MouseEvent; public class Dodectrahedron { private Vertex[] v; private Face[] f; private int [][] adjacentNodes; private double yAxisAngle, xAxisAngle; public static final double PI_5 = 2.0*Math.PI/5.0; public static final double PHI=1.618033988749894848204586834365638; public Dodectrahedron(){ v = new Vertex[20]; v[0]=new Vertex(1,1,1); v[1]=new Vertex(1,1,-1); v[2]=new Vertex(1,-1,1); v[3]=new Vertex(1,-1,-1); v[4]=new Vertex(-1,1,1); v[5]=new Vertex(-1,1,-1); v[6]=new Vertex(-1,-1,1); v[7]=new Vertex(-1,-1,-1); v[8]=new Vertex(0,1.0/PHI,PHI);//green v[9]=new Vertex(0,1.0/PHI,-PHI); v[10]=new Vertex(0,-1.0/PHI,PHI); v[11]=new Vertex(0,-1.0/PHI,-PHI); v[12]=new Vertex(PHI,0,1/PHI);//red v[13]=new Vertex(PHI,0,-1/PHI); v[14]=new Vertex(-PHI,0,1/PHI); v[15]=new Vertex(-PHI,0,-1/PHI); v[16]=new Vertex(1.0/PHI,PHI,0);//blu v[17]=new Vertex(1.0/PHI,-PHI,0); v[18]=new Vertex(-1.0/PHI,PHI,0); v[19]=new Vertex(-1.0/PHI,-PHI,0); f = new Face[12]; f[0] = new Face(v[18], v[16], v[1], v[9],v[5]);//ok f[1] = new Face(v[18], v[16], v[0], v[8],v[4]);//ok f[2] = new Face(v[16], v[1], v[13], v[12],v[0]); f[3] = new Face(v[1], v[9], v[11], v[3],v[13]); f[4] = new Face(v[9], v[5], v[15], v[7],v[11]); f[5] = new Face(v[5], v[18], v[4], v[14],v[15]); f[6] = new Face(v[10], v[2], v[17], v[19],v[6]); f[7] = new Face(v[10], v[2], v[12], v[0],v[8]); f[8] = new Face(v[2], v[17], v[3], v[13],v[12]); f[9] = new Face(v[17], v[19], v[7], v[11],v[3]); f[10] = new Face(v[19], v[6], v[14], v[15],v[7]); f[11] = new Face(v[6], v[10], v[8], v[4],v[14]); for (Face side:f) side.setColor(randomColor()); this.adjacentNodes = new int [20][3]; //clockwise initNode(0,8,12,16); initNode(1,16,13, 9); initNode(2,12,10, 17); initNode(3,13, 17, 11); initNode(4,18, 14, 8); initNode(5,18, 9,15); initNode(6,14,19, 10); initNode(7,15,11,19); initNode(8,4,10,0); initNode(9,5,1,11); initNode(10,8,6,2); initNode(11,3,7,9); initNode(12,0,2,13); initNode(13,1,12,3); initNode(14,4,15,6); initNode(15,5,7,14); initNode(16,0,1,18); initNode(17,3,2,19); initNode(18,16,5,4); initNode(19,7,17,6); } public void nodeTest(Graphics g, Rectangle screen, int n){ g.setColor(Color.BLACK); for(int i=0; i<3;i++) connect(g, n, adjacentNodes[n][i], screen, true); } private void initNode(int n, int v0, int v1,int v2){ adjacentNodes[n][0]=v0; adjacentNodes[n][1]=v1; adjacentNodes[n][2]=v2; } /** * from a node, facing a node get the left node * @return -1 if not possible to face from the node from that node error */ public int getLeft(int from, int facing){ int currentIndex=0; if(from==facing)// select first if same node facing=adjacentNodes[from][0]; while (currentIndex<3 && facing!=adjacentNodes[from][currentIndex]) currentIndex++; if (adjacentNodes[from][currentIndex]!=facing) return -1; int i=(currentIndex-1+3)%3; return adjacentNodes[from][i]; } /** * from a node, facing a node get the left node * @return -1 if not possible to face from the node from that node error */ public int getRight(int from, int facing){ int currentIndex=0; if(from==facing)// select first if same node facing=adjacentNodes[from][0]; while (currentIndex<3 && facing!=adjacentNodes[from][currentIndex]) currentIndex++; if (adjacentNodes[from][currentIndex]!=facing) return -1; int i=(currentIndex+1+3)%3; return adjacentNodes[from][i]; } /** * Returns the array of 5 nodes of the pentagan from a node facing a node. * @param from * @param facing * @param leftOrRight * @return null if not facing properly */ public int[] getFaceNodes(int from, int facing, String leftOrRight){ if (from==facing) return null; if (getRight(from,facing)==-1) return null; int[] p=new int[5]; p[0]=from; p[1]=facing; if (leftOrRight.equalsIgnoreCase("left")){ for (int i=2; i<5;i++) p[i]=getRight(p[i-1],p[i-2]); }else{ for (int i=2; i<5;i++) p[i]=getLeft(p[i-1],p[i-2]); } return p; } public Color randomColor(){ return new Color((int)(255*Math.random()), (int)(255*Math.random()), (int)(255*Math.random())); } public void rotateY(double yAxisDeg){ for (Vertex n:v) n.rotateAxisY(yAxisDeg); } public void rotateX( double xAxisDeg){ for (Vertex n:v) n.rotateAxisX(xAxisDeg); } public Face getFace(int i){ return f[i]; } public Face[] getFaces(){ return f; } public Vertex getVertex(int i){ return v[i]; } public double getyAxisAngle() { return yAxisAngle; } public void setyAxisAngle(double yAxisAngle) { this.yAxisAngle = yAxisAngle; } public double getxAxisAngle() { return xAxisAngle; } public void setxAxisAngle(double xAxisAngle) { this.xAxisAngle = xAxisAngle; } public void drawEdges(Graphics g, Rectangle screen, boolean ortho){ connect(g, 18, 16, screen, ortho); connect(g, 16, 1, screen, ortho); connect(g, 1, 9, screen, ortho); connect(g, 9, 5, screen, ortho); connect(g, 5, 18, screen, ortho); connect(g, 16, 0, screen, ortho); connect(g, 0, 8, screen, ortho); connect(g, 8, 4, screen, ortho); connect(g, 4, 18, screen, ortho); connect(g, 0, 12, screen, ortho); connect(g, 12, 13, screen, ortho); connect(g, 13, 1, screen, ortho); connect(g, 13, 3, screen, ortho); connect(g, 3, 11, screen, ortho); connect(g, 11, 9, screen, ortho); connect(g, 11, 7, screen, ortho); connect(g, 7, 15, screen, ortho); connect(g, 15, 5, screen, ortho); connect(g, 15, 14, screen, ortho); connect(g, 14, 4, screen, ortho); connect(g, 10, 8, screen, ortho); connect(g, 2, 12, screen, ortho); connect(g, 17, 3, screen, ortho); connect(g, 19, 7, screen, ortho); connect(g, 6, 14, screen, ortho); connect(g, 10, 2, screen, ortho); connect(g, 2, 17, screen, ortho); connect(g, 17, 19, screen, ortho); connect(g, 19, 6, screen, ortho); connect(g, 6, 10, screen, ortho); } public void drawCenter2Vertex(Graphics g, Rectangle area, int i,boolean ortho, double offset){ Vertex o=new Vertex(0,0,0); Point p1,p2; if(ortho){ p1=o.orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(i).orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); }else{ p1=o.screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(i).screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); } g.drawLine(p1.x, p1.y, p2.x, p2.y); } public void point2Vertex(Graphics g, Rectangle area, int from, int to, boolean ortho, double offset){ Vertex o=Vertex.spike(getVertex(from), .25); Point p1,p2, p3; if(ortho){ p1=Vertex.midpoint(getVertex(from), getVertex(to)).orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(from).orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); p3=o.orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); }else{ p1=Vertex.midpoint(getVertex(from), getVertex(to)).screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(from).screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); p3=o.screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); } Polygon flag = new Polygon(); flag.addPoint(p1.x, p1.y); flag.addPoint(p2.x, p2.y); flag.addPoint(p3.x, p3.y); g.fillPolygon(flag); } /** * * @param g * @param area * @param i the node * @param percent how long the spike * @param ortho whether or not ortho or perspectve projectoin * @param offset rotation offset for stereo use */ public void spikeVertex(Graphics g, Rectangle area, int i, double percent, boolean ortho, double offset){ Vertex o=Vertex.spike(getVertex(i), percent); Point p1,p2; if(ortho){ p1=o.orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(i).orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); }else{ p1=o.screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(i).screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); } g.drawLine(p1.x, p1.y, p2.x, p2.y); } public void connect(Graphics g,int i, int j, Rectangle screen, boolean ortho, double offset){ Point p1,p2; if (ortho){ p1=getVertex(i).orthoXY(screen, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(j).orthoXY(screen, getyAxisAngle()+offset, getxAxisAngle()); }else { p1=getVertex(i).screenXY(screen, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(j).screenXY(screen, getyAxisAngle()+offset, getxAxisAngle()); } g.drawLine(p1.x, p1.y, p2.x, p2.y ); } public void connect(Graphics g, int i, int j, Rectangle screen, boolean ortho){ connect(g,i,j,screen,ortho,0); } public void drawDot(Graphics g, Rectangle area, int i, double percent, boolean ortho, double offset){ Vertex o=Vertex.spike(getVertex(i), percent); Point p1,p2; if(ortho){ p1=o.orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(i).orthoXY(area, getyAxisAngle()+offset, getxAxisAngle()); }else{ p1=o.screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); p2=getVertex(i).screenXY(area, getyAxisAngle()+offset, getxAxisAngle()); } int size=(int)Math.round(Math.sqrt(Math.pow(p1.x-p2.x,2)+Math.pow(p1.y-p2.y,2))); size=Math.max(5, size); g.fillOval(p1.x-size, p1.y-size, 2*size, 2*size); } }