Advertisement
Guest User

ball collision

a guest
Jan 12th, 2013
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 10.54 KB | None | 0 0
  1. import javax.swing.JPanel;
  2. import javax.swing.JFrame;
  3. import java.awt.Graphics;
  4. import java.awt.Dimension;
  5. import java.util.List;
  6. import java.util.ArrayList;
  7. import java.util.Arrays;
  8. import java.awt.Color;
  9. import java.awt.event.MouseAdapter;
  10. import java.awt.event.MouseEvent;
  11.  
  12. class Vector {
  13.     private final double x,y;
  14.     Vector(double x, double y) {
  15.         this.x = x;
  16.         this.y = y;
  17.     }
  18.     public double getX() {
  19.         return x;
  20.     }
  21.     public double getY() {
  22.         return y;
  23.     }
  24.     public Vector addX(double dx) {
  25.         return new Vector(x+dx, y);
  26.     }
  27.     public Vector addY(double dy) {
  28.         return new Vector(x, y+dy);
  29.     }
  30.     public Vector add(Vector v) {
  31.         return new Vector(x+v.x, y+v.y);
  32.     }
  33.     public Vector sub(Vector v) {
  34.         return new Vector(x-v.x, y-v.y);
  35.     }
  36.     public Vector mul(double d) {
  37.         return new Vector(x*d, y*d);
  38.     }
  39.     public Vector div(double d) {
  40.         return new Vector(x/d, y/d);
  41.     }
  42.     public Vector neg() {
  43.         return new Vector(-x, -y);
  44.     }
  45.     public Vector negX() {
  46.         return new Vector(-x, y);
  47.     }
  48.     public Vector negY() {
  49.         return new Vector(x, -y);
  50.     }
  51.     public double angle() {
  52.         return Math.atan2(y, x);
  53.     }
  54.     public double length() {
  55.         return Math.sqrt(x*x+y*y);
  56.     }
  57.     public double distance(Vector v) {
  58.         return sub(v).length();
  59.     }
  60.     public Vector normalize() {
  61.         double length = length();
  62.         if(length == 1) return this;
  63.         else if(length == 0) return new Vector(1,0);
  64.         else return new Vector(x/length, y/length);
  65.     }
  66.     public Vector rotate90() {
  67.         return new Vector(-y, x);
  68.     }
  69.     public Vector rotate(double angle) {
  70.         double sin = Math.sin(angle);
  71.         double cos = Math.cos(angle);
  72.         return new Vector(x*cos - y*sin,
  73.                           x*sin + y*cos);
  74.     }
  75.     public Vector rotate(Vector v) {
  76.         v = v.normalize();
  77.         return new Vector(x*v.x - y*v.y,
  78.                           x*v.y + y*v.x);
  79.     }
  80.     public Vector oppositeRotVector() {
  81.         return new Vector(x, -y).normalize();
  82.     }
  83.     @Override
  84.     public String toString() {
  85.         return "Vector("+x+", "+y+")";
  86.     }
  87. }
  88.  
  89. abstract class Shape {
  90.     private Vector pos;
  91.     private Vector velocity;
  92.     Shape(Vector pos) {
  93.         this.pos = pos;
  94.         this.velocity = new Vector(0,0);
  95.     }
  96.     abstract public double getArea();
  97.     abstract public boolean collides(Circle c);
  98.     abstract public boolean contains(Vector v);
  99.     public Vector getPos() {
  100.         return pos;
  101.     }
  102.     public Vector getVelocity() {
  103.         return velocity;
  104.     }
  105.     public void setVelocity(Vector v) {
  106.         this.velocity = v;
  107.     }
  108.     public void move(Vector v) {
  109.         pos = pos.add(v);
  110.     }
  111.     public void accelerate(Vector v) {
  112.         velocity = velocity.add(v);
  113.     }
  114.     public void update(double time) {
  115.         pos = pos.add(velocity.mul(time));
  116.     }
  117.     abstract public void paint(Graphics g);
  118. }
  119.  
  120. class Circle extends Shape {
  121.     private double radius;
  122.     private boolean moveable = true;
  123.     Circle(Vector pos, double radius) {
  124.         super(pos);
  125.         this.radius = radius;
  126.     }
  127.     public void setMoveable(boolean moveable) {
  128.         this.moveable = moveable;
  129.     }
  130.     public boolean isMoveable() {
  131.         return moveable;
  132.     }
  133.     public double getRadius() {
  134.         return radius;
  135.     }
  136.     public double getArea() {
  137.         return Math.PI*radius*radius;
  138.     }
  139.     public boolean collides(Circle c) {
  140.         return getPos().sub(c.getPos()).length() <= radius+c.radius;
  141.     }
  142.     public boolean contains(Vector v) {
  143.         return v.sub(getPos()).length() <= radius;
  144.     }
  145.     public void collisionCheck(List<Shape> shapes, double time) {
  146.         boolean movedBack = false;
  147.         for(int i = 0; i < shapes.size(); i++) {
  148.             Shape shape = shapes.get(i);
  149.             if(shape != this && shape.collides(this)) {
  150.                 if(!movedBack) {
  151.                     move(getVelocity().mul(time).neg());
  152.                     movedBack = true;
  153.                 }
  154.                 if(shape instanceof Circle) reflect((Circle)shape);
  155.                 else if(shape instanceof Rectangle) reflect((Rectangle)shape);
  156.                 else setVelocity(getVelocity().neg());
  157.             }
  158.         }
  159.     }
  160.     public void reflect(Rectangle r) {
  161.         if(getPos().getX() >= r.getPos().getX() && getPos().getX() < r.getPos().getX()+r.getWidth()) {
  162.             setVelocity(getVelocity().negY());
  163.         } else if(getPos().getY() >= r.getPos().getY() && getPos().getY() < r.getPos().getY()+r.getHeight()) {
  164.             setVelocity(getVelocity().negX());
  165.         } else {
  166.             Vector corner = null;
  167.             for(Vector c: r.getCorners()) {
  168.                 if(corner == null) corner = c;
  169.                 else if(getPos().distance(c) < getPos().distance(corner)) {
  170.                     corner = c;
  171.                 }
  172.             }
  173.             Circle c = new Circle(corner, 1);
  174.             c.setMoveable(false);
  175.             reflect(c);
  176.            
  177.         }
  178.     }
  179.     public void reflect(Circle c) {
  180.         Vector tangent = c.getPos().sub(getPos()).rotate90().normalize();
  181.         Vector rotVector = tangent.oppositeRotVector();
  182.         Vector vel1 = getVelocity().rotate(rotVector);
  183.         Vector vel2 = c.getVelocity().rotate(rotVector);
  184.         double v1 = vel1.getY();
  185.         double v2 = vel2.getY();
  186.         double m1 = getArea();
  187.         double m2 = c.getArea();
  188.         double speedm = 2*(m1*v1+m2*v2)/(m2+m1);
  189.         double newV1 = speedm-v1;
  190.         double newV2 = speedm-v2;
  191.        
  192.         if(!isMoveable()) {
  193.             newV1 = v1;
  194.             newV2 = -v2;
  195.         } else if(!c.isMoveable()) {
  196.             newV1 = -v1;
  197.             newV2 = v2;
  198.         }
  199.        
  200.         vel1 = new Vector(vel1.getX(), newV1).rotate(tangent);
  201.         vel2 = new Vector(vel2.getX(), newV2).rotate(tangent);
  202.         setVelocity(vel1);
  203.         c.setVelocity(vel2);
  204.     }
  205.    
  206.     public void paint(Graphics g) {
  207.         g.fillOval((int)(getPos().getX()-radius),
  208.                    (int)(getPos().getY()-radius),
  209.                    (int)(radius*2), (int)(radius*2));
  210.     }
  211. }
  212.  
  213. class Rectangle extends Shape {
  214.     private double width, height;
  215.     Rectangle(Vector pos, double width, double height) {
  216.         super(pos);
  217.         this.width = width;
  218.         this.height = height;
  219.     }
  220.     public double getWidth() {
  221.         return width;
  222.     }
  223.     public double getHeight() {
  224.         return height;
  225.     }
  226.     public double getArea() {
  227.         return width*height;
  228.     }
  229.     public List<Vector> getCorners() {
  230.         return Arrays.asList(getPos(), getPos().addX(width),
  231.                              getPos().addX(width).addY(height), getPos().addY(height));
  232.     }
  233.     public boolean contains(Vector v) {
  234.         return !(v.getX() < getPos().getX() || v.getX() >= getPos().getX()+width ||
  235.                  v.getY() < getPos().getY() || v.getY() >= getPos().getY()+height);
  236.     }
  237.     public boolean collides(Circle c) {
  238.         for(Vector corner: getCorners()) {
  239.             if(c.contains(corner)) {
  240.                 return true;
  241.             }
  242.         }
  243.         Vector cPos = c.getPos();
  244.         return  (cPos.getX() >= getPos().getX() &&
  245.                  cPos.getX() < getPos().getX()+width &&
  246.                  cPos.getY()+c.getRadius() >= getPos().getY() &&
  247.                  cPos.getY()-c.getRadius() < getPos().getY()+height) ||
  248.                 (cPos.getX()+c.getRadius() >= getPos().getX() &&
  249.                  cPos.getX()-c.getRadius() < getPos().getX()+width &&
  250.                  cPos.getY() >= getPos().getY() &&
  251.                  cPos.getY() < getPos().getY()+height);
  252.     }
  253.     public void paint(Graphics g) {
  254.         g.fillRect((int)getPos().getX(),
  255.                    (int)getPos().getY(),
  256.                    (int)width, (int)height);
  257.     }
  258. }
  259.  
  260. public class Collision extends JPanel {
  261.     ArrayList<Shape> shapes = new ArrayList<Shape>();
  262.     Vector mousePressedPos = null;
  263.     Vector mousePos = null;
  264.    
  265.     private MouseAdapter mouseAdapter = new MouseAdapter() {
  266.         public void mousePressed(MouseEvent e) {
  267.             mousePressedPos = new Vector(e.getX(), e.getY());
  268.             mousePos = null;
  269.         }
  270.         public void mouseReleased(MouseEvent e) {
  271.             if(mousePos != null) {
  272.                 Circle ball = new Circle(mousePressedPos, 20);
  273.                 for(Shape shape: shapes) {
  274.                     if(shape.collides(ball)) {
  275.                         return;
  276.                     }
  277.                 }
  278.                 ball.setVelocity(mousePos.sub(mousePressedPos));
  279.                 addShapes(ball);
  280.             }
  281.         }
  282.         public void mouseDragged(MouseEvent e) {
  283.             mousePos = new Vector(e.getX(), e.getY());
  284.         }
  285.     };
  286.    
  287.     public Collision() {
  288.         addMouseListener(mouseAdapter);
  289.         addMouseMotionListener(mouseAdapter);
  290.     }
  291.    
  292.     public void addShapes(Shape ... shapes) {
  293.         for(Shape s: shapes) this.shapes.add(s);
  294.         repaint();
  295.     }
  296.    
  297.     public void start() throws Exception {
  298.         long lastTime = System.nanoTime();
  299.         while(true) {
  300.             long currentTime = System.nanoTime();
  301.             double time = (currentTime - lastTime)/1e9;
  302.             lastTime = currentTime;
  303.             for(int i=0; i<shapes.size(); i++) {
  304.                 Shape s = shapes.get(i);
  305.                 s.update(time);
  306.                 if(s instanceof Circle) {
  307.                     ((Circle)s).collisionCheck(shapes, time);
  308.                 }
  309.             }
  310.             repaint();
  311.             Thread.sleep(1);
  312.         }
  313.     }
  314.    
  315.     public static void main(String[] args) throws Exception {
  316.         JFrame frame = new JFrame();
  317.         Collision panel = new Collision();
  318.        
  319.         Rectangle r1 = new Rectangle(new Vector(100,100), 200, 300);
  320.         Circle c1 = new Circle(new Vector(400,200), 50);
  321.         c1.setMoveable(false);
  322.         panel.addShapes(r1,c1);
  323.        
  324.         panel.setPreferredSize(new Dimension(800,600));
  325.         frame.add(panel);
  326.         frame.pack();
  327.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  328.         frame.setVisible(true);
  329.  
  330.         panel.start();
  331.     }
  332.    
  333.     @Override
  334.     public void paint(Graphics g) {
  335.         g.setColor(Color.WHITE);
  336.         g.fillRect(0,0,getWidth(),getHeight());
  337.         g.setColor(Color.BLACK);
  338.         for(int i=0; i < shapes.size(); i++) {
  339.             shapes.get(i).paint(g);
  340.         }
  341.     }
  342. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement