import java.awt.*; import java.awt.event.*; import java.lang.*; import java.lang.Math; public class Projectilea extends java.applet.Applet implements Runnable { Canvas oscillators; Label launchAngleLabel, vZeroLabel, aGravLabel, launchAngleS, vZeroS; TextField aGrav; Button Start, Reset; Thread runner; Scrollbar launchAnglescroll, vZeroscroll; int launchAngle, vZero, ballDiameter, index; int[] xpos, ypos = new int[102]; double[] x, y = new double[102]; double g, vInt, vIntX, vIntY, vY, dropTime, maxHeight, range, maxTime, launchA, currentX, currentY; double pi = 3.141592653589793238468; Image offscreenImg; Graphics offscreenG; boolean startFlag; boolean pauseFlag; void buildConstraints(GridBagConstraints gbc, int gx, int gy, int gw, int gh, int wx, int wy) { gbc.gridx = gx; gbc.gridy = gy; gbc.gridwidth = gw; gbc.gridheight = gh; gbc.weightx = wx; gbc.weighty = wy; } public void init() { GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints constraints = new GridBagConstraints(); setLayout(gridbag); // Initial velocity text buildConstraints(constraints, 0, 0, 1, 1, 20, 5); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.EAST; Label vZeroLabel = new Label("Initial velocity (m/s):", Label.CENTER); gridbag.setConstraints (vZeroLabel, constraints); add(vZeroLabel); // Initial velocity scrollbar label buildConstraints(constraints, 2, 0, 1, 1, 20, 0); constraints.fill = GridBagConstraints.HORIZONTAL; vZeroS = new Label("25", Label.LEFT); vZero = 25; gridbag.setConstraints (vZeroS, constraints); add(vZeroS); // Initial velocity scrollbar buildConstraints(constraints, 1, 0, 1, 1, 20, 0); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.WEST; vZeroscroll = new Scrollbar(Scrollbar.HORIZONTAL, 0, 0, 0, 100); vZeroscroll.setValue (vZero); gridbag.setConstraints (vZeroscroll, constraints); add(vZeroscroll); // launch angle text buildConstraints(constraints, 0, 1, 1, 1, 20, 5); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.EAST; Label launchAngleLabel = new Label("Launch angle (degrees):", Label.CENTER); gridbag.setConstraints (launchAngleLabel, constraints); add(launchAngleLabel); // launch angle scrollbar label buildConstraints(constraints, 2, 1, 1, 1, 20, 0); constraints.fill = GridBagConstraints.HORIZONTAL; launchAngleS = new Label("45", Label.LEFT); launchAngle = 45; gridbag.setConstraints (launchAngleS, constraints); add(launchAngleS); // launch angle scrollbar buildConstraints(constraints, 1, 1, 1, 1, 20, 0); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.WEST; launchAnglescroll = new Scrollbar(Scrollbar.HORIZONTAL, 0, 0, 0, 90); launchAnglescroll.setValue (launchAngle); gridbag.setConstraints (launchAnglescroll, constraints); add(launchAnglescroll); // g label buildConstraints(constraints, 0, 2, 1, 1, 20, 5); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.EAST; Label labelk = new Label("Acceleration due to gravity (between 0.1 and 100 m/s^2):", Label.RIGHT); gridbag.setConstraints (labelk, constraints); add(labelk); // k textbox buildConstraints(constraints, 1, 2, 1, 1, 0, 0); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.CENTER; aGrav = new TextField("9.8", 6); g = 9.8; gridbag.setConstraints (aGrav, constraints); add(aGrav); // Start button buildConstraints(constraints, 0, 3 , 1, 1, 0, 10); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.EAST; Start = new Button(" Start "); gridbag.setConstraints (Start, constraints); add(Start); // Reset button buildConstraints(constraints, 1, 3 , 1, 1, 0, 10); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.WEST; Reset = new Button("Reset"); gridbag.setConstraints (Reset, constraints); add(Reset); // canvas buildConstraints(constraints, 0, 4, 3, 1, 0, 80); constraints.fill = GridBagConstraints.HORIZONTAL; oscillators = new Canvas(); gridbag.setConstraints (oscillators, constraints); add(oscillators); offscreenImg = createImage(this.size().width, this.size().height); offscreenG = offscreenImg.getGraphics(); } public void start() { if (runner == null); { runner = new Thread(this); runner.start(); } } public void stop() { if (runner != null) { runner.stop(); runner = null; } } public void run() { double deltat, junk, xScale, yScale, scale, xOrigin, yOrigin, kAngle; Double temp; deltat=0.1; ballDiameter = 15; kAngle = pi/180.0; yOrigin = 380.0; xOrigin = 20.0; currentX = 0.0; currentY = 0.0; while (true) { startFlag = false; pauseFlag = false; index = 0; dropTime = 0.0; vInt = vZero; launchA = launchAngle*kAngle; x[0] = xOrigin-ballDiameter; xpos[0] = (int)(x[0]); y[0] = yOrigin-ballDiameter; ypos[0] = (int)(y[0]); temp = Double.valueOf(aGrav.getText()); g = temp.doubleValue(); if (g < 0.1) g = 0.1; if (g > 100.0) g = 100.0; g = -g; vIntX = vInt*Math.cos(launchA); vIntY = vInt*Math.sin(launchA); maxHeight = -0.5*vIntY*vIntY/g; maxTime = -2.0*vIntY/g; range = vIntX*maxTime; xScale = 180.0/range; yScale = 160.0/maxHeight; scale = xScale; if (yScale < xScale) scale = yScale; if (maxTime > 10.0) deltat = (1.0+math.trunc(maxTime/10))/10.0; while (pauseFlag) { while (startFlag) { index = index +1; dropTime = dropTime + deltat; currentX = vIntX*dropTime; x[index] = x[0]+scale*currentX; currentY = dropTime*(vIntY+0.5*g*dropTime); y[index] = y[0]-scale*currentY; vY = vIntY+g*dropTime; if (y[index]>y[0]) { currentX = range; x[index] = x[0]+scale*range; currentY = 0.0; y[index] = y[0]; vY = -vIntY; dropTime = maxTime; startFlag = false; pauseFlag = true; } xpos[index] = (int)(x[index]); ypos[index] = (int)(y[index]); repaint(); try { Thread.sleep(300); } catch (InterruptedException e) { } } } repaint(); try { Thread.sleep(3); } catch (InterruptedException e) { } } } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { int i; // Draw background offscreenG.setBackground(Color.lightGray); offscreenG.setColor(Color.white); offscreenG.fillRect(0,200,400,400); // Draw mass offscreenG.setColor(Color.black); offscreenG.drawLine(10, 380, 200, 380); offscreenG.setColor(Color.blue); for (i=0, i<=index, i++) { offscreenG.fillOval(xpos[i],ypos[i],ballDiameter,ballDiameter); } offscreenG.drawString("Positive x = right and y = up", 200, 220); offscreenG.drawString("X = " + currentX + " m", 200, 240); offscreenG.drawString("Y = " + currentY + " m", 200, 260); offscreenG.drawString("Vx = " + vIntX + " m/s", 200, 280); offscreenG.drawString("Vy = " + vY + " m/s", 200, 300); offscreenG.drawString("Time = " + dropTime + " s", 200, 320); offscreenG.drawString("Maximum height = " + maxHeight + " m", 200, 340); offscreenG.drawString("Range = " + range + " m", 200, 360); offscreenG.drawString("Total time = " + maxTime + " s", 200, 380); g.drawImage(offscreenImg,0,0,this); } public void destroy() { offscreenG.dispose(); } public boolean action (Event evt, Object arg) { if (evt.target instanceof Button) { if ((Button)evt.target == Reset) { startFlag = false; pauseFlag = false; Start.setLabel(" Start "); } else if ((Button)evt.target == Start) { if (Start.getLabel().equals(" Start ")) { startFlag = true; pauseFlag = true; Start.setLabel("Pause"); } else { startFlag = false; pauseFlag = true; Start.setLabel(" Start "); } } } else return super.action(evt, arg); return true; } public boolean handleEvent(Event evt) { if (evt.target instanceof Scrollbar) { if ((Scrollbar)evt.target == launchAnglescroll) { launchAngle = ((Scrollbar)evt.target).getValue(); launchAngleS.setText(String.valueOf(launchAngle)); } else if ((Scrollbar)evt.target == vZeroscroll) { vZero = ((Scrollbar)evt.target).getValue(); vZeroS.setText(String.valueOf(vZero)); } repaint(); } else return super.handleEvent(evt); return true; } }