boxglue

Bouncing Images #2

Apr 30th, 2020
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 7.57 KB | None | 0 0
  1. package bouncer2;
  2.  
  3. /* NOTE: requires MyImage.java */
  4.  
  5. import java.awt.BorderLayout;
  6. import java.awt.Color;
  7. import java.awt.Dimension;
  8. import java.awt.Graphics;
  9. import java.awt.Point;
  10. import java.awt.event.ActionEvent;
  11. import java.awt.event.ActionListener;
  12. import java.util.ArrayList;
  13.  
  14. import javax.swing.JButton;
  15. import javax.swing.JFrame;
  16. import javax.swing.JPanel;
  17.  
  18.  
  19.  
  20. public class BouncingImages2 extends JFrame implements ActionListener {
  21.  
  22.     public static void main(String[] args) {
  23.         new BouncingImages2();
  24.     }
  25.  
  26.  
  27.     /* These are the width and height of the DrawingPanel NOT the whole JFrame.
  28.     Bouncing off walls will not work properly if it's the JFrame size */
  29.     static final int WINW = 1000;
  30.     static final int WINH = 800;
  31.     static boolean imagesLoaded = true;
  32.  
  33.     JPanel buttonPanel = new JPanel();
  34.     AnimationPanel animationPanel;
  35.     ArrayList<ImageRect> imageList = new ArrayList<ImageRect>();
  36.     AnimationThread thread;
  37.     private volatile boolean stopRequested = false; //maybe should use AtomicBoolean
  38.  
  39.     BouncingImages2() {
  40.  
  41.         //set up button panel
  42.         JButton btnStart = new JButton("Start");
  43.         JButton btnStop  = new JButton("Stop");
  44.         JButton btnExit  = new JButton("Exit");
  45.         btnStart.addActionListener(this);
  46.         btnStop.addActionListener(this);
  47.         btnExit.addActionListener(this);
  48.         buttonPanel.add(btnStart);
  49.         buttonPanel.add(btnStop);
  50.         buttonPanel.add(btnExit);
  51.  
  52.         animationPanel = new AnimationPanel();
  53.  
  54.         //setup JFrame
  55.         //this.setExtendedState(JFrame.MAXIMIZED_BOTH); //If we use this, then we need to determine the dimensions of the JPanel before we start drawing
  56.         // this.setUndecorated(true);
  57.         this.add(buttonPanel, BorderLayout.SOUTH);
  58.         this.add(animationPanel);
  59.         this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  60.         this.pack(); //since the JPanel is controlling the size, we need pack() here.
  61.         this.setLocationRelativeTo(null);   //after pack();
  62.         this.setVisible(true);
  63.     }
  64.  
  65.     void startAnimation() {
  66.         //this doesn't restart the thread if it terminates
  67.         if (thread == null) {
  68.             thread = new AnimationThread ();
  69.             stopRequested = false;
  70.             thread.start();        
  71.         }
  72.         //System.out.println("thread is " + thread.toString());
  73.  
  74.         //this will "restart" the thread!
  75.         if (thread.getThreadGroup() == null) {
  76.             thread = new AnimationThread ();
  77.             stopRequested = false;
  78.             thread.start();
  79.         }
  80.  
  81.     }
  82.  
  83.     //two different versions here as I was testing how to stop threads properly
  84.     void stopAnimation1(){
  85.         stopRequested = true;      
  86.     }
  87.  
  88.     void stopAnimation2(){     
  89.         thread.interrupt();
  90.         //System.out.println(thread.isInterrupted());
  91.     }
  92.  
  93.     void addImage()  { 
  94.         //  imageList.add(new ImageRect("planeIcon.png"));
  95.         //don't allow two images to be added on top of each other
  96.         ImageRect ir = null;
  97.         while (true) {
  98.             ir= new ImageRect("planeIcon.pngx");
  99.             if (checkCollision(ir)) {
  100.                 try {
  101.                     Thread.sleep(100);
  102.                 } catch (InterruptedException e) {}
  103.             } else {
  104.                 break;
  105.             }
  106.         }
  107.  
  108.         imageList.add(ir);
  109.     }
  110.  
  111.     void moveAllImages() {
  112.         for (ImageRect image : imageList) {                
  113.             image.moveImage();
  114.             image.calculatePoints();
  115.             checkCollision(image);
  116.         }
  117.     }
  118.  
  119.     boolean checkCollision(ImageRect currIm) {
  120.  
  121.         for (ImageRect im : imageList) {   
  122.             if (currIm == im) continue; //don't collide with yourself
  123.  
  124.             // check to see if the two images are close enough to collide
  125.             //          if (distance (currIm.ctr, im.ctr) > (ImageRect.biggestDim*ImageRect.biggestDim*4)) {               
  126.             //              return;  //I think that this should be (1.5 * biggestDim)^2
  127.             //          }
  128.  
  129.             if (currIm.intersects(im)) {
  130.                 //determine which side hits
  131.  
  132.                 //first check the centres:
  133.                 //Does it hit the left or right side?
  134.                 if (im.contains(currIm.ml) || im.contains(currIm.mr)) {
  135.                     currIm.undoMove();
  136.                     currIm.vx *= -1;
  137.                     return true;
  138.                 }
  139.                 //does it hit the top or bottom?
  140.                 if (im.contains(currIm.mt) || im.contains(currIm.mb)) {
  141.                     currIm.undoMove();
  142.                     currIm.vy *= -1;
  143.                     return true;
  144.                 }
  145.  
  146.                 //We have to reverse this too because a large rectangle can move over a small one and freeze if the small one fits between the corner and a midpoint
  147.                 if (currIm.contains(im.ml) || currIm.contains(im.mr)) {
  148.                     currIm.undoMove();
  149.                     currIm.vx *= -1;
  150.                     return true;
  151.                 }
  152.                 //does it hit the top or bottom?
  153.                 if (currIm.contains(im.mt) || currIm.contains(im.mb)) {
  154.                     currIm.undoMove();
  155.                     currIm.vy *= -1;
  156.                     return true;
  157.                 }
  158.  
  159.                 //does it hit a corner?  This part has the least realistic bounce
  160.                 if (im.contains(currIm.tl) || im.contains(currIm.tr) || im.contains(currIm.bl) || im.contains(currIm.br)) {
  161.                     currIm.undoMove();
  162.                     currIm.vx *= -1;
  163.                     currIm.vy *= -1;
  164.                     return true;
  165.                 }
  166.  
  167.             }
  168.         }
  169.         return false;
  170.     }
  171.  
  172.     //for sake of speed, it returns distance squared
  173.     int distance(Point p1, Point p2) {
  174.         int dx = p1.x-p2.x;
  175.         int dy = p1.y-p2.y;
  176.         return dx*dx+dy*dy;
  177.     }
  178.  
  179.     //ActionListener for Buttons
  180.     @Override
  181.     public void actionPerformed(ActionEvent e) {
  182.         if (e.getActionCommand().equals("Start")) {
  183.             addImage();
  184.             startAnimation();
  185.         }
  186.         if (e.getActionCommand().equals("Stop")) {
  187.             stopAnimation2();          
  188.         }
  189.         if (e.getActionCommand().equals("Exit")) {
  190.             System.exit(0);        
  191.         }
  192.     }
  193.  
  194.     //This class does drawing graphics and nothing else
  195.     class AnimationPanel extends JPanel {
  196.  
  197.         AnimationPanel() {
  198.             this.setBackground(new Color(222,222,255));
  199.             this.setPreferredSize(new Dimension(WINW, WINH));
  200.         }
  201.  
  202.  
  203.         @Override
  204.         public void paintComponent(Graphics g){
  205.             synchronized(g) { //try to stop flicker
  206.                 super.paintComponent(g);
  207.                 g.setColor(Color.ORANGE);
  208.                 for (ImageRect im : imageList) {
  209.                     if(imagesLoaded) {
  210.                         g.drawImage(im.image, im.x, im.y, im.width, im.height,null);
  211.                         g.drawRect(im.x, im.y, im.width, im.height);
  212.                     } else {
  213.                         g.setColor(im.color);
  214.                         g.fillRect(im.x, im.y, im.width, im.height);
  215.                     }
  216.                 }
  217.             }
  218.         }
  219.     }
  220.  
  221.     /* NOTE: I'm not that experienced with threads, preferring to use timers. A Swing Timer would work perfectly for this program
  222.      * Quote: "Starting from Java 5 it is not a good idea to work with Threads directly.
  223.      * You should rather use Executor framework and choose an execution policy depending on your requirements."
  224.      */
  225.     private class AnimationThread extends Thread {
  226.  
  227.         public void run() {
  228.             run2B(); //here we can test different methods
  229.         }
  230.  
  231.         //this version stops the thread using a flag and break. (use stopAnimation1())
  232.         public void run1() {
  233.             while (true) {     
  234.  
  235.                 //everything in the main game loop goes here
  236.                 moveAllImages();               
  237.             //  animationPanel.repaint();
  238.                 animationPanel.paintImmediately(0, 0, WINW, WINH);
  239.  
  240.                 try {
  241.                     this.sleep(5);
  242.                 } catch (InterruptedException e) {}
  243.  
  244.                 if(stopRequested) break;
  245.             }
  246.  
  247.         }
  248.  
  249.         //this version stops the thread using an interrupt and break (use stopAnimation2())
  250.         public void run2A() {
  251.             while (true) {
  252.                 moveAllImages();
  253.                 //collide_images()
  254.                 animationPanel.repaint();
  255.  
  256.                 try {
  257.                     this.sleep(5);
  258.                 } catch (InterruptedException e) {     
  259.                     System.out.println("interrupted");
  260.                     break;
  261.                 }              
  262.             }
  263.         }
  264.  
  265.         //this version stops the thread using interrupt only (use stopAnimation2())
  266.         public void run2B() {
  267.             while ( ! thread.isInterrupted() ) {  // or     //while (! Thread.currentThread().isInterrupted() ) {
  268.                 moveAllImages();
  269.                 //collide_images()
  270.                 animationPanel.repaint();
  271.  
  272.                 try {
  273.                     this.sleep(5);
  274.                 } catch (InterruptedException e) {
  275.                     System.out.println("interrupted");
  276.                     thread.interrupt(); //catching the exception seems to clear it.
  277.                 }
  278.             }
  279.         }
  280.     }
  281. }
Add Comment
Please, Sign In to add comment