// Name: Anita Blake Partner: Ted Forrester // ID: 014916 ID: 642708 // Sec: Yan T 2:30 Sec: Artemov R 1:25 // Date: March 30, 2000 // Project 5: Following the Bouncing Ball import java.text.DecimalFormat; import java.awt.*; /* changes from core solution: class Molecule + make all instance variables $private$ + use $World.getsize()$ instead of $World.size$ + use $World.getStep()$ instead of $World.step$ + use $World.hitTop(momentum)$ instead of $world.hit += momentum$ class World: + make all instance variables $private$ + use $Molecule[] m$ instead of $Molecule m1, m2, m3$ + define getters $getsize$ and $getStep$ + define setter $hitTop$ + add parameter $n$ to constructor $World$: number of copies of each kind of Molecule + use loops over $m$ in constructor $World$ and methods $paint$ and $move$; observe the nested loop for testing collisions between each pair of Molecules *once* + define method $drawStats$ to draw instead of print statistics class Stats: separate window for drawing instead of printing statistics class Project5: + ask for 20 of each kind of Molecule when instantiating World + instantiate Stats window + call $drawStats$ instead of $printStats$ */ // a Molecule moving around in a World class Molecule { private double mass; // mass private double px, py; // (px,py) = position of the center private double vx, vy; // (vx,vy) = velocity private double radius; // radius private Color color; // color private World world; // World where the molecule "lives" // create a molecule of color c, mass m, radius r, world w; // place randomly in the world, // with random velocity |vx|, |vy| <= maxv = 5 Molecule(Color c, int m, int r, World w) { double maxv = 5; // maximum magnitude of vx, vy mass = m; radius = r; color = c; world = w; px = r + Math.random() * (w.getsize() - 2.0 * r); py = r + Math.random() * (w.getsize() - 2.0 * r); vx = (Math.random() * 2.0 - 1.0) * maxv; vy = (Math.random() * 2.0 - 1.0) * maxv; } // paint the molecule void paint(Graphics g) { g.setColor(color); int left = (int) (px-radius), top = (int) (py-radius); int diameter = (int) (2.0*radius); g.fillOval(left, top, diameter, diameter); } // move the molecule one time step void move() { px += vx * world.getStep(); py += vy * world.getStep(); double wmin = radius; // topmost, leftmost walls double wmax = world.getsize() - radius; // bottommost, rightmost walls // bounce off walls if (px <= wmin) { px = 2.0 * wmin - px; vx = -vx; } else if (px >= wmax) { px = 2.0 * wmax - px; vx = -vx; } if (py <= wmin) { py = 2.0 * wmin - py; vy = -vy; world.hitTop(2.0 * mass * vy); } else if (py >= wmax) { py = 2.0 * wmax - py; vy = -vy; } } // check for collision with m and update velocities if so void collide(Molecule m) { double dt = world.getStep(); // size of time step // variable definitions: named to match write-up double x1 = px, y1 = py; // center of self double x2 = m.px, y2 = m.py; // center of m double vx1 = vx, vy1 = vy; // velocity of self double vx2 = m.vx, vy2 = m.vy; // velocity of m double r = radius, r2 = m.radius; // radii of self, m double m1 = mass, m2 = m.mass; // mass of self, m // if extents don't overlap, then there is no collision if (x1+Math.max(0,vx1)*dt+r < x2+Math.min(0,vx2)*dt-r2 || x1+Math.min(0,vx1)*dt-r > x2+Math.max(0,vx2)*dt+r2 || y1+Math.max(0,vy1)*dt+r < y2+Math.min(0,vy2)*dt-r2 || y1+Math.min(0,vy1)*dt-r > y2+Math.max(0,vy2)*dt+r2 ) return; // ok, (assume) there is a collision: // update velocities according to formula from write-up double fx = x2 - x1, fy = y2 - y1; double s = 2.0 * (fx * (vx2-vx1) + fy * (vy2 - vy1)) / ((fx * fx + fy * fy) * (1.0 / m1 + 1.0 / m2)); vx += (s/m1) * fx; vy += (s/m1) * fy; m.vx -= (s/m2) * fx; m.vy -= (s/m2) * fy; } // return kinetic energy double energy() { return 0.5 * mass * (vx*vx + vy*vy); } } // a World is a square container containing Molecules class World extends Frame { private double step = 0.5; // the length of time of each time step private double size; // width=height of container private double hit = 0.0; // cumulative vertical momentum applied to the top wall private double time = 0.0; // elapsed time from start of simulation private double P; // pressure private double V; // area (not volume) private double N; // number of molecules private double T; // temperature measured as average kinetic energy private Molecule[] m; // molecules in the world // getters for instance variables double getsize() { return size; } double getStep() { return step; } // add momentum p to hit void hitTop(double p) { hit += p; } // create a new world of size s with n of each kind of Molecule public World(int s, int n) { size = s; V = size*size; N = 3*n; int j = 0;// # of molecules so far m = new Molecule[(int) N]; for (int i = 0; i < n; i++) { m[j] = new Molecule(Color.red, 1, 4, this); j++; m[j] = new Molecule(Color.green, 4, 5, this); j++; m[j] = new Molecule(Color.blue, 16, 7, this); j++; } show(); // show; apparently needed to getInsets setSize(getInsets().left+getInsets().right+(int)size, getInsets().top+getInsets().bottom+(int)size); setBackground(Color.white); } // move each Molecule one time step public void move() { for (int i = 0; i