Created
July 17, 2019 01:22
-
-
Save ahmednasserpro/be175b05f8ca146bf578e971c6c8f4e7 to your computer and use it in GitHub Desktop.
Combine colliding bouncing balls
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.*; | |
import java.awt.event.*; | |
import java.util.ArrayList; | |
import javax.swing.*; | |
public class BouncingBall extends JFrame { | |
public BouncingBall() { | |
add(new BallControl()); | |
} | |
public static void main(String[] args) { | |
JFrame frame = new BouncingBall(); | |
frame.setSize(600, 500); | |
frame.setLocationRelativeTo(null); // Center the frame | |
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | |
frame.setVisible(true); | |
} | |
} | |
class BallControl extends JPanel { | |
private BallPanel ballPanel = new BallPanel(); | |
private JButton jbtSuspend = new JButton("Suspend"); | |
private JButton jbtResume = new JButton("Resume"); | |
private JButton jbtAdd = new JButton("+1"); | |
private JButton jbtSubtract = new JButton("-1"); | |
private JScrollBar jsbDelay = new JScrollBar(); | |
public BallControl() { | |
// Group buttons in a panel | |
JPanel panel = new JPanel(); | |
panel.add(jbtSuspend); | |
panel.add(jbtResume); | |
panel.add(jbtAdd); | |
panel.add(jbtSubtract); | |
// Add ball and buttons to the panel | |
ballPanel.setBorder( | |
new javax.swing.border.LineBorder(Color.red)); | |
jsbDelay.setOrientation(JScrollBar.HORIZONTAL); | |
ballPanel.setDelay(jsbDelay.getMaximum()); | |
setLayout(new BorderLayout()); | |
add(jsbDelay, BorderLayout.NORTH); | |
add(ballPanel, BorderLayout.CENTER); | |
add(panel, BorderLayout.SOUTH); | |
// Register listeners | |
jbtSuspend.addActionListener(new Listener()); | |
jbtResume.addActionListener(new Listener()); | |
jbtAdd.addActionListener(new Listener()); | |
jbtSubtract.addActionListener(new Listener()); | |
jsbDelay.addAdjustmentListener(new AdjustmentListener() { | |
@Override | |
public void adjustmentValueChanged(AdjustmentEvent e) { | |
ballPanel.setDelay(jsbDelay.getMaximum() - e.getValue()); | |
} | |
}); | |
} | |
class Listener implements ActionListener { | |
@Override | |
public void actionPerformed(ActionEvent e) { | |
if (e.getSource() == jbtSuspend) { | |
ballPanel.suspend(); | |
} else if (e.getSource() == jbtResume) { | |
ballPanel.resume(); | |
} else if (e.getSource() == jbtAdd) { | |
ballPanel.add(); | |
} else if (e.getSource() == jbtSubtract) { | |
ballPanel.subtract(); | |
} | |
} | |
} | |
} | |
class BallPanel extends JPanel { | |
private int delay = 10; | |
private ArrayList<Ball> list = new ArrayList<>(); | |
private Timer timer = new Timer(delay, new ActionListener() { | |
@Override | |
public void actionPerformed(ActionEvent event) { | |
repaint(); | |
} | |
}); | |
public BallPanel() { | |
timer.start(); | |
} | |
public void add() { | |
list.add(new Ball()); | |
} | |
public void subtract() { | |
list.remove(list.size() - 1); | |
} | |
@Override | |
protected void paintComponent(Graphics g) { | |
super.paintComponent(g); | |
for (int i = 0; i < list.size(); i++) { | |
Ball ball1 = list.get(i); | |
g.setColor(ball1.color); | |
if (ball1.x < 0 || ball1.x > getWidth()) | |
ball1.dx = -ball1.dx; | |
if (ball1.y < 0 || ball1.y > getHeight()) | |
ball1.dy = -ball1.dy; | |
ball1.x += ball1.dx; | |
ball1.y += ball1.dy; | |
if (getcollideIndex(ball1, i) != -1) { | |
Ball ball2 = list.get(getcollideIndex(ball1, i)); | |
list.remove(ball2); | |
ball1.radius += ball2.radius; | |
} | |
g.fillOval(ball1.x - ball1.radius, ball1.y - ball1.radius, | |
ball1.radius * 2, ball1.radius * 2); | |
} | |
} | |
public int getcollideIndex(Ball ball1, int index) { | |
for (int i = 0; i < list.size(); i++) { | |
if (i == index) | |
continue; | |
Ball ball2 = list.get(i); | |
int dis = distance(ball1.x + ball1.radius, ball1.y + ball1.radius, | |
ball2.x + ball2.radius, ball2.y + ball2.radius); | |
if (dis <= Math.abs(ball1.radius - ball2.radius) || dis <= (ball1.radius + ball2.radius)) | |
return i; | |
} | |
return -1; | |
} | |
public static int distance(int x1, int y1, int x2, int y2) { | |
return (int) Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); | |
} | |
public void suspend() { | |
timer.stop(); | |
} | |
public void resume() { | |
timer.start(); | |
} | |
public void setDelay(int delay) { | |
this.delay = delay; | |
timer.setDelay(delay); | |
} | |
} | |
class Ball { | |
int x = 0; | |
int y = 0; | |
int dx = 2; | |
int dy = 2; | |
int radius = 5; | |
Color color = new Color((int) (Math.random() * 256), (int) | |
(Math.random() * 256), (int) (Math.random() * 256)); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment