keldon85

FCircleCircleCollision.java

Apr 26th, 2014
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 8.60 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 fixed point Circle/Circle collision detection.
  14. */
  15. public class FCircleCircleCollision {
  16.     public static void main ( String argv [] ) {
  17.  
  18.         Circle A = new Circle ( 0,0, 1);
  19.         Circle B = new Circle ( 20, 0, 2 );
  20.         A.velocity = new Vector (10, -1);
  21.         System.out.println( collisionDistance ( A, B ) );
  22.  
  23.         JFrame frame = new JFrame ("Fixed-point Moving circle/circle collision");
  24.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  25.         frame.getContentPane().add( new CircleFrame ());
  26.         frame.pack();
  27.         frame.setVisible(true);
  28.     }
  29.    
  30.     static int collisionDistance ( Circle A, Circle B ) {      
  31.         if ( A.velocity == null ) return Integer.MAX_VALUE;
  32.         Vector v = new FVector ( A.velocity ).transform(new Vector(B.x - A.x,B.y - A.y));
  33.         int nx = v.x;
  34.         int ny = v.y;
  35.        
  36.         System.out.println ( "Integer nx,ny: " + nx + "," + ny );
  37.        
  38.         if ( nx <= 0 ) return Integer.MAX_VALUE;
  39.         if ( Math.abs(ny) > (A.radius+B.radius)) return Integer.MAX_VALUE;
  40.        
  41.         int distance = nx - (int)(Math.sqrt((double)((A.radius+B.radius)*(A.radius+B.radius) - (ny * ny))));
  42.         return distance;
  43.     }
  44.  
  45.     static class Circle {
  46.         int x, y, radius;
  47.        
  48.         Vector velocity = null;
  49.  
  50.         Circle(int _x, int _y, int _radius) {
  51.             x = _x;
  52.             y = _y;
  53.             radius = _radius;
  54.         }
  55.  
  56.         /** return whether this point is contained within the circle) */
  57.         boolean contains(int px, int py) {
  58.             int r = radius * radius;
  59.             px -= x;
  60.             py -= y;
  61.  
  62.             px *= px;
  63.             py *= py;
  64.  
  65.             return (px + py) <= r;
  66.         }
  67.        
  68.        
  69.  
  70.         public String toString (){
  71.             return "("+x+","+y+",r="+radius+")";
  72.         }
  73.     }
  74.  
  75.     /**
  76.      * Fixed point vector
  77.      * @author Keldon
  78.      *
  79.      */
  80.     static class FVector {
  81.         int x, y;
  82.  
  83.         public FVector(Vector v) {
  84.             x = v.x << 16;
  85.             y = v.y << 16;
  86.         }
  87.        
  88.         public FVector ( int _x, int _y ) {
  89.             x = _x;
  90.             y = _y;
  91.         }
  92.        
  93.         public FVector copy (){
  94.             return new FVector ( x,y);
  95.         }
  96.  
  97.         public void cross() {
  98.             int nx, ny;
  99.             nx = -y;
  100.             ny = x;
  101.  
  102.             x = nx;
  103.             y = ny;
  104.         }
  105.  
  106.         public int getLength() {
  107.             long lx = (long)x;
  108.             long ly = (long)y;
  109.             return (int)Math.sqrt((lx*lx) + (ly*ly));
  110.         }
  111.        
  112.         /**
  113.          * will transform v to a position relative to the plane where this vector is the x axis;
  114.          * for example if this vector were (1,0) then the returned vector would be the same. But if this
  115.          * vector were (0,1) then the returned vector would appear to have been rotated 90 degrees!
  116.          * @param v
  117.          * @return
  118.          */
  119.         public Vector transform ( Vector v ) {
  120.             int nx,ny;
  121.            
  122.             FVector x,y;
  123.  
  124.             x = copy();
  125.             x.normalize();
  126.             y = x.copy();
  127.             y.cross();
  128.  
  129.             nx = x.x * v.x + x.y * v.y;
  130.             ny = y.x * v.x + y.y * v.y;
  131.            
  132.             nx = nx >> 16;
  133.             ny = ny >> 16;
  134.            
  135.             return new Vector (nx,ny);
  136.         }
  137.  
  138.         public void normalize() {
  139.             int length = getLength();
  140.             if (length == 0)
  141.                 length = 1;
  142.            
  143.             x = (int)(((long)x << 16 ) / (long)length);
  144.             y = (int)(((long)y << 16 ) / (long)length);
  145.         }
  146.  
  147.         public String toString() {
  148.             return x + ",\t" + y;
  149.         }
  150.     }
  151.  
  152.     static class Vector {
  153.         int x, y;
  154.  
  155.         public Vector(int _x, int _y) {
  156.             x = _x;
  157.             y = _y;
  158.         }
  159.  
  160.         public void cross() {
  161.             int nx, ny;
  162.             nx = -y;
  163.             ny = x;
  164.  
  165.             x = nx;
  166.             y = ny;
  167.         }
  168.  
  169.         public int getLength() {
  170.             return (int) Math.sqrt((x * x) + (y * y));
  171.         }
  172.  
  173.         Vector copy() {
  174.             return new Vector(x, y);
  175.         }
  176.  
  177.         public String toString() {
  178.             return x + ",\t" + y;
  179.         }
  180.     }
  181.     static class CircleFrame extends JPanel implements MouseListener, MouseMotionListener{
  182.         private static final long serialVersionUID = -7074661778734564087L;
  183.         Circle c1=null,c2=null;
  184.        
  185.         CircleFrame (){
  186.             setPreferredSize(new Dimension ( 640,480));
  187.             addMouseListener(this);
  188.             addMouseMotionListener(this);
  189.         }
  190.        
  191.         public void paintComponent ( Graphics g ) {
  192.             super.paintComponent(g);
  193.            
  194.             int x1,y1,x2,y2;
  195.            
  196.             if ( c1 != null ) {
  197.                
  198.                 // draw circle
  199.                 x1 = (int)(c1.x - c1.radius);
  200.                 y1 = (int)(c1.y - c1.radius);
  201.                 x2 = (int)(c1.radius*2);
  202.                 y2 = (int)(c1.radius*2);
  203.                 g.drawOval(x1, y1, x2, y2);
  204.                
  205.                 // draw velocity
  206.                 if ( c1.velocity != null ) {
  207.                     x1 = (int)c1.x;
  208.                     y1 = (int)c1.y;
  209.                     x2 = x1 + (int)c1.velocity.x;
  210.                     y2 = y1 + (int)c1.velocity.y;
  211.                     g.drawLine(x1,y1,x2,y2);
  212.                 }
  213.             }
  214.  
  215.             if ( c2 != null ) {
  216.                
  217.                 // draw circle
  218.                 x1 = (int)(c2.x - c2.radius);
  219.                 y1 = (int)(c2.y - c2.radius);
  220.                 x2 = (int)(c2.radius*2);
  221.                 y2 = (int)(c2.radius*2);
  222.                 g.drawOval(x1, y1, x2, y2);
  223.                
  224.             }
  225.            
  226.             if ( c1 != null & c2 != null ) {
  227.                 int distance = collisionDistance (c1, c2 );
  228.                 System.out.println(distance);
  229.                 if ( distance != Integer.MAX_VALUE ) {
  230.                     int vx = (c1.velocity.x*distance) / c1.velocity.getLength();
  231.                     int vy = (c1.velocity.y*distance) / c1.velocity.getLength();
  232.                     x1 = (int)((c1.x - c1.radius) + vx);
  233.                     y1 = (int)((c1.y - c1.radius) + vy);
  234.                     x2 = (int)(c1.radius*2);
  235.                     y2 = (int)(c1.radius*2);
  236.                     g.drawOval(x1, y1, x2, y2);
  237.                    
  238.                     if ( distance <= c1.velocity.getLength() ){
  239.                         g.fillOval(x1, y1, x2, y2);
  240.                     }
  241.                 }
  242.             }
  243.            
  244.         }
  245.  
  246.         Point lDown = null, rDown = null, clDown = null;
  247.         public void mousePressed(MouseEvent e) {
  248.             button = e.getButton();
  249.             switch ( e.getButton ()){
  250.                 case MouseEvent.BUTTON1:
  251.                     if ( (e.getModifiers() & MouseEvent.CTRL_MASK) != 0 & c1 != null ) {
  252.                         int dx = e.getPoint().x - (int)c1.x;
  253.                         int dy = e.getPoint().y - (int)c1.y;
  254.                         if ( c1!= null ) c1.velocity = new Vector ( dx, dy );
  255.                         repaint();
  256.                     }
  257.                     else lDown = e.getPoint();
  258.                     break;
  259.                 case MouseEvent.BUTTON3:
  260.                     rDown = e.getPoint();
  261.                     break;
  262.             }
  263.         }
  264.  
  265.         int button = -1;
  266.         public void mouseDragged(MouseEvent e) {
  267.             switch ( button){
  268.                 case MouseEvent.BUTTON1:
  269.                     if ( (e.getModifiers() & MouseEvent.CTRL_MASK ) > 0 ){
  270.                         int dx = e.getPoint().x - (int)c1.x;
  271.                         int dy = e.getPoint().y - (int)c1.y;
  272.                         if ( c1!= null ) c1.velocity = new Vector ( dx, dy );
  273.                         repaint();
  274.                     } else {
  275.                         if ( lDown != null ) {
  276.                             int dx = e.getPoint().x - lDown.x;
  277.                             int dy = e.getPoint().y - lDown.y;
  278.                             int radius = (dx > dy ? dx : dy) >> 1;
  279.                             if ( radius < 0 ) radius = -radius;
  280.                             if ( radius != 0 ){
  281.                                 c1 = new Circle (lDown.x + radius, lDown.y+ radius, radius);
  282.                                 if ( dx < 0 ) c1.x -= radius*2;
  283.                                 if ( dy < 0 ) c1.y -= radius*2;
  284.                             }
  285.                             repaint();
  286.                         }
  287.                     }
  288.                     break;
  289.                 case MouseEvent.BUTTON3:
  290.                     if ( rDown != null ) {
  291.                         int dx = e.getPoint().x - rDown.x;
  292.                         int dy = e.getPoint().y - rDown.y;
  293.                         int radius = (dx > dy ? dx : dy) >> 1;
  294.                         if ( radius < 0 ) radius = -radius;
  295.                         if ( radius != 0 ){
  296.                             c2 = new Circle (rDown.x + radius, rDown.y+ radius,radius);
  297.                             if ( dx < 0 ) c2.x -= radius*2;
  298.                             if ( dy < 0 ) c2.y -= radius*2;
  299.                         }
  300.                         repaint();
  301.                     }
  302.                     break;
  303.             }
  304.         }
  305.        
  306.         public void mouseReleased(MouseEvent e) {
  307.             button = -1;
  308.  
  309.             switch ( e.getButton ()){
  310.                 case MouseEvent.BUTTON1:
  311.                     if ( (e.getModifiers() & MouseEvent.CTRL_MASK ) > 0 ){
  312.                         int dx = e.getPoint().x - (int)c1.x;
  313.                         int dy = e.getPoint().y - (int)c1.y;
  314.                         if ( c1!= null ) c1.velocity = new Vector (dx, dy );
  315.                         repaint();
  316.                     } else {
  317.                         if ( lDown != null ) {
  318.                             int dx = e.getPoint().x - lDown.x;
  319.                             int dy = e.getPoint().y - lDown.y;
  320.                             int radius = (dx > dy ? dx : dy) >> 1 ;
  321.                             if ( radius < 0 ) radius = -radius;
  322.                             if ( radius != 0 ){
  323.                                 c1 = new Circle (lDown.x + radius, lDown.y+ radius,radius);
  324.                                 if ( dx < 0 ) c1.x -= radius*2;
  325.                                 if ( dy < 0 ) c1.y -= radius*2;
  326.                             }
  327.                             repaint();
  328.                             lDown = null;
  329.                         }
  330.                     }
  331.                     break;
  332.                 case MouseEvent.BUTTON3:
  333.                     if ( rDown != null ) {
  334.                         int dx = e.getPoint().x - rDown.x;
  335.                         int dy = e.getPoint().y - rDown.y;
  336.                         int radius = (dx > dy ? dx : dy) >> 1;
  337.                         if ( radius < 0 ) radius = -radius;
  338.                         if ( radius != 0 ){
  339.                             c2 = new Circle (rDown.x + radius, rDown.y+ radius,radius);
  340.                             if ( dx < 0 ) c2.x -= radius*2;
  341.                             if ( dy < 0 ) c2.y -= radius*2;
  342.                         }
  343.                         repaint();
  344.                         rDown = null;
  345.                     }
  346.                     break;
  347.             }
  348.         }
  349.         public void mouseClicked(MouseEvent arg0) { }
  350.         public void mouseEntered(MouseEvent arg0) { }
  351.         public void mouseExited(MouseEvent arg0) { }
  352.         public void mouseMoved(MouseEvent arg0) { }
  353.        
  354.     }
  355.  
  356. }
Advertisement
Add Comment
Please, Sign In to add comment