From a1ff4ed304654dc15674539556ab23457c2c22cd Mon Sep 17 00:00:00 2001 From: Jesse Morgan Date: Thu, 17 Mar 2011 06:17:12 +0000 Subject: Remote Control and Fixed the tank. --- src/tesseract/objects/blimp/Blimp.java | 12 +- src/tesseract/objects/remote/KeyInfo.java | 20 ++++ src/tesseract/objects/remote/RemoteObject.java | 122 ++++++++++++++++++++- .../objects/remote/RemoteObjectCommunicator.java | 118 ++++++++++++++++++++ src/tesseract/objects/remote/RemoteObjectMenu.java | 24 +++- src/tesseract/objects/tank/Body.java | 2 + src/tesseract/objects/tank/Tank.java | 118 ++++++++++++-------- 7 files changed, 354 insertions(+), 62 deletions(-) create mode 100644 src/tesseract/objects/remote/KeyInfo.java create mode 100644 src/tesseract/objects/remote/RemoteObjectCommunicator.java (limited to 'src/tesseract/objects') diff --git a/src/tesseract/objects/blimp/Blimp.java b/src/tesseract/objects/blimp/Blimp.java index d4a88b5..836ef41 100644 --- a/src/tesseract/objects/blimp/Blimp.java +++ b/src/tesseract/objects/blimp/Blimp.java @@ -1,16 +1,11 @@ package tesseract.objects.blimp; -import java.awt.Color; import java.awt.event.KeyEvent; -import java.util.LinkedList; -import java.util.List; import javax.media.j3d.Appearance; -import javax.media.j3d.BranchGroup; import javax.media.j3d.ColoringAttributes; import javax.media.j3d.Geometry; import javax.media.j3d.GeometryArray; -import javax.media.j3d.Group; import javax.media.j3d.ImageComponent2D; import javax.media.j3d.Material; import javax.media.j3d.Shape3D; @@ -22,8 +17,7 @@ import javax.vecmath.Color3f; import javax.vecmath.Matrix3f; import javax.vecmath.Vector3f; -import tesseract.objects.ModifyableParticle; -import tesseract.objects.PhysicalObject; +import tesseract.objects.remote.KeyInfo; import tesseract.objects.remote.RemoteObject; import com.sun.j3d.utils.geometry.Box; @@ -36,7 +30,7 @@ import com.sun.j3d.utils.image.TextureLoader; public class Blimp extends RemoteObject { - KeyEvent lastEvent; + KeyInfo lastEvent; /** * Default mass. */ @@ -242,7 +236,7 @@ public class Blimp extends RemoteObject { * * @author Phillip Cardon, Steve Bradshaw */ - protected void keyEventReceived(final KeyEvent event) { + protected void keyEventReceived(final KeyInfo event) { lastEvent = event; Vector3f temp = new Vector3f(); Transform3D currentOrientation = new Transform3D(); diff --git a/src/tesseract/objects/remote/KeyInfo.java b/src/tesseract/objects/remote/KeyInfo.java new file mode 100644 index 0000000..844ee24 --- /dev/null +++ b/src/tesseract/objects/remote/KeyInfo.java @@ -0,0 +1,20 @@ +package tesseract.objects.remote; + +import java.io.Serializable; + +public class KeyInfo implements Serializable { + /** + * Serial UID. + */ + private static final long serialVersionUID = -1378329597453071920L; + + private int keyCode; + + public KeyInfo(int keyCode) { + this.keyCode = keyCode; + } + + public int getKeyCode() { + return keyCode; + } +} diff --git a/src/tesseract/objects/remote/RemoteObject.java b/src/tesseract/objects/remote/RemoteObject.java index e3edc1c..32f5a11 100644 --- a/src/tesseract/objects/remote/RemoteObject.java +++ b/src/tesseract/objects/remote/RemoteObject.java @@ -1,6 +1,14 @@ package tesseract.objects.remote; import java.awt.event.KeyEvent; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.Socket; +import java.net.SocketAddress; +import java.util.UUID; import javax.vecmath.Vector3f; @@ -22,16 +30,51 @@ public abstract class RemoteObject extends PhysicalObject { */ protected static final float STEP = 0.01f; + /** + * Unique object id. + */ + private UUID myId; + + /** + * The home address. + */ + private SocketAddress myHome; + + /** + * The local computer address. + */ + transient private boolean isLocal; + + /** + * The socket. + */ + transient private RemoteObjectReciever myListener; + + /** + * + * @param thePosition + * @param mass + */ public RemoteObject(Vector3f thePosition, float mass) { super(thePosition, mass); + + myId = UUID.randomUUID(); + isLocal = true; } - + + public void setHome(SocketAddress home) { + myHome = home; + + myListener = new RemoteObjectReciever(); + new Thread(myListener).start(); + } + /** * This method is called when a key event is received. * * @param event The KeyEvent recieved */ - protected void keyEventReceived(final KeyEvent event) { + protected void keyEventReceived(final KeyInfo event) { switch (event.getKeyCode()) { case KeyEvent.VK_W: velocity.z -= STEP; @@ -57,17 +100,84 @@ public abstract class RemoteObject extends PhysicalObject { * @return The object's name for the menu. */ public abstract String getName(); + + public UUID getId() { + return myId; + } /** * Send a KeyEvent to this remote object. * * @param keyEvent The key event */ - public void sendKeyEvent(final KeyEvent keyEvent) { - // TODO: Send this event over the network if necessary. + public void sendKeyEvent(final KeyInfo keyEvent) { keyEventReceived(keyEvent); - updateTranformGroup(); } - + + + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException { + in.defaultReadObject(); + + // Start Socket Thread + myListener = new RemoteObjectReciever(); + new Thread(myListener).start(); + + } + + private void writeObject(ObjectOutputStream out) + throws IOException { + out.defaultWriteObject(); + + myListener.stop(); + } + + private class RemoteObjectReciever implements Runnable { + private Socket mySocket; + + public void stop() { + try { + mySocket.close(); + + } catch (IOException e) { + } + } + + public void run() { + mySocket = new Socket(); + + try { + System.out.println("Connecting to " + myHome); + mySocket.connect(myHome); + + // Send id + DataOutputStream out = new DataOutputStream(mySocket.getOutputStream()); + out.writeLong(myId.getMostSignificantBits()); + out.writeLong(myId.getLeastSignificantBits()); + out.flush(); + + // Wait for data + DataInputStream in = new DataInputStream(mySocket.getInputStream()); + + while (true) { + try { + int key = in.readInt(); + + KeyInfo event = new KeyInfo(key); + + sendKeyEvent(event); + + } catch (Exception e) { + System.err.println("Could not read KeyEvent: " + e); + break; + } + } + + } catch (IOException e) { + System.err.println(e); + } + } + + } } diff --git a/src/tesseract/objects/remote/RemoteObjectCommunicator.java b/src/tesseract/objects/remote/RemoteObjectCommunicator.java new file mode 100644 index 0000000..8c8dc11 --- /dev/null +++ b/src/tesseract/objects/remote/RemoteObjectCommunicator.java @@ -0,0 +1,118 @@ +package tesseract.objects.remote; + +import java.awt.event.KeyEvent; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.HashMap; +import java.util.UUID; + +public class RemoteObjectCommunicator implements Runnable { + + private static final int BASE_PORT = 5551; + + private ServerSocket mySocket; + + private HashMap mySockets; + + private boolean myRunning; + + public RemoteObjectCommunicator() { + mySockets = new HashMap(); + myRunning = false; + } + + + public void run() { + int port = BASE_PORT; + + // Find an open port. + while (true) { + try { + mySocket = new ServerSocket(port); + myRunning = true; + break; + + } catch (IOException e) { + port++; + + } catch (Exception e) { + System.err.println(e); + return; + } + } + + // Listen for connections + while (myRunning) { + try { + Socket s = mySocket.accept(); + + handleNewSocket(s); + + } catch (IOException e) { + System.err.println(e); + } + } + } + + public boolean sendKeyToObject(UUID id, KeyEvent event) { + Socket s = mySockets.get(id); + + if (s != null && s.isConnected()) { + try { + DataOutputStream out = new DataOutputStream(s.getOutputStream()); + out.writeInt(event.getKeyCode()); + out.flush(); + + return true; + + } catch (IOException e) { + mySockets.remove(id); + // TODO: REMOVE + System.out.println(id + " Exception. " + e); + return false; + } + + } else { + // TODO: REMOVE + System.out.println(id + " has not called home."); + return false; + } + } + + private void handleNewSocket(final Socket socket) { + try { + // TODO: Remove + System.out.println("New Socket"); + DataInputStream in = new DataInputStream(socket.getInputStream()); + + long msb = in.readLong(); + long lsb = in.readLong(); + + UUID id = new UUID(msb, lsb); + + System.out.println("Id is " + id); + + mySockets.put(id, socket); + + } catch (Exception e) { + System.err.println(e); + } + } + + + public int getPort() { + System.out.print("Blocking for address."); + while (mySocket == null) { + // Block until we get a socket. + System.out.print("."); + } + + System.out.println(); + + return mySocket.getLocalPort(); + } + +} diff --git a/src/tesseract/objects/remote/RemoteObjectMenu.java b/src/tesseract/objects/remote/RemoteObjectMenu.java index bb076d1..610c433 100644 --- a/src/tesseract/objects/remote/RemoteObjectMenu.java +++ b/src/tesseract/objects/remote/RemoteObjectMenu.java @@ -3,6 +3,10 @@ package tesseract.objects.remote; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.net.UnknownHostException; import java.util.ArrayList; import javax.swing.JCheckBoxMenuItem; @@ -21,12 +25,25 @@ public class RemoteObjectMenu extends JMenu { private World myWorld; + private RemoteObjectCommunicator myCommunicator; + + private SocketAddress myHome; + public RemoteObjectMenu(final World theWorld) { super("RC Objects"); // Added by Steve: Fixes viewing menu problem with Canvas3D on both my windows machines JPopupMenu.setDefaultLightWeightPopupEnabled(false); myWorld = theWorld; myControlledObjects = new ArrayList(); + myCommunicator = new RemoteObjectCommunicator(); + new Thread(myCommunicator).start(); + + try { + myHome = new InetSocketAddress(InetAddress.getLocalHost(), myCommunicator.getPort()); + + } catch (UnknownHostException e) { + System.err.println(e); + } // Objects that can be added add(new TankMenuItem(this)); @@ -56,13 +73,18 @@ public class RemoteObjectMenu extends JMenu { myWorld.addObject(theObject); myControlledObjects.add(theObject); + theObject.setHome(myHome); item.setSelected(true); add(item); } public void sendKeyToObjects(final KeyEvent e) { for (RemoteObject o : myControlledObjects) { - o.sendKeyEvent(e); + if (!myCommunicator.sendKeyToObject(o.getId(), e)) { + System.out.println("Send failed to " + o.getId()); + //myControlledObjects.remove(o); + // TODO : Remove from menu. + } } } } diff --git a/src/tesseract/objects/tank/Body.java b/src/tesseract/objects/tank/Body.java index 260eb46..e597f9a 100644 --- a/src/tesseract/objects/tank/Body.java +++ b/src/tesseract/objects/tank/Body.java @@ -1,6 +1,7 @@ package tesseract.objects.tank; import java.awt.Color; +import java.io.Serializable; import javax.media.j3d.Appearance; import javax.media.j3d.ColoringAttributes; @@ -30,6 +31,7 @@ import com.sun.j3d.utils.geometry.Sphere; * */ public class Body { + public static final float width = 1.35f; public static final float height = .45f; public static final float depth = .9f; diff --git a/src/tesseract/objects/tank/Tank.java b/src/tesseract/objects/tank/Tank.java index afafe60..3e5fbdd 100644 --- a/src/tesseract/objects/tank/Tank.java +++ b/src/tesseract/objects/tank/Tank.java @@ -2,44 +2,51 @@ package tesseract.objects.tank; import java.awt.Color; import java.awt.event.KeyEvent; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.util.LinkedList; import java.util.List; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.vecmath.Color3f; -import javax.vecmath.Point3f; import javax.vecmath.Vector3f; import tesseract.objects.ModifyableParticle; -import tesseract.objects.Particle; import tesseract.objects.PhysicalObject; +import tesseract.objects.remote.KeyInfo; import tesseract.objects.remote.RemoteObject; + /** - * tank object + * tank object. * @author Phillip Cardon * */ public class Tank extends RemoteObject { + /** + * Serial UID. + */ + private static final long serialVersionUID = 4419863813052251438L; - private final TransformGroup whole; - private final TransformGroup turret; - //private final Vector3f orientation; - KeyEvent lastEvent; - //private Vector3f aim; - //private final Point3f gunLocation; private static final float DEFAULT_SCALE = 0.0625f / 4f; private static final Color DEFAULT_BODY_COLOR = Color.GREEN; private static final Color DEFAULT_TRACK_COLOR = Color.DARK_GRAY; private static final Color DEFAULT_TURRET_COLOR = Color.GREEN; - private final Body tank; - private int barrelElevation = 0; private static final int maxBarrelElevation = 14; private static final int minBarrelElevation = -1; + private static final int MAX_TURN = 32; + private static final float MAX_SPEED = .3f; + + transient private TransformGroup whole; + transient private TransformGroup turret; + transient private TransformGroup barrel; + + private int barrelElevation = 0; private final float myScale; private int barrelTurn = 0; - private final int MAX_TURN = 32; - private final float MAX_SPEED = .3f; + + private KeyInfo lastEvent; public Tank(final Vector3f thePosition, final float mass) { this(thePosition, mass, DEFAULT_SCALE); @@ -56,20 +63,23 @@ public class Tank extends RemoteObject { final Color turretColor) { super (thePosition, mass); myScale = theScale; - tank = new Body(trackColor, bodyColor, theScale, turretColor); - //orientation = new Vector3f(); - //aim = new Vector3f(); - //gunLocation = new Point3f(); - Transform3D turretMove = new Transform3D(); - turretMove.setTranslation(new Vector3f(0, Body.height * theScale, 0)); + + + Body tank = new Body(trackColor, bodyColor, theScale, turretColor); + + barrel = tank.getBarrel(); + turret = new TransformGroup(); turret.addChild(tank.getTurret()); turret.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); + whole = new TransformGroup(); whole.addChild(tank.getBody()); whole.addChild(turret); whole.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); + setShape(whole); + //inverseInertiaTensor.m00 = 1f / 12 / inverseMass * (Body.height * Body.height * theScale + Body.depth * Body.depth * theScale); //inverseInertiaTensor.m11 = 1f / 12 / inverseMass * (Body.width * Body.width * theScale + Body.depth * Body.depth * theScale); //inverseInertiaTensor.m22 = 1f / 12 / inverseMass * (Body.width * Body.width * theScale + Body.height * Body.height * theScale); @@ -77,36 +87,34 @@ public class Tank extends RemoteObject { } - /** - * - */ - private static final long serialVersionUID = 4419863813052251438L; @Override public String getName() { return "Tank"; } - protected void keyEventReceived(final KeyEvent event) { + protected void keyEventReceived(final KeyInfo event) { lastEvent = event; - //Transform3D check = new Transform3D(); - //tank.getBody().getTransform(check); - //check.get(orientation); - Vector3f temp = new Vector3f(); - Transform3D current = new Transform3D(); - turret.getTransform(current); - Transform3D currentOrientation = new Transform3D(); - whole.getTransform(currentOrientation); + + //Vector3f temp = new Vector3f(); + + Transform3D turnRight = new Transform3D(); Transform3D barrelDown = new Transform3D(); Transform3D barrelUp = new Transform3D(); Transform3D right = new Transform3D(); Transform3D left = new Transform3D(); Transform3D turnLeft = new Transform3D(); - Vector3f facing = new Vector3f(tank.getFacing()); - Transform3D faceTrans = new Transform3D(); - whole.getTransform(faceTrans); - faceTrans.transform(facing); + + Transform3D currentTurrentTransform = new Transform3D(); + turret.getTransform(currentTurrentTransform); + + Transform3D currentOrientation = new Transform3D(); + whole.getTransform(currentOrientation); + + Vector3f facing = new Vector3f(1, 0, 0); + currentOrientation.transform(facing); + switch (event.getKeyCode()) { case KeyEvent.VK_W: facing.scale(.01f); @@ -145,25 +153,25 @@ public class Tank extends RemoteObject { case KeyEvent.VK_LEFT: left.rotY(Math.PI / 32); - current.mul(left); - turret.setTransform(current); + currentTurrentTransform.mul(left); + turret.setTransform(currentTurrentTransform); barrelTurn = barrelTurn - 1; break; case KeyEvent.VK_RIGHT: right.rotY(-Math.PI / 32); - current.mul(right); - turret.setTransform(current); + currentTurrentTransform.mul(right); + turret.setTransform(currentTurrentTransform); barrelTurn = barrelTurn + 1; break; case KeyEvent.VK_UP: - tank.getBarrel().getTransform(barrelUp); + barrel.getTransform(barrelUp); Transform3D up = new Transform3D(); up.rotZ(Math.PI /32); barrelUp.mul(up); if (barrelElevation < maxBarrelElevation) { - tank.getBarrel().setTransform(barrelUp); + barrel.setTransform(barrelUp); barrelElevation++; } //barrelUp.get(aim); @@ -171,12 +179,12 @@ public class Tank extends RemoteObject { break; case KeyEvent.VK_DOWN: - tank.getBarrel().getTransform(barrelDown); + barrel.getTransform(barrelDown); Transform3D down = new Transform3D(); down.rotZ(-Math.PI /32); barrelDown.mul(down); if (barrelElevation > minBarrelElevation) { - tank.getBarrel().setTransform(barrelDown); + barrel.setTransform(barrelDown); barrelElevation--; } @@ -230,9 +238,9 @@ public class Tank extends RemoteObject { particleTurret.setTransform(pTurret); ((TransformGroup) turret.getChild(0)).getTransform(pTG); particleTG.setTransform(pTG); - tank.getBarrel().getTransform(pBarrel); + barrel.getTransform(pBarrel); particleBarrel.setTransform(pBarrel); - ((TransformGroup) tank.getBarrel().getChild(0)).getTransform(pGun); + ((TransformGroup) barrel.getChild(0)).getTransform(pGun); particleGunTG.setTransform(pGun); particleBody.addChild(particleTurret); particleTurret.addChild(particleTG); @@ -322,5 +330,23 @@ public class Tank extends RemoteObject { } + private void writeObject(ObjectOutputStream out) + throws IOException { + out.defaultWriteObject(); + + System.out.println(whole); + System.out.println(turret); + System.out.println(barrel); + } + + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException { + in.defaultReadObject(); + + // Find those pesky references + whole = (TransformGroup) TG.getChild(0); + turret = (TransformGroup) whole.getChild(1); + barrel = ((TransformGroup) ((TransformGroup) ((TransformGroup) turret.getChild(0)).getChild(0)).getChild(1)); + } } -- cgit v1.2.3