Skip to content

Instantly share code, notes, and snippets.

@akhikhl
Created December 31, 2013 16:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akhikhl/8199472 to your computer and use it in GitHub Desktop.
Save akhikhl/8199472 to your computer and use it in GitHub Desktop.
2d graphics simulation of a ball in gravity field. Energy conservation law is respected.
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