// File: Main.java
// Date: Jul 29, 2010
// Author: Nicholas Duchon
// Purpose: physics experiments - bouncing balls, 2 and 3 D
eventually
// History:
// Mar 09, 2019 - moved from JApplet to JFrame,
various updates
public class Main extends JFrame implements BallOwner {
public static final long serialVersionUID =
123; // ND: junk
final static private String version = "0.0.2";
final static private String progName =
"Bouncing Balls Processor";
final static private String copyrightNotice =
progName + " - Copyright 2003-2019 by Nicholas Duchon";
final static private int
WINDOWWIDTH = 600;
final static private int
WINDOWHEIGHT = 400;
final static private double INITIALSPEED = 12;
// slider units:0 - 2*
final static private Random rn = new Random ();
JSlider speedS;
JPanel box = new JPanel ();
Stack <Ball>
balls = new Stack <Ball> ();
Timer tm;
boolean showNumberFlag = false, gravityFlag =
false;
double gravity = 0, speed = 1; // in pixels per
update of timer
JButton [] jbList = {
new NDCB
("Add" , Color.green, e ->
newBall() ),
new NDCB
("Remove" , Color.red , e -> removeBall() ),
new NDCB
("Shake" , Color.cyan , e -> shakeBalls() ),
new NDCB
("Show" , Color.red , e ->
showTags() ),
new NDCB
("Gravity", Color.red , e -> gravityToggle())
} ;
static {
try {
javax.swing.UIManager.setLookAndFeel(
javax.swing.UIManager.getCrossPlatformLookAndFeelClassName() );
} catch
(Exception e) {
e.printStackTrace();
} } // static initializer - this
seems to not work in constructor because jbList as instance vars??
public Main () {
JOptionPane.showMessageDialog (null, copyrightNotice + "\nVersion:
" + version);
JPanel pControls = new
JPanel ();
pControls.setLayout(new
GridLayout (0, 5));
for (JButton jb: jbList)
pControls.add(jb);
add (pControls,
BorderLayout.SOUTH);
tm = new Timer (10, e ->
moveBalls());
tm.start();
int isd = (int)INITIALSPEED
/ 2;
speedS = new JSlider
(JSlider.HORIZONTAL, 0, 4*isd, 2*isd);
speedS.setBackground(Color.yellow);
speedS.setMajorTickSpacing(5);
speedS.setMinorTickSpacing(1);
speedS.setPaintLabels(true);
speedS.setPaintTicks(true);
speedS.setSnapToTicks(true);
// add labels to the slider
Dictionary <Integer,
JLabel> sliderLabels = new Hashtable <Integer, JLabel>
();
sliderLabels.put
( 0, new JLabel("0"));
sliderLabels.put (
isd, new JLabel("0.25"));
sliderLabels.put (2*isd, new
JLabel("1"));
sliderLabels.put (3*isd, new
JLabel("2"));
sliderLabels.put (4*isd, new
JLabel("4"));
speedS.setLabelTable(sliderLabels);
speedS.addChangeListener(this::setSpeed);
pControls.add (new JLabel
("Speed", SwingConstants.CENTER));
pControls.add (speedS);
validate ();
}
// end constructor
void setSpeed (ChangeEvent e) {
double s =
((JSlider)e.getSource()).getValue() / INITIALSPEED;
speed = s*s; }
// end method setSpeed
public void removeBall () {
try {
Ball x =
balls.pop();
box.remove(x);
Ball.count--;
repaint
();
}
catch (EmptyStackException
ex) {} }
// end method removeBall
public boolean showLabel () {return
showNumberFlag;} public double getGravity () {return
gravity;} public double getSpeed
() {return speed;}
public static void main(String[] args) {
new Main (); }
// end main
} //
end class Main
class NDCB extends JButton implements ActionListener {
public static final long serialVersionUID =
123; // ND: junk
java.util.function.Consumer<ActionEvent>
func;
public NDCB (String st, Color c,
java.util.function.Consumer<ActionEvent> f) {
super (st);
setBackground (c);
func = f;
addActionListener (this); }
// end constructor
public void actionPerformed (ActionEvent
e) {
func.accept(e); } // end method actionPerformed
} //
end class NDCB
File: BallOwner.java
// File: BallOwner.java
// Date: Jul 30, 2010
// Author: Nicholas Duchon
// Purpose: allow communications between Balls and their owner
public interface BallOwner {
public boolean showLabel ();
public double getGravity ();
public double getSpeed ();
} // end BallOwner interface
File: Ball.java
// File: Ball.java
// Date: Jul 27, 2010
// Author: Nicholas Duchon
// Purpose: physics of balls
public class Ball extends JComponent {
public static final long serialVersionUID =
123; // ND: junk
final static double MAXV = 5;
final static int MAXD = 40, MIND = 10;
static int count = 0;
BallOwner owner = null;
int index;
String indexString;
double xr, yr, dx, dy, dz;
int xString, yString;
Color color = Color.red;
public Ball (Random rn, JComponent pc,
BallOwner bo) {
Rectangle bx =
pc.getBounds();
int rad = rn.nextInt(MAXD) +
MIND;
xr = rn.nextDouble() *
(bx.width - bx.x - rad)+ bx.x;
yr = rn.nextDouble() *
(bx.height - bx.y - rad)+ bx.y;
shake (rn);
color =
Color.getHSBColor(rn.nextFloat(), 1, 1);
this.setBounds((int)(xr+0.5), (int)(yr+0.5), rad, rad);
commonInit(bo); }
// create random Ball
public Ball (int ix, int iy, int iw, int
ih, double idx, double idy, BallOwner bo) {
this.setBounds(ix, iy, iw,
ih);
xr = ix; yr = iy;
dx = idx; dy = idy;
// System.out.printf ("init:
Bounds: %d, %d, %d, %d\n", getX(), getY(), getWidth(),
getHeight());
commonInit (bo); }
// end 4-int constructor
//tm = new Timer (10, new ActionListener () {
//public void actionPerformed (ActionEvent e) {
//} // end method action performed
//} // end anonymous class definition
//); // end parameter for Timer Constructor