keldon85

CircleCircleCollision.java

Apr 26th, 2014
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 7.08 KB | None | 0 0
  1. package collision;
  2.  
  3. import java.awt.Dimension;
  4. import java.awt.Graphics;
  5. import java.awt.Point;
  6. import java.awt.event.MouseEvent;
  7. import java.awt.event.MouseListener;
  8. import java.awt.event.MouseMotionListener;
  9.  
  10. import javax.swing.JFrame;
  11. import javax.swing.JPanel;
  12.  
  13. /** Efficient circle / circle collision detection.
  14.  *  (c) Keldon Alleyne 2007
  15.  */
  16. public class CircleCircleCollision {
  17.     public static void main ( String argv [] ) {
  18.         Circle A = new Circle ( 1d, 0,0, new Vector (10d, -1d));
  19.         Circle B = new Circle ( 2d, 20d, 0d, null );
  20.         System.out.println( collisionDistance ( A, B ) );
  21.  
  22.         JFrame frame = new JFrame ();
  23.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  24.         frame.getContentPane().add( new CircleFrame ());
  25.         frame.pack();
  26.         frame.setVisible(true);
  27.     }
  28.    
  29.     static double collisionDistance ( Circle A, Circle B ) {
  30.         double x = B.x - A.x;
  31.         double y = B.y - A.y;
  32.        
  33.         if ( A.velocity == null ) return Double.NaN;
  34.         Vector velocity = A.velocity.normalized();
  35.        
  36.         double nx = x * velocity.x + y * velocity.y;
  37.         double ny = x * velocity.cross().x + y * velocity.cross().y;
  38.        
  39.         System.out.println ( "Double nx, ny: " + nx + "," + ny);
  40.        
  41.         if ( nx <= 0d ) return Double.NaN;
  42.         if ( Math.abs(ny) > (A.radius + B.radius )) return Double.NaN;
  43.            
  44.         double distance = nx - Math.sqrt( (A.radius+B.radius)*(A.radius+B.radius) - (ny * ny));
  45.         return distance;
  46.     }
  47.    
  48.     static class Circle {
  49.         double radius;
  50.         double x,y;
  51.         Vector velocity;
  52.        
  53.         Circle ( double _radius, double _x, double _y, Vector _velocity ) {
  54.             radius = _radius;
  55.             x = _x;
  56.             y = _y;
  57.             velocity = _velocity;
  58.         }
  59.     }
  60.    
  61.     static class Vector {
  62.         double x,y;
  63.        
  64.         Vector ( double _x, double _y ) {
  65.             x = _x;
  66.             y = _y;
  67.         }
  68.        
  69.         Vector cross (){
  70.             return new Vector ( -y, x);
  71.         }
  72.        
  73.         double length (){
  74.             return Math.sqrt(x*x + y*y);
  75.         }
  76.        
  77.         Vector normalized (){
  78.             return new Vector ( x / length(), y / length () );
  79.         }
  80.        
  81.     }
  82.    
  83.     static class CircleFrame extends JPanel implements MouseListener, MouseMotionListener{
  84.         private static final long serialVersionUID = -7074661778734564087L;
  85.         Circle c1=null,c2=null;
  86.        
  87.         CircleFrame (){
  88.             setPreferredSize(new Dimension ( 640,480));
  89.             addMouseListener(this);
  90.             addMouseMotionListener(this);
  91.         }
  92.        
  93.         public void paintComponent ( Graphics g ) {
  94.             super.paintComponent(g);
  95.            
  96.             int x1,y1,x2,y2;
  97.            
  98.             if ( c1 != null ) {
  99.                
  100.                 // draw circle
  101.                 x1 = (int)(c1.x - c1.radius);
  102.                 y1 = (int)(c1.y - c1.radius);
  103.                 x2 = (int)(c1.radius*2);
  104.                 y2 = (int)(c1.radius*2);
  105.                 g.drawOval(x1, y1, x2, y2);
  106.                
  107.                 // draw velocity
  108.                 if ( c1.velocity != null ) {
  109.                     x1 = (int)c1.x;
  110.                     y1 = (int)c1.y;
  111.                     x2 = x1 + (int)c1.velocity.x;
  112.                     y2 = y1 + (int)c1.velocity.y;
  113.                     g.drawLine(x1,y1,x2,y2);
  114.                 }
  115.             }
  116.  
  117.             if ( c2 != null ) {
  118.                
  119.                 // draw circle
  120.                 x1 = (int)(c2.x - c2.radius);
  121.                 y1 = (int)(c2.y - c2.radius);
  122.                 x2 = (int)(c2.radius*2);
  123.                 y2 = (int)(c2.radius*2);
  124.                 g.drawOval(x1, y1, x2, y2);
  125.                
  126.             }
  127.            
  128.             if ( c1 != null & c2 != null ) {
  129.                 double distance = collisionDistance (c1, c2 );
  130.                 System.out.println(distance);
  131.                 if ( ! (Double.isNaN(distance) | Double.isInfinite(distance)) ) {
  132.                     x1 = (int)((c1.x - c1.radius) + c1.velocity.normalized().x*distance);
  133.                     y1 = (int)((c1.y - c1.radius) + c1.velocity.normalized().y*distance);
  134.                     x2 = (int)(c1.radius*2);
  135.                     y2 = (int)(c1.radius*2);
  136.                     g.drawOval(x1, y1, x2, y2);
  137.                    
  138.                     if ( distance <= c1.velocity.length() ){
  139.                         g.fillOval(x1, y1, x2, y2);
  140.                     }
  141.                 }
  142.             }
  143.            
  144.         }
  145.  
  146.         Point lDown = null, rDown = null, clDown = null;
  147.         public void mousePressed(MouseEvent e) {
  148.             button = e.getButton();
  149.             switch ( e.getButton ()){
  150.                 case MouseEvent.BUTTON1:
  151.                     if ( (e.getModifiers() & MouseEvent.CTRL_MASK) != 0 & c1 != null ) {
  152.                         int dx = e.getPoint().x - (int)c1.x;
  153.                         int dy = e.getPoint().y - (int)c1.y;
  154.                         if ( c1!= null ) c1.velocity = new Vector ( (double) dx, (double) dy );
  155.                         repaint();
  156.                     }
  157.                     else lDown = e.getPoint();
  158.                     break;
  159.                 case MouseEvent.BUTTON3:
  160.                     rDown = e.getPoint();
  161.                     break;
  162.             }
  163.         }
  164.  
  165.         int button = -1;
  166.         public void mouseDragged(MouseEvent e) {
  167.             switch ( button){
  168.                 case MouseEvent.BUTTON1:
  169.                     if ( (e.getModifiers() & MouseEvent.CTRL_MASK ) > 0 ){
  170.                         int dx = e.getPoint().x - (int)c1.x;
  171.                         int dy = e.getPoint().y - (int)c1.y;
  172.                         if ( c1!= null ) c1.velocity = new Vector ( (double) dx, (double) dy );
  173.                         repaint();
  174.                     } else {
  175.                         if ( lDown != null ) {
  176.                             int dx = e.getPoint().x - lDown.x;
  177.                             int dy = e.getPoint().y - lDown.y;
  178.                             double radius = (double)((dx > dy ? dx : dy) >> 1 );
  179.                             if ( radius < 0 ) radius = -radius;
  180.                             if ( radius != 0 ){
  181.                                 c1 = new Circle (radius,(double)(lDown.x + radius), (double)(lDown.y+ radius), null);
  182.                                 if ( dx < 0 ) c1.x -= radius*2;
  183.                                 if ( dy < 0 ) c1.y -= radius*2;
  184.                             }
  185.                             repaint();
  186.                         }
  187.                     }
  188.                     break;
  189.                 case MouseEvent.BUTTON3:
  190.                     if ( rDown != null ) {
  191.                         int dx = e.getPoint().x - rDown.x;
  192.                         int dy = e.getPoint().y - rDown.y;
  193.                         double radius = (double)((dx > dy ? dx : dy) >> 1 );
  194.                         if ( radius < 0 ) radius = -radius;
  195.                         if ( radius != 0 ){
  196.                             c2 = new Circle (radius,(double)(rDown.x + radius), (double)(rDown.y+ radius), null);
  197.                             if ( dx < 0 ) c2.x -= radius*2;
  198.                             if ( dy < 0 ) c2.y -= radius*2;
  199.                         }
  200.                         repaint();
  201.                     }
  202.                     break;
  203.             }
  204.         }
  205.        
  206.         public void mouseReleased(MouseEvent e) {
  207.             button = -1;
  208.  
  209.             switch ( e.getButton ()){
  210.                 case MouseEvent.BUTTON1:
  211.                     if ( (e.getModifiers() & MouseEvent.CTRL_MASK ) > 0 ){
  212.                         int dx = e.getPoint().x - (int)c1.x;
  213.                         int dy = e.getPoint().y - (int)c1.y;
  214.                         if ( c1!= null ) c1.velocity = new Vector ( (double) dx, (double) dy );
  215.                         repaint();
  216.                     } else {
  217.                         if ( lDown != null ) {
  218.                             int dx = e.getPoint().x - lDown.x;
  219.                             int dy = e.getPoint().y - lDown.y;
  220.                             double radius = (double)((dx > dy ? dx : dy) >> 1 );
  221.                             if ( radius < 0 ) radius = -radius;
  222.                             if ( radius != 0 ){
  223.                                 c1 = new Circle (radius,(double)(lDown.x + radius), (double)(lDown.y+ radius), null);
  224.                                 if ( dx < 0 ) c1.x -= radius*2;
  225.                                 if ( dy < 0 ) c1.y -= radius*2;
  226.                             }
  227.                             repaint();
  228.                             lDown = null;
  229.                         }
  230.                     }
  231.                     break;
  232.                 case MouseEvent.BUTTON3:
  233.                     if ( rDown != null ) {
  234.                         int dx = e.getPoint().x - rDown.x;
  235.                         int dy = e.getPoint().y - rDown.y;
  236.                         double radius = (double)((dx > dy ? dx : dy) >> 1 );
  237.                         if ( radius < 0 ) radius = -radius;
  238.                         if ( radius != 0 ){
  239.                             c2 = new Circle (radius,(double)(rDown.x + radius), (double)(rDown.y+ radius), null);
  240.                             if ( dx < 0 ) c2.x -= radius*2;
  241.                             if ( dy < 0 ) c2.y -= radius*2;
  242.                         }
  243.                         repaint();
  244.                         rDown = null;
  245.                     }
  246.                     break;
  247.             }
  248.         }
  249.         public void mouseClicked(MouseEvent arg0) { }
  250.        
  251.         public void mouseEntered(MouseEvent arg0) { }
  252.        
  253.         public void mouseExited(MouseEvent arg0) { }
  254.  
  255.         public void mouseMoved(MouseEvent arg0) {
  256.         }
  257.        
  258.     }
  259. }
Advertisement
Add Comment
Please, Sign In to add comment