Pseudo elastic collision of two balls in java. Quick and dirty solution to implement elastic collision in java. There is better solution but this can serve good as well. Two balls are moving with different speed. One is heavier then the other, so we expect on collision the lighter ball to pick up some speed. Also if smaller ball hit bigger ball with certain amount of speed we expect bigger ball to pick some speed as well.
Here is ball class:
Here is ball class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | package realball; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.geom.Ellipse2D; /** * * @author Anak1n */ public class ball { private float x; private float y; private float diametar; Color color; private double xSpeed; private double ySpeed; public ball(float x, float y, float diameter, Color color) { this.x = x; this.y = y; this.diametar = diameter; this.color = color; } public void draw(Graphics g) { Graphics2D g2d = (Graphics2D) g; Ellipse2D.Double circle = new Ellipse2D.Double(getX() - getDiametar() / 2, getY() - getDiametar() / 2, getDiametar(), getDiametar()); g2d.fill(circle); } public void move() { setX((float) (getX() + getxSpeed())); if (getX() - getDiametar() / 2 < 0) { setX(getDiametar() / 2); setxSpeed(-getxSpeed()); } else if (getX() + getDiametar() / 2 > 390) { setxSpeed(-getxSpeed()); } setY((float) (getY() + getySpeed())); if (getY() - getDiametar() / 2 < 0) { setySpeed(-getySpeed()); } else if (getY() + getDiametar() / 2 > 360) { setY(360 - getDiametar() / 2); setySpeed(-getySpeed()); } } /** * @return the xSpeed */ public double getxSpeed() { return xSpeed; } /** * @param xSpeed the xSpeed to set */ public void setxSpeed(double xSpeed) { this.xSpeed = xSpeed; } /** * @return the ySpeed */ public double getySpeed() { return ySpeed; } /** * @param ySpeed the ySpeed to set */ public void setySpeed(double ySpeed) { this.ySpeed = ySpeed; } /** * @return the x */ public float getX() { return x; } /** * @param x the x to set */ public void setX(float x) { this.x = x; } /** * @return the y */ public float getY() { return y; } /** * @param y the y to set */ public void setY(float y) { this.y = y; } /** * @return the diametar */ public float getDiametar() { return diametar; } /** * @param diameter */ public void setDiametar(float diameter) { this.diametar = diameter; } } |
gui class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | package realball; import java.awt.Color; import java.awt.Graphics; import javax.swing.JPanel; /** * * @author Anak1n */ public class gui extends JPanel implements Runnable { ball b1; boolean going = true; Thread animator; ball b2; double deltaX; double deltaY; double distance; public gui() { b1 = new ball(50, 80, 40, Color.red); b1.setX(50); b1.setY(80); b1.setxSpeed(4); b1.setySpeed(2); b2 = new ball(50, 80, 70, Color.red); b2.setX(150); b2.setY(80); b2.setxSpeed(4); b2.setySpeed(2); animator = new Thread(this); animator.start(); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); b1.draw(g); b2.draw(g); g.setColor(Color.red); // draw center of circle g.fillOval((int) b1.getX() - 5, (int) b1.getY() - 5, 10, 10); g.fillOval((int) b2.getX() - 5, (int) b2.getY() - 5, 10, 10); } @Override public void run() { while (going) { b1.move(); b2.move(); checkCollision(); repaint(); try { Thread.sleep(20); } catch (InterruptedException ex) { } } } public void checkCollision() { deltaX = Math.abs(b1.getX() - b2.getX()); deltaY = Math.abs(b1.getY() - b2.getY()); distance = deltaX * deltaX + deltaY * deltaY; if (distance < (b1.getDiametar() / 2 + b2.getDiametar() / 2) * (b1.getDiametar() / 2 + b2.getDiametar() / 2)) { double newxSpeed1 = (b1.getxSpeed() * (4 - 7) + (2 * 7 * b2.getxSpeed())) / 11; double newxSpeed2 = (b2.getxSpeed() * (7 - 4) + (2 * 4 * b1.getxSpeed())) / 11; double newySpeed1 = (b1.getySpeed() * (4 - 7) + (2 * 7 * b2.getySpeed())) / 11; double newySpeed2 = (b2.getySpeed() * (7 - 4) + (2 * 4 * b1.getySpeed())) / 11; b2.setxSpeed(newxSpeed2); b2.setySpeed(newySpeed2); b1.setxSpeed(newxSpeed1); b1.setySpeed(newySpeed1); } } } |
main class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import javax.swing.JFrame; /** * * @author Anak1n */ public class RealBall { /** * @param args the command line arguments */ public static void main(String[] args) { JFrame frame = new JFrame (); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); gui balls = new gui (); frame.setSize(400,400); frame.add(balls); frame.setVisible(true); } } |
If you want to improve this collision I would suggest calculating angle of impact and new direction after impact.
Video: