import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import java.util.*; import java.applet.Applet; import java.applet.AudioClip; public class BouncingBall extends JApplet implements ActionListener, ChangeListener, ItemListener { private double appwidth = 600, appheight = 290; private double coefficient, gravity; private double horizontalVelocity, verticalVelocity; private double xPosition, yPosition; private double height; private double sleeptime; private int bounces; private boolean action; private JLabel coefficientLabel; private JSlider coefficientSlider; private JCheckBox soundBox; private JButton startButton, resetButton; private AudioClip bounce; private Image ball; public void init() { defaultValues(); gravity = 9.8000000000000007; Container c = getContentPane(); c.setLayout (new FlowLayout()); coefficientLabel = new JLabel ("Restitution Coefficient (%) : "); coefficientSlider = new JSlider (SwingConstants.HORIZONTAL, 0, 100, 30); coefficientSlider.addChangeListener (this); coefficientSlider.setMajorTickSpacing (20); coefficientSlider.setMinorTickSpacing (5); coefficientSlider.setPaintTicks (true); coefficientSlider.setPaintLabels(true); c.add (coefficientLabel); c.add (coefficientSlider); soundBox = new JCheckBox ("Sound", true); soundBox.addItemListener (this); c.add (soundBox); startButton = new JButton ("Start"); startButton.addActionListener (this); c.add (startButton); resetButton = new JButton ("Reset"); resetButton.addActionListener (this); c.add (resetButton); bounce = getAudioClip(getDocumentBase(), "bounce.au"); ball = getImage(getDocumentBase(), "soccerball.gif"); } // init() public void defaultValues() { horizontalVelocity = 2.0; verticalVelocity = 0.0; xPosition = 40.0; yPosition = 70.0; height = appheight - yPosition; bounces = 0; sleeptime = 0.10000000000000001; action = false; } public void paint(Graphics g) { getContentPane().setBackground (Color.decode("#ccccff")); if (action && xPosition + horizontalVelocity < appwidth) { try { Thread.sleep ((int)(sleeptime * 1000)); } catch (InterruptedException interruptedexception) { showStatus (interruptedexception.toString()); } xPosition += horizontalVelocity; yPosition += verticalVelocity * sleeptime + 0.5 * gravity * Math.pow (sleeptime, 2); verticalVelocity = verticalVelocity + gravity * sleeptime; if(yPosition >= appheight) { yPosition = appheight; verticalVelocity = -getVi (++bounces); bounce.play(); } int i = ball.getWidth (this); int j = ball.getHeight (this); g.drawImage(ball, (int)xPosition, (int)yPosition, i / 2, j / 2, this); repaint(); } } // paint() public void update(Graphics g) { paint(g); } public double getVi (int i) { if (i == 0) return 0.0; else return Math.sqrt (2 * gravity * getH(i)); } public double getH (int i) { if (i == 0) return height; else return coefficient * 0.01 * getH(i - 1); } // Start / reset simulation with buttons. public void actionPerformed (ActionEvent e) { if (e.getSource() == startButton) { coefficient = coefficientSlider.getValue(); showStatus ("Coefficient of Restitution: " + (int)coefficient + "%"); action = true; repaint(); } if (e.getSource() == resetButton) { coefficientSlider.setValue (30); defaultValues(); getContentPane().repaint(); } } // Set coefficient of restitution with slider. public void stateChanged (ChangeEvent e) { coefficient = coefficientSlider.getValue(); showStatus ("Coefficient of Restitution: " + (int)coefficient + "%"); } // Set sound on/off status with check box. public void itemStateChanged (ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) bounce = getAudioClip (getDocumentBase(), "bounce.au"); else bounce = getAudioClip (getDocumentBase(), ""); } } // class BouncingBall