Local SpritesTourSprite offers a simplified interface for moving and rotating a local sprite. It communicates movements, rotations, and its initial creation to the server. The complete class appears in Example 32-1. Example 32-1. The TourSprite classpublic class TourSprite extends Sprite3D { private final static double MOVERATE = 0.3; private final static double ROTATE_AMT = Math.PI / 16.0; PrintWriter out; // for sending commands to the server public TourSprite(String userName, String fnm, Obstacles obs, double xPosn, double zPosn, PrintWriter o) { super(userName, fnm, obs); setPosition(xPosn, zPosn); out = o; out.println("create " + userName + " " + xPosn + " " + zPosn); } // moves public boolean moveForward( ) { out.println("forward"); return moveBy(0.0, MOVERATE); } public boolean moveBackward( ) { out.println("back"); return moveBy(0.0, -MOVERATE); } public boolean moveLeft( ) { out.println("left"); return moveBy(-MOVERATE,0.0); } public boolean moveRight( ) { out.println("right"); return moveBy(MOVERATE,0.0); } // rotations in Y-axis only public void rotClock( ) { out.println("rotClock"); doRotateY(-ROTATE_AMT); // clockwise } public void rotCounterClock( ) { out.println("rotCClock"); doRotateY(ROTATE_AMT); // counter-clockwise } } // end of TourSprite Creating a Local SpriteWrapNetTour3D creates a local sprite by invoking a TourSprite object and adding it to the scene graph. As part of TourSprite's construction, a create n x z message is sent to the server; n is its client's name, and (x, z) is its position on the XZ plane. The pattern of communication following on from the sending of the "create" message is shown by the activity diagram in Figure 32-6. Figure 32-6. Creating a local spriteThe create message must be broadcast by the server to all the other current clients, as represented by the message labeled 2' in Figure 32-6. The new client must populate its copy of the world with distributed sprites representing the other users. This task is started by the server sending a wantDetails message to all the other clients (message 2), which triggers a series of detailsFor replies (message 3) passed back to the new client as messages of type 4. The reception of the "create" and "wantDetails" messages in the other clients are handled by their TourWatcher threads and TourWatcher in the new client deals with the "detailsFor" replies. Each "detailsFor" message causes a distributed sprite (an object of the DistTourSprite class) to be added to the client's world. Moving and Rotating a Local SpriteEach movement and rotation of the local sprite has the side effect of sending a message to the server, as illustrated by the activity diagram in Figure 32-7. Figure 32-7. Moving/rotating a local spriteThe various messages are listed in the box in Figure 32-7; their transmission can be seen in the code for TourSprite given earlier. The server must broadcast the messages to all the other clients so the distributed sprites representing the user can be moved or rotated. The message is prefixed with the user's name before being delivered to the TourWatcher tHReads of the other clients. This permits the TourWatchers to determine which distributed sprite to affect. The Departure of a Local SpriteWhen the users want to leave the world, they will click the close box of the NetTour3D JFrame. This triggers a call to closeLink( ) in the WrapNetTour3D object: public void closeLink( ) { try { out.println("bye"); // say bye to server sock.close( ); } catch(Exception e) { System.out.println("Link terminated"); } System.exit( 0 ); } The "bye" message causes the server to notify all the other clients of the user's departure, as shown by the activity diagram in Figure 32-8. Figure 32-8. The departure of a local spriteThe TourWatcher threads for each of the clients receives a bye message and uses the name prefix to decide which of the distributed sprites should be detached from the scene graph. |