<< Chapter < Page Chapter >> Page >

Listing 32 . Source code for the program named GM01test04.

/*GM01test04.java Copyright 2008, R.G.BaldwinRevised 02/25/08. This animation program is designed to test many of the 2Dfeatures of the GM01 game-math library. The animation is generally based on the idea of a flocking behavior similar to that exhibited by birds.A set of Point2D objects is created with random locations. An additional Point2D object known at the target is alsocreated. The target is drawn in red while the pursuers are drawn in black.An algorithm is executed that attempts to cause the points to chase the target without colliding with one another.Even though the algorithm causes the points to chase the target, it also tries to keep the points from collidingwith the target. A GUI is provided that contains an input text field forthe number of points plus a Start button and a Stop button. The GUI also contains check boxes that allow theuser to elect to display points only, direction vectors only, or both. (The point and the direction vector isalways displayed for the target.) The user specifies the number of randomly-placed pointsand clicks the Start button, at which time the animation begins and the points start chasing the target. Targetmotion is random. The animation continues until the user clicks the Stop button. The user can click the Stopbutton, change the number of points, and then click Start again to re-start the animation with a different numberof points chasing the target. The algorithm seems to cause the points to come togetherand fly in formation while chasing the target. The most common formation is hexagonal but sometimes triangles andincomplete hexagons also appear. I have no explanation for this behavior. The tendency to fly in formation is morevisually obvious when only the points are displayed. On the other hand, the animation is most impressive whenthe direction vectors are displayed, with or without points, because the vectors illustrate the doggeddetermination and undying focus that the pursuers maintain while chasing the target.Tested using JDK 1.6 under WinXP. *********************************************************/import java.awt.*; import javax.swing.*;import java.awt.geom.*; import java.awt.event.*;import java.util.*; class GM01test04{public static void main(String[] args){GUI guiObj = new GUI(); }//end main}//end controlling class GM01test04 //======================================================//class GUI extends JFrame implements ActionListener{ int hSize = 400;//horizontal size of JFrame.int vSize = 400;//vertical size of JFrame Image osi;//an off-screen imageint osiWidth;//off-screen image width int osiHeight;//off-screen image heightMyCanvas myCanvas;//a subclass of Canvas Graphics2D g2D;//off-screen graphics context.int numberPoints = 0;//can be modified by the user. JTextField numberPointsField; //user input field.Random random = new Random();//random number generator //The following collection is used to store the points.ArrayList<GM01.Point2D>points;//The following collection is used to store the vectors // for display.ArrayList<GM01.Vector2D>vectors;//The following are used to support user input. Checkbox drawPointsBox;//User input fieldCheckbox drawVectorsBox;//User input field. boolean drawPoints = true;boolean drawVectors = true;//Animation takes place while the following is true. boolean animate = false;//----------------------------------------------------//GUI(){//constructor//Set JFrame size, title, and close operation. setSize(hSize,vSize);setTitle("Copyright 2008,R.G.Baldwin"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//Instantiate the user input components.numberPointsField =new JTextField("6",5); JButton startButton = new JButton("Start");JButton stopButton = new JButton("Stop"); drawPointsBox = new Checkbox("Draw Points",true);drawVectorsBox = new Checkbox("Draw Vectors",true); //Instantiate a JPanel that will house the user input// components and set its layout manager. JPanel controlPanel = new JPanel();controlPanel.setLayout(new GridLayout(0,2)); //Add the user input component and appropriate labels// to the control panel. controlPanel.add(new JLabel(" Number Points"));controlPanel.add(numberPointsField); controlPanel.add(drawPointsBox);controlPanel.add(drawVectorsBox); controlPanel.add(startButton);controlPanel.add(stopButton); //Add the control panel to the SOUTH position in the// JFrame. this.getContentPane().add(BorderLayout.SOUTH,controlPanel); //Instantiate a new drawing canvas and add it to the// CENTER of the JFrame above the control panel. myCanvas = new MyCanvas();this.getContentPane().add( BorderLayout.CENTER,myCanvas);//This object must be visible before you can get an // off-screen image. It must also be visible before// you can compute the size of the canvas. setVisible(true);//Make the size of the off-screen image match the// size of the canvas. osiWidth = myCanvas.getWidth();osiHeight = myCanvas.getHeight(); //Create an off-screen image and get a graphics// context on it. osi = createImage(osiWidth,osiHeight);g2D = (Graphics2D)(osi.getGraphics());//Translate the origin to the center. GM01.translate(g2D,0.5*osiWidth,-0.5*osiHeight);//Register this object as an action listener on the// startButton and the stopButton startButton.addActionListener(this);stopButton.addActionListener(this);}//end constructor //----------------------------------------------------////This method is called to respond to a click on the// startButton or the stopButton. public void actionPerformed(ActionEvent e){if(e.getActionCommand().equals("Start")&&!animate){ numberPoints = Integer.parseInt(numberPointsField.getText()); if(drawPointsBox.getState()){drawPoints = true; }else{drawPoints = false; }//end elseif(drawVectorsBox.getState()){drawVectors = true; }else{drawVectors = false; }//end elseanimate = true; new Animate().start();}//end ifif(e.getActionCommand().equals("Stop")&&animate){ //This will cause the run method to terminate and// stop the animation. animate = false;}//end if }//end actionPerformed//====================================================////This is an inner class of the GUI class. class MyCanvas extends Canvas{//Override the update method to eliminate the default // clearing of the Canvas in order to reduce or// eliminate the flashing that that is often caused by // such default clearing.//In this case, it isn't necessary to clear the canvas // because the off-screen image is cleared each time// it is updated. This method will be called when the // JFrame and the Canvas appear on the screen or when// the repaint method is called on the Canvas object. public void update(Graphics g){paint(g);//Call the overridden paint method. }//end overridden update()//Override the paint() method. The purpose of the// paint method is to display the off-screen image on // the screen. This method is called by the update// method above. public void paint(Graphics g){g.drawImage(osi,0,0,this); }//end overridden paint()}//end inner class MyCanvas //====================================================////This is an animation thread.class Animate extends Thread{ //Declare a general purpose variable of type Point2D.// It will be used for a variety of purposes. GM01.Point2D tempPoint;//Declare a general purpose variable of type Vector2D.// It will be used for a variety of purposes. GM01.Vector2D tempVector;public void run(){//This method is executed when start is called on // this thread.//Create a new empty container for the points. points = new ArrayList<GM01.Point2D>();//Create a new empty container for the vectors.vectors = new ArrayList<GM01.Vector2D>();//Create a set of Point objects at random locations // and store references to the points in the// ArrayList object.. for(int cnt = 0;cnt<numberPoints;cnt++){ points.add(new GM01.Point2D(new GM01.ColMatrix2D( 100*(random.nextDouble()-0.5),100*(random.nextDouble()-0.5))));//Populate vectors collection with dummy vectors. vectors.add(tempVector);}//end for loop //Create a Point2D object that will be the target// that will be chased by the other Point2D objects. GM01.Point2D target = new GM01.Point2D(new GM01.ColMatrix2D( 100*(random.nextDouble()-0.5),100*(random.nextDouble()-0.5)));//Create a Vector2D object that will be used to // control the motion of the target.GM01.Vector2D targetVec = new GM01.Vector2D( new GM01.ColMatrix2D(100*(random.nextDouble()-0.5), 100*(random.nextDouble()-0.5))).scale(0.3);//Create a reference point to mark the origin. GM01.Point2D zeroPoint =new GM01.Point2D(new GM01.ColMatrix2D(0,0)); //Declare a variable that will be used to control// the update frequency of the target vector. int animationLoopCounter = 0;//This is the animation loop. The value of animate// is set to true by the Start button and is set to // false by the Stop button. Setting it to false// will cause the run method to terminate and stop // the animation.while(animate){ animationLoopCounter++;//Try to keep the points from colliding with one// another. Note, however, that this algorithm // is far from perfect in accomplishing that.for(int row = 0;row<points.size();row++){ for(int col = 0;col<points.size();col++){ GM01.Point2D refPoint = points.get(row);GM01.Point2D testPoint = points.get(col);if(col != row){ //Get the distance of the testPoint from the// refPoint. tempVector = testPoint.getDisplacementVector(refPoint);if(tempVector.getLength()<25){ //Modify testPoint to move it away from// the refPoint and save the modified // point.tempVector = tempVector.negate(); tempPoint = testPoint.addVectorToPoint(tempVector.scale(0.1)); points.set(col,tempPoint.clone());}else{ //Do nothing.}//end else }//end if col != row}//end loop on col }//end loop on row//Move all of the points toward the target but try // to keep them separated from the target.for(int cnt = 0;cnt<points.size();cnt++){ //Get the next point.tempPoint = points.get(cnt); //Find the distance from this point to the// target. tempVector =tempPoint.getDisplacementVector(target); if(tempVector.getLength()<10){ //Modify the point to move it away from the// target and save the modified point. tempVector = tempVector.negate();tempPoint = tempPoint.addVectorToPoint( tempVector.scale(0.1));//Save the modified point. points.set(cnt,tempPoint.clone());}else{ //Modify the point to move it toward the// target and save the modified point. tempPoint = tempPoint.addVectorToPoint(tempVector.scale(0.1)); points.set(cnt,tempPoint.clone());}//end else//Save a normalized version of the direction // vector for drawing later.vectors.set( cnt,tempVector.normalize().scale(15.0));}//end for loop//Insert a delay.try{ Thread.currentThread().sleep(166);}catch(Exception e){ e.printStackTrace();}//end catch//Erase the screen g2D.setColor(Color.WHITE);GM01.fillRect(g2D,-osiWidth/2,osiHeight/2, osiWidth,osiHeight);g2D.setColor(Color.BLACK);//Draw the points and the vectors in the arrayList // objects.for(int cnt = 0;cnt<numberPoints;cnt++){ tempPoint = points.get(cnt);if(drawPoints){ tempPoint.draw(g2D);}//end ifif(drawVectors){ tempVector = vectors.get(cnt);tempVector.draw(g2D,tempPoint); }//end if}//end for loop//Cause the targets movements to be slightly less// random by using the same vector for several // successive movementsif(animationLoopCounter%10 == 0){ //Get a new vectortargetVec = new GM01.Vector2D( new GM01.ColMatrix2D(100*(random.nextDouble()-0.5), 100*(random.nextDouble()-0.5))).scale(0.3);}//else use the same vector again.//Test to see if this displacement vector will // push the target outside the limit. If so,// modify the vector to send the target back // toward the origin.if(target.getDisplacementVector(zeroPoint). getLength()>0.4*osiWidth){ targetVec = target.getDisplacementVector(zeroPoint).scale(0.1); }//end if//Modify the location of the target point.target = target.addVectorToPoint(targetVec);//Set the color to RED and draw the target and its // vector.g2D.setColor(Color.RED); target.draw(g2D);targetVec.normalize().scale(15.0).draw( g2D,target);g2D.setColor(Color.BLACK);myCanvas.repaint();}//end while loop }//end run}//end inner class named Animate //====================================================//}//end class GUI

Get Jobilize Job Search Mobile App in your pocket Now!

Get it on Google Play Download on the App Store Now




Source:  OpenStax, Game 2302 - mathematical applications for game development. OpenStax CNX. Jan 09, 2016 Download for free at https://legacy.cnx.org/content/col11450/1.33
Google Play and the Google Play logo are trademarks of Google Inc.

Notification Switch

Would you like to follow the 'Game 2302 - mathematical applications for game development' conversation and receive update notifications?

Ask