<< Chapter < Page Chapter >> Page >

Listing 33 . Source code for the program named GM01test03.

/*GM01test03.java Copyright 2008, R.G.BaldwinRevised 02/25/08. This is a 3D update from the 2D version named GM01test04.Basically all that was required to perform the update was to specify 3D classes from the game-math library in placeof the 2D classes used in the 2D version. Virtually everything else took care of itself.The visual behavior of this 3D version is more realistic than the 2D version. This is particularly true when thetarget gets in the middle of the pursuers and the display is showing both points and vectors. In this 3D version,a pursuer is free to swing around in any plane as the target passes by whereas in the 2D version, a pursuer isconstrained to swing around only in the plane of the screen. That causes the motion to be less fluid. This isbest demonstrated with only one pursuer because that makes it easy to see the behavior of an individual pursuer.One thing that I did notice, is that unlike the 2D version, the pursuers in this 3D version don't seem tohave a tendency to form up and fly in formation while chasing the target. This may be because they have moreoptions in terms of avoiding collisions while giving chase, but that is pure speculation since I don't knowwhy they tend to fly in formation in the 2D version.This animation program is designed to test many of the 3D features 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 Point3D objects is created with random locations. An additional Point3D 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. (Both the point and the direction vectorare always 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 animation is most impressive when the directionvectors are displayed, with or without points, because the vectors illustrate the dogged determination and undyingfocus 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 GM01test03{ public static void main(String[]args){ GUI guiObj = new GUI();}//end main }//end controlling class GM01test03//======================================================// class GUI extends JFrame implements ActionListener{int hSize = 400;//horizontal size of JFrame. int vSize = 400;//vertical size of JFrameImage osi;//an off-screen image int osiWidth;//off-screen image widthint osiHeight;//off-screen image height MyCanvas myCanvas;//a subclass of CanvasGraphics2D 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.Point3D>points;//The following collection is used to store the vectors // for display.ArrayList<GM01.Vector3D>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 stopButtonstartButton.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 Point3D.// It will be used for a variety of purposes. GM01.Point3D tempPoint;//Declare a general purpose variable of type Vector3D.// It will be used for a variety of purposes. GM01.Vector3D 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.Point3D>();//Create a new empty container for the vectors. vectors = new ArrayList<GM01.Vector3D>();//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.Point3D(new GM01.ColMatrix3D( 100*(random.nextDouble()-0.5),100*(random.nextDouble()-0.5), 100*(random.nextDouble()-0.5))));//Populate vectors collection with dummy vectors.vectors.add(tempVector); }//end for loop//Create a Point3D object that will be the target // that will be chased by the other Point3D objects.GM01.Point3D target = new GM01.Point3D( new GM01.ColMatrix3D(100*(random.nextDouble()-0.5), 100*(random.nextDouble()-0.5),100*(random.nextDouble()-0.5)));//Create a Vector3D object that will be used to // control the motion of the target.GM01.Vector3D targetVec = new GM01.Vector3D( new GM01.ColMatrix3D(100*(random.nextDouble()-0.5), 100*(random.nextDouble()-0.5),100*(random.nextDouble()-0.5))).scale(0.3); //Create a reference point to mark the origin.GM01.Point3D zeroPoint = new GM01.Point3D(new GM01.ColMatrix3D(0,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. for(int row = 0;row<points.size();row++){ for(int col = 0;col<points.size();col++){ GM01.Point3D refPoint = points.get(row);GM01.Point3D 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.2)); 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 movements if(animationLoopCounter%10 == 0){//Get a new vector targetVec = new GM01.Vector3D(new GM01.ColMatrix3D (100*(random.nextDouble()-0.5),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 // displacement 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