import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.awt.geom.*; public class Base extends JApplet implements Runnable, MouseListener, ComponentListener { //Thanks, Mr. Fry public static final String javaVersionName = System.getProperty("java.version").substring(0,3); public static final float javaVersion = new Float(javaVersionName).floatValue(); Random generator = new Random(); Image offScreenImage; int width, height; int i = 0; Thread t = null; boolean threadSuspended; Font waterFont = new Font("serif", Font.PLAIN, 20); Vector traffic; Car staller = null; float incidentLoc =0; boolean mousePressed = false; sgSlider carPower = new sgSlider("Car Power",0,100,15); sgSlider trafficRate = new sgSlider("Traffic Rate",0,40,15); JPanel display = new JPanel(); JPanel controls = new JPanel(); public void init() { System.out.println("Init"); addMouseListener(this); addComponentListener(this); traffic = new Vector(); traffic.add(new Car(.15f)); controls.setLayout(new BorderLayout()); controls.add(carPower,"West"); controls.add(trafficRate,"East"); getContentPane().add(display,BorderLayout.CENTER); getContentPane().add(controls,BorderLayout.SOUTH); System.out.println(traffic); } public void destroy() { } public void start() { System.out.println("Start"); if ( t == null ) { t = new Thread( this ); threadSuspended = false; t.start(); } else { if ( threadSuspended ) { threadSuspended = false; synchronized( this ) { notify(); } } } } public void stop() { threadSuspended = true; } // Executed within the thread that this applet created. public void run() { try { while (true) { // Now the thread checks to see if it should suspend itself if ( threadSuspended ) { synchronized( this ) { while ( threadSuspended ) { wait(); } } } update(display.getGraphics()); t.sleep( 1000/30 ); // interval given in milliseconds } } catch (InterruptedException e) { } } public void paint( Graphics g ) { if (javaVersion < 1.5f) { //System.out.println("monkey"); } width = getSize().width; height = getSize().height; Graphics2D g2d = (Graphics2D)g; g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); int mid = height/2; g2d.setPaint(new Color(70,130,60)); g2d.fill(new Rectangle2D.Double(0, 0,width, height)); //gravel g2d.setPaint(new Color(100,100,100)); g2d.fillRect(0, mid-20,width, 40); //yellow striping g2d.setPaint(new Color(230,230,0)); g2d.drawRect(0,mid-13,width,26); //asphalt g2d.setPaint(new Color(80,80,80)); g2d.fill(new Rectangle2D.Double(0,mid-12,width,24)); //striping g2d.setPaint(Color.white); for (int i =0; i*7 < width; i++){ g2d.fill(new Rectangle2D.Double(i*7, mid-1,4,2)); } //watermark g2d.setColor(new Color(1.0f,1.0f,1.0f,.5f)); g2d.setFont(waterFont); //g2d.drawString("screamyGuy.net",width-140,height-10); //cars //randomly add cars if (generator.nextDouble() < trafficRate.getValue()/100.0f){ //check for existing backup if (((Car)traffic.elementAt(traffic.size()-1)).x > 0){ traffic.add(new Car(carPower.getValue()/100.f)); } } //draw the lead car Car curr = (Car)traffic.elementAt(0); curr.draw(null, this, g2d); //halt one of them if (mousePressed){ if (staller == null){ staller = (Car)traffic.elementAt(1); staller.distracted = true; incidentLoc = staller.x; } else{ staller.distracted = true; } } else{ if (!(staller == null)) staller = null; } //update all of the traffic for (int i = 1; i < traffic.size(); i++){ curr = (Car)traffic.elementAt(i); curr.draw((Car)traffic.elementAt(i-1), this,g2d); } //remove offscreen cars for (int i = 0; i < traffic.size(); i++){ curr = (Car)traffic.elementAt(i); if (curr.x > width + 30) traffic.remove(i); } if (incidentLoc !=0 ){ g2d.setPaint(new Color(255,255,255,100)); g2d.fillRect((int)incidentLoc, mid-20,20,40); } controls.repaint(); } static public void main(String [] argv){ Base smonkaroni = new Base(); JFrame frame = new JFrame("Blarg!"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(smonkaroni); frame.setSize(600,200); frame.setVisible(true); smonkaroni.init(); smonkaroni.start(); frame.setSize(600,200); } public void mousePressed(MouseEvent e) { mousePressed = true; } public void mouseReleased(MouseEvent e) { mousePressed = false; } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mouseClicked(MouseEvent e) { } //perform double buffering manually public void update( Graphics g ){ if ( offScreenImage == null){ offScreenImage = createImage( getSize().width, getSize().height ); } Graphics gOffScreenImage = offScreenImage.getGraphics(); //Now draw on the offscreen image. paint( gOffScreenImage ); g.drawImage(offScreenImage, 0, 0, this); gOffScreenImage.dispose(); } public void componentResized(ComponentEvent e) { offScreenImage = null; } public void componentMoved(ComponentEvent e) { } public void componentShown(ComponentEvent e) { } public void componentHidden(ComponentEvent e) { } } class Car{ Random generator = new Random(); float x,y; float dx = 6; float dx2 = 0; float trailing = 25; float maxVel = 6.5f; float maxAccel = .15f; boolean distracted = false; public Car(float maxAccel){ y = 3; x = -20; this.maxAccel = maxAccel; } public void draw(Car next, Base can, Graphics2D g){ if (distracted) g.setPaint(new Color(255,0,0)); else g.setPaint(new Color(220,220,250)); g.fillRect((int)x,(int)(y + can.height/2),10,7); g.setColor(Color.black); g.drawRect((int)x,(int)(y + can.height/2),10,7); //even though we use P and D, this is not a PD controller! //Here, we have access to some variables that are not //available in real life. if (next != null){ float P = next.x - trailing - x; float D = next.dx - dx; dx2 = P/7 + D/8; } if (dx2 > maxAccel) dx2 = maxAccel; dx += dx2; //cars top speed limited if (dx > maxVel) dx = maxVel; if (distracted){ dx -= 2; distracted = false; } //cars not allowed to reverse if (dx < 0) dx = 0; x += dx; } } class sgSlider extends JPanel{ JLabel label; JSlider slider; int min,max; JPanel area; public sgSlider(String label, int min, int max, int value){ this.label = new JLabel(label); slider = new JSlider(min,max,value); add(this.label); add(slider); } public int getValue(){ return slider.getValue(); } }