// Extension of the Graphics object that flips the Y-axis and translates // center-based shaped to Java's upper-left-based shapes. Although the // former transformation could be accomplished via more conventional // means, the latter can not. So we do both transformations at the same // time. // // This object is intended to be wrapped around whatever Graphics object // is passed to the paint() method. The actual operations (after // transformation of the parameters) are delegated to the wrapped-up // underlying Graphics object. // // SpaceGraphicsFlipCenter is an example of the Decorator pattern, delegating // transformed operations to its superclass. It implements the SpaceGraphics // interface. package SpaceWar; import java.awt.*; class SpaceGraphicsFlipCenter implements SpaceGraphics { // Instance variables protected Graphics wrappedGraphics; // Graphics to delegate to. protected int[] xPointsXformed; // Transformed polygon points. protected int[] yPointsXformed; // Transformed polygon points. protected int nPointsXformed = 0; SpacePoint currentPoint; // For intermediate results. ////////////////////////////////////////////////////////////////////// // // Constructors public SpaceGraphicsFlipCenter() { currentPoint = new SpacePoint(0, 0); } public SpaceGraphicsFlipCenter(Graphics g) { this(); wrappedGraphics = g; } ////////////////////////////////////////////////////////////////////// // // Internal maintenance methods. protected void allocPointsIfNeeded(int nPoints) { if (nPointsXformed < nPoints) { nPointsXformed = nPoints; xPointsXformed = new int[nPoints]; yPointsXformed = new int[nPoints]; } } ////////////////////////////////////////////////////////////////////// // // Get-set methods. public void setWrappedGraphics(Graphics g) { wrappedGraphics = g; } ////////////////////////////////////////////////////////////////////// // // Drawing methods. public void setColor(Color c) { wrappedGraphics.setColor(c); } public void fillOval(int x, int y, int width, int height) { wrappedGraphics.fillOval(x - width / 2, -y - height / 2, width, height); } public void fillOval(SpacePoint ref, double r, double theta, int width, int height) { currentPoint.addPolar(ref, r, theta); fillOval(currentPoint.x, currentPoint.y, width, height); } public void drawLine(int x1, int y1, int x2, int y2) { wrappedGraphics.drawLine(x1, -y1, x2, -y2); wrappedGraphics.drawLine(x1 - 1, -y1, x2 - 1, -y2); } public void drawLine(SpacePoint ref, double r1, double theta1, double r2, double theta2) { int x1, y1, x2, y2; currentPoint.addPolar(ref, r1, theta1); x1 = currentPoint.x; y1 = currentPoint.y; currentPoint.addPolar(ref, r2, theta2); x2 = currentPoint.x; y2 = currentPoint.y; drawLine(x1, y1, x2, y2); } public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) { allocPointsIfNeeded(nPoints); for (int i = 0; i < nPoints; i++) { yPointsXformed[i] = - yPoints[i]; } wrappedGraphics.drawPolygon(xPoints, yPointsXformed, nPoints); } public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) { allocPointsIfNeeded(nPoints); for (int i = 0; i < nPoints; i++) { yPointsXformed[i] = - yPoints[i]; } wrappedGraphics.fillPolygon(xPoints, yPointsXformed, nPoints); } ////////////////////////////////////////////////////////////////////// // // Specialize SpaceWar drawing methods. // Draw a speed-blur polygon between four points specified as // polar offsets from a pair of reference points. public void polarBlur(SpacePoint ref1, double r1a, double r1b, double theta1, SpacePoint ref2, double r2a, double r2b, double theta2) { allocPointsIfNeeded(4); currentPoint.addPolar(ref1, r1a, theta1); xPointsXformed[0] = currentPoint.x; yPointsXformed[0] = currentPoint.y; currentPoint.addPolar(ref1, r1b, theta1); xPointsXformed[1] = currentPoint.x; yPointsXformed[1] = currentPoint.y; currentPoint.addPolar(ref2, r2b, theta1); xPointsXformed[2] = currentPoint.x; yPointsXformed[2] = currentPoint.y; currentPoint.addPolar(ref2, r2a, theta1); xPointsXformed[3] = currentPoint.x; yPointsXformed[3] = currentPoint.y; fillPolygon(xPointsXformed, yPointsXformed, 4); } // Draw a speed-blur polygon between a pair of circles. public void circleBlur(SpacePoint ref1, double r1, SpacePoint ref2, double r2) { long d; long x; long y; allocPointsIfNeeded(4); // Compute vector from ref1 to ref2, place it in (x,y). x = ref2.x - ref1.x; y = ref2.y - ref1.y; // Normalize. Return if zero distance between ref1 and ref2. d = (long)Math.sqrt((double)(x * x + y * y)); if (d == 0) { return; } x /= d; y /= d; // Rotate (x,y) ninety degrees counter-clockwise. d = -x; x = y; y = d; // Build list of points for speed-blur polygon. xPointsXformed[0] = (int)(ref1.x + x * r1); yPointsXformed[0] = (int)(ref1.y + y * r1); xPointsXformed[1] = (int)(ref1.x - x * r1); yPointsXformed[1] = (int)(ref1.y - y * r1); xPointsXformed[2] = (int)(ref2.x - x * r2); yPointsXformed[2] = (int)(ref2.y - y * r2); xPointsXformed[3] = (int)(ref2.x + x * r2); yPointsXformed[3] = (int)(ref2.y + y * r2); // Draw the polygon! fillPolygon(xPointsXformed, yPointsXformed, 4); } }