//BouncingMouse.java //click on ball kills it import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; public class BouncingMouse extends JApplet implements ActionListener { JLabel infoLabel, sizeLabel, moveLabel, animationDelayLabel; JTextField sizeTextField, movesizeTextField, animationDelayTextField; JPanel controlPanel; int size, movesize; int x, y, dir; Color circleColor; int hits; //boolean mouseHit; int animationDelay; // millisecond delay Timer animationTimer; // Timer drives animation public void init() { Container container = getContentPane(); container.setLayout( new BorderLayout() ); controlPanel = new JPanel(); controlPanel.setLayout(new FlowLayout()); controlPanel.setBackground(Color.MAGENTA); controlPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.RAISED)); container.add(controlPanel,BorderLayout.NORTH); infoLabel = new JLabel( "Click the circle. " ); controlPanel.add( infoLabel ); sizeLabel = new JLabel( "Size of circle" ); controlPanel.add( sizeLabel ); sizeTextField = new JTextField("50",3); size = Integer.parseInt(sizeTextField.getText()); sizeTextField.setBackground(Color.CYAN); sizeTextField.addActionListener( this ); controlPanel.add( sizeTextField ); moveLabel = new JLabel( "Size of move" ); controlPanel.add( moveLabel ); movesizeTextField = new JTextField("10",3); movesize = Integer.parseInt(movesizeTextField.getText()); movesizeTextField.setBackground(Color.CYAN); movesizeTextField.addActionListener(this ); controlPanel.add( movesizeTextField ); animationDelayLabel = new JLabel( "Frame rate in ms" ); controlPanel.add( animationDelayLabel ); animationDelayTextField = new JTextField("30",3); animationDelay = Integer.parseInt(animationDelayTextField.getText()); animationDelayTextField.setBackground(Color.CYAN); animationDelayTextField.addActionListener( this ); controlPanel.add( animationDelayTextField ); x=(int)(Math.random()*getWidth()); //random starting y=(int)(Math.random()*getHeight()); dir=(int)(Math.random()*4); //random diagonal direction: //0 is NE, 1 is SE, 2 is SW, 3 is NW circleColor = new Color((int)(Math.random()*256), (int)(Math.random()*256), (int)(Math.random()*256)); //incantation that responds to mouse click events: addMouseListener( //anonymous inner class overrides mouseClicked. //creates a $1 class file which must be uploaded to web site new MouseAdapter() { public void mouseClicked( MouseEvent event) { int mouseX = event.getX(); //gets X coord of mouse click event int mouseY = event.getY(); if (Math.abs(x-mouseX)<=size/2 && Math.abs(y-mouseY)<=size/2) { //is inside circle hits++; showStatus("hits="+hits+" ("+mouseX+","+mouseY+")"); //generate new circle x=(int)(Math.random()*getWidth()); //random starting y=(int)(Math.random()*getHeight()); dir=(int)(Math.random()*4); //random diagonal direction: circleColor = new Color((int)(Math.random()*256), (int)(Math.random()*256), (int)(Math.random()*256)); //mouseHit = true; repaint(); //will invoke paint } else showStatus("hits="+hits+" ("+mouseX+","+mouseY+")"); } } ); startAnimation(); //begin animation } //will be called when mouse clicks on ball //and each time timer goes off public void paint (Graphics g) { super.paint(g); //clears entire screen //g.setColor( Color.WHITE ); //problem when new x,y when mouse click...??? //g.fillOval(x-size/2,y-size/2,size,size); //erase current circle if (dir == 0) { //moving NE x = x + movesize; y = y - movesize; if (y-size/2 <= 0) //hit top, dir = 1; //change to SE. else if (x+size/2 >= getWidth()) //hit right, dir = 3; //change to NW } else if (dir == 1) { x = x + movesize; y = y + movesize; if (x+size/2 >= getWidth()) dir = 2; else if (y+size/2 >= getHeight()) dir = 0; } else if (dir == 2) { x = x - movesize; y = y + movesize; if (x-size/2 <= 0) dir = 1; else if (y+size/2 >= getHeight()) dir = 3; } else if (dir == 3) { x = x - movesize; y = y - movesize; if (y-size/2 <= 0) dir = 2; else if (x-size/2 <= 0) dir = 0; } /* else { //paint called because of mouse click inside ball mouseHit = false; //turn off hit flag //generate new circle x=(int)(Math.random()*getWidth()); //random starting y=(int)(Math.random()*getHeight()); dir=(int)(Math.random()*4); //random diagonal direction: } */ g.setColor( circleColor ); g.fillOval(x-size/2,y-size/2,size,size); } //** Generic animation stuff: use this as is for any animation. // respond to Timer's event and textfield events public void actionPerformed( ActionEvent event ) { if ( event.getSource() == animationTimer ) { repaint(); } else if ( event.getSource() == sizeTextField ) { size = Integer.parseInt(sizeTextField.getText()); repaint(); } else if ( event.getSource() == movesizeTextField ) { movesize = Integer.parseInt(movesizeTextField.getText()); repaint(); } else if ( event.getSource() == animationDelayTextField ) { animationDelay = Integer.parseInt(animationDelayTextField.getText()); stopAnimation(); startAnimation(); repaint(); } } // start or restart animation public void startAnimation() { // if ( animationTimer == null ) { animationTimer = new Timer( animationDelay, this ); animationTimer.start(); /* } else // continue from last image displayed if ( ! animationTimer.isRunning() ) animationTimer.restart(); */ } // stop animation timer public void stopAnimation() { animationTimer.stop(); } }