// // FILE: CannonGameFrame.java // AUTHOR: Eugene Wallingford // DATE: 2012/10/08 // COMMENT: This class is based on Tim Budd's original CannonWorld // and adapted for CS 2530. // // MODIFIED: 2012/10/23 -- Eugene Wallingford // CHANGE: added a button that lets user change the ball's color // import java.awt.Button; import java.awt.Color; import java.awt.Frame; import java.awt.Graphics; import java.awt.Scrollbar; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.AdjustmentEvent; import java.awt.event.AdjustmentListener; public class CannonGameFrame extends CloseableFrame { private static final int FrameWidth = 600; private static final int FrameHeight = 400; private int angle; private String message; private CannonBall cannonBall; private Scrollbar angleSlider; public CannonGameFrame() { super(); setSize ( FrameWidth, FrameHeight ); setTitle( "Cannon World" ); angle = 30; message = "Angle: " + angle; cannonBall = null; angleSlider = new Scrollbar( Scrollbar.VERTICAL, angle, 5, 0, 95 ); angleSlider.addAdjustmentListener( new AngleSliderListener() ); add( "East", angleSlider ); Button fire = new Button( "shoot a cannonball" ); fire.addActionListener( new FireButtonListener() ); add( "North", fire ); //***** the new button Button colorButton = new Button( "changeColor" ); add( "West", colorButton ); colorButton.addActionListener( new ColorButtonListener() ); } public void paint( Graphics g ) { drawCannon ( g ); drawTarget ( g ); drawCannonBall( g ); writeMessage ( g ); try { Thread.sleep( 200 ); } catch (Exception e) {} } /* ---------------- paint helper methods ---------------- */ protected void drawCannon( Graphics g ) { int x = 20; int y = 15; double radianAngle = angle * Math.PI / 180.0; int lv = (int) ( 30 * Math.sin(radianAngle) ); int lh = (int) ( 30 * Math.cos(radianAngle) ); int sv = (int) ( 10 * Math.sin(radianAngle + Math.PI/2) ); int sh = (int) ( 10 * Math.cos(radianAngle + Math.PI/2) ); g.setColor( Color.green ); g.drawLine( x, dy(y), x+lh, dy(y+lv) ); g.drawLine( x+lh, dy(y+lv), x+lh+sh, dy(y+lv+sv) ); g.drawLine( x+lh+sh, dy(y+lv+sv), x+sh, dy(y+sv) ); g.drawLine( x+sh, dy(y+sv), x, dy(y) ); g.fillOval( x-8, dy(y+10), 12, 12 ); } protected void drawTarget( Graphics g ) { g.setColor( Color.red ); g.fillRect( FrameWidth-100, dy(12), 50, 10 ); } protected void drawCannonBall( Graphics g ) { if ( cannonBall == null ) return; cannonBall.move(); cannonBall.paint( g ); if ( dy(cannonBall.y()) > 0 ) repaint(); else { int ballX = cannonBall.x(); int targetX = FrameWidth - 100; if ( ballX < targetX ) message = sorryMessageFor( targetX - ballX ); else if ( ballX > (targetX + 50) ) message = sorryMessageFor( ballX - targetX - 50 ); else message = "Congratulations!"; cannonBall = null; } } protected void writeMessage( Graphics g ) { g.drawString( message, 10, FrameHeight/2 ); } /* ------------- miscellaneous helper methods ------------- */ // This method lets us think of up as up, even though // in Java frames, up is down. :-) public int dy( int y ) { return FrameHeight - y; } protected String sorryMessageFor( int units ) { return "Sorry... You missed by " + units + " feet."; } /* ------------------- listener classes ------------------- */ private class FireButtonListener implements ActionListener { public void actionPerformed( ActionEvent e ) { double angleInRadians = angle * Math.PI / 180.0; double sinAngle = Math.sin( angleInRadians ); double cosAngle = Math.cos( angleInRadians ); cannonBall = new CannonBall( 15 + (int) (30 * cosAngle), dy(5+(int) (30 * sinAngle)), 5, 12 * cosAngle, -12 * sinAngle ); repaint(); } } private class AngleSliderListener implements AdjustmentListener { public void adjustmentValueChanged( AdjustmentEvent e ) { angle = angleSlider.getValue(); message = "Angle: " + angle; repaint(); } } //***** the new button listener private class ColorButtonListener implements ActionListener { public void actionPerformed( ActionEvent e ) { if ( cannonBall != null ) { cannonBall.nextColor(); repaint(); } } } }