Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

2d graphics simulation of a ball in gravity field. Energy conservation law is respected.

View physical_ball_2d_graphics.groovy
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
import javax.swing.*;
import java.awt.Color;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
 
public class Ball extends JComponent {
 
public static final int physicsTimerInterval = 1; // milliseconds, means 1000 computes / second
public static final int paintTimerInterval = 20; // milliseconds, means 50 frames / second
 
private double scale = 50; // pixels/meter
private double diameter = 1;
private double x = diameter;
private double y = diameter;
private double vx = 3;
private double vy = 0;
private double g = 9.8;
private double dt = physicsTimerInterval / 1000.0; // in seconds
private double energy;
private long stepsComputed = 0;
 
public Ball() {
}
void computePhysics() {
Rectangle r = getBounds(null);
double bx = r.x / scale;
double by = r.y / scale;
double bwidth = r.width / scale;
double bheight = r.height / scale;
if(stepsComputed == 0)
energy = (vx*vx + vy*vy) / 2 + g * (bheight - y)
if(x < bx + diameter / 2) {
x = Math.max(x, bx + diameter / 2);
vx = -vx;
} else if (x > bx + bwidth - diameter / 2) {
x = Math.min(x, bx + bwidth - diameter / 2);
vx = -vx;
}
if(y < by + diameter / 2) {
y = Math.max(y, by + diameter / 2);
vy = -vy;
} else if (y > by + bheight - diameter / 2) {
y = Math.min(y, by + bheight - diameter / 2);
vy = -vy;
}
vy += g * dt;
x += vx * dt;
// y += vy * dt;
// respect energy conservation law
y = bheight - (energy - (vx*vx + vy*vy) / 2) / g;
++stepsComputed;
}
 
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
double screenX = x * scale;
double screenY = y * scale;
double screenDiameter = diameter * scale;
Ellipse2D.Double circle = new Ellipse2D.Double(screenX - screenDiameter / 2, screenY - screenDiameter / 2, screenDiameter, screenDiameter);
g2d.setPaint(new Color(0, 128, 128));
g2d.fill(circle);
}
}
 
public class Main {
private static void createAndShowGUI() {
JFrame frame = new JFrame("Java 2d graphics test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
final Ball component = new Ball();
frame.add(component);
final Timer physicsTimer = new Timer(Ball.physicsTimerInterval, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
component.computePhysics();
}
});
final Timer repaintTimer = new Timer(Ball.paintTimerInterval, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
component.repaint();
}
});
physicsTimer.start();
repaintTimer.start();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
physicsTimer.stop();
}
});
frame.setVisible(true);
}
 
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
 
new Main().main([] as String[])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.