如何针对多人游戏场景在客户端之间序列化更新消息?

时间:2014-06-14 17:16:29

标签: java serialization tcp 3d jmonkeyengine

对于2人空间场景,我启动了一个接受来自2个客户端的连接的服务器。

import java.io.IOException;

import com.jme3.app.SimpleApplication;
import com.jme3.system.JmeContext;
import com.jme3.network.ConnectionListener;
import com.jme3.network.Filters;
import com.jme3.network.HostedConnection;
import com.jme3.network.Message;
import com.jme3.network.Network;
import com.jme3.network.Server;
import com.jme3.network.serializing.Serializer;

public class SpaceWorldServer extends SimpleApplication implements
        ConnectionListener {
    Server myServer = null;
    static SpaceWorldServer app = null;
    int counter = 0;

    public static void main(String[] args) {
        app = new SpaceWorldServer();
        app.start(JmeContext.Type.Headless);
    }

    public void simpleInitApp() {
        System.out.println("simpleInitApp");
        try {
            myServer = Network.createServer(6143);
            Serializer.registerClass(ActionMessage.class);
            myServer.addMessageListener(new ServerListener(app),
                    ActionMessage.class);
            myServer.addConnectionListener(this);
        } catch (IOException e) {
            e.printStackTrace();
        }
        myServer.start();
    }

    @Override
    public void destroy() {
        myServer.close();
        super.destroy();
    }

    public void updatePlayers(Message message, HostedConnection c) {
        myServer.broadcast(Filters.notEqualTo(c), message);
    }

    public void connectionAdded(Server s, HostedConnection c) {
        System.out.println("connectionAdded:" + c.toString());
        Message message = new ActionMessage(100, 200, true);
        System.out.println("broadcasting message " + message.toString());
        myServer.broadcast(Filters.notEqualTo(c), message);
        System.out.println("broadcast message " + message.toString());
    }

    public void connectionRemoved(Server s, HostedConnection c) {
    }

    @Override
    public void simpleUpdate(float tpf) {
        if (counter != myServer.getConnections().size()) {
            System.out.println("#connections:"
                    + myServer.getConnections().size());
            counter = myServer.getConnections().size();
        }
    }
}

我有一个客户端监听器,当第二个客户端更新时,通过服务器可以将其消息广播到第一个客户端。

import java.util.concurrent.Callable;

import com.jme3.network.Client;
import com.jme3.network.ClientStateListener;
import com.jme3.network.Message;
import com.jme3.network.MessageListener;

public class ClientListener implements ClientStateListener,
        MessageListener<Client> {

    private UFOSpaceWorld app;
    private Client client;
    private boolean doTheRoll = false;

    public ClientListener(UFOSpaceWorld app, Client client) {
        this.app = app;
        this.client = client;
        client.addClientStateListener(this);
    }

    public void messageReceived(Client source, Message message) {
        if (message instanceof ActionMessage) {
            ActionMessage helloMessage = (ActionMessage) message;
            if (helloMessage.getAction() == 200) {
                app.enqueue(new Callable<Void>() {
                    public Void call() throws Exception {
                        app.addNewSaucer();
                        return null;
                    }
                });
            } else if (helloMessage.getAction() == 1) {
                if (helloMessage.isB() == true) {
                    doTheRoll = true;

                } else {
                    doTheRoll = false;
                }
                app.enqueue(new Callable<Void>() {
                    public Void call() throws Exception {
                        if (doTheRoll == true) {
                            app.setDoRoll(true);
                        } else {
                            app.setDoRoll(false);
                        }
                        app.setPlayer2update(true);
                        return null;
                    }
                });

            }
        }
    }

    @Override
    public void clientConnected(Client arg0) {
    }

    @Override
    public void clientDisconnected(Client arg0, DisconnectInfo arg1) {
    }
}

执行并同步回调,以便在启动第二个客户端时第二个太空船出现在第一个客户端上。现在我想在第一个客户端(播放器1)的屏幕上移动第二个客户端,但是我无法将类Vector3f序列化为播放器2移动时的方向向量。我的2个客户端使用相同的客户端类和ActionMessage类。

@Serializable()
public class ActionMessage extends PhysicsSyncMessage {

    public final static int NULL_ACTION = 0;
    public final static int JUMP_ACTION = 1;
    public final static int ENTER_ACTION = 2;
    public final static int SHOOT_ACTION = 3;

    public int action = 000;

    public int getAction() {
        return action;
    }

    public void setAction(int action) {
        this.action = action;
    }

    public boolean pressed;

    public ActionMessage() {
    }

    String s = null;

    public String getS() {
        return s;
    }

    public void setS(String s) {
        this.s = s;
    }

    boolean b = false;

    public boolean isB() {
        return b;
    }

    public void setB(boolean b) {
        this.b = b;
    }

    public ActionMessage(String s, boolean b) {
        this.s = s;
        this.b = b;
    }

    public ActionMessage(long id, int action, boolean pressed) {
        this.syncId = id;
        this.action = action;
        this.pressed = pressed;
        this.b = pressed;
    }

    public ActionMessage(long id, int action, boolean pressed, boolean up) {
        this.syncId = id;
        this.action = action;
        this.pressed = pressed;
        this.b = pressed;
    }

    @Override
    public void applyData(Object object) {
        ((Spatial) object).getControl(NetworkActionEnabled.class)
                .doPerformAction(action, pressed);
    }
}

当Vector3f无法序列化时,如何在客户端移动时发送消息?

public class UFOSpaceWorld extends SimpleApplication implements AnalogListener,
        ActionListener {

    private PlanetAppState planetAppState;
    private Geometry mark;
    private Node ufoNode;
    private RigidBodyControl ufoControl;
    private RigidBodyControl ufoControl2;
    private Node ufoNode2;
    private CylinderCollisionShape shape;
    private BoundingBox bv;
    private RigidBodyControl jumpGateControl;
    private RigidBodyControl jumpGateControl2;
    private AnimChannel channel;
    private AnimControl control;
    private Node spacemanNode;
    private RigidBodyControl spacemanControl;
    private Node alien;
    private String serverName = "localhost";
    private int portNumber = 6143;
    private RigidBodyControl alienControl;
    Spatial jumpgateSpatial;
    CameraNode camNode;
    ChaseCamera chaseCam;
    Planet moon;
    static UFOSpaceWorld app;
    Client myClient = null;
    Vector3f ufoDirection = new Vector3f();
    Vector3f ufoDirection2 = new Vector3f();
    Vector3f gate2vector = new Vector3f(10f, 10f, 1598300f);
    Vector3f gate1vector = new Vector3f(10f, 10f, 1098300f);
    private BulletAppState bulletAppState;
    private boolean left = false, right = false, up = false, down = false,
            forward = false, backward = false, attack = false, rotate = false;
    private long starttime = 0;
    private long playtime = 0;

    private void setupChaseCamera() {
        flyCam.setEnabled(false);
        chaseCam = new ChaseCamera(cam, ufoNode, inputManager);
        chaseCam.setDefaultDistance(2237);
    }

    @Override
    public void destroy() {
        // custom code
        if (myClient != null) {
            myClient.close();
        }
        super.destroy();
    }

    public static void main(String[] args) {

        AppSettings settings = new AppSettings(true);
        settings.setResolution(1280, 1024);
        settings.setSettingsDialogImage("Interface/spacesplash.png");
        settings.setTitle("Space World");
        app = new UFOSpaceWorld();
        if (args.length > 0) {
            app.serverName = args[0];
        }
        if (args.length > 1) {
            app.portNumber = new Integer(args[0]);
        }
        app.setSettings(settings);
        app.start();
    }

    @Override
    public void simpleInitApp() {
        playtime = 0;
        starttime = System.currentTimeMillis();
        this.setDisplayStatView(false);
        setDisplayFps(false);
        java.util.logging.Logger.getLogger("com.jme3").setLevel(
                java.util.logging.Level.SEVERE);
        bulletAppState = new BulletAppState();
        bulletAppState.setThreadingType(BulletAppState.ThreadingType.PARALLEL);
        stateManager.attach(bulletAppState);
        bulletAppState.setDebugEnabled(false);
        DirectionalLight sun = new DirectionalLight();
        sun.setDirection(new Vector3f(-.1f, 0f, -1f));
        sun.setColor(new ColorRGBA(0.75f, 0.75f, 0.75f, 1.0f));
        rootNode.addLight(sun);
        // Add sky
        Node sceneNode = new Node("Scene");
        sceneNode.attachChild(Utility.createSkyBox(this.getAssetManager(),
                "Textures/blue-glow-1024.dds"));
        rootNode.attachChild(sceneNode);
        // Create collision test mark
        Sphere sphere = new Sphere(30, 30, 5f);
        mark = new Geometry("mark", sphere);
        Material mark_mat = new Material(assetManager,
                "Common/MatDefs/Misc/Unshaded.j3md");
        mark_mat.setColor("Color", ColorRGBA.Red);
        mark.setMaterial(mark_mat);
        // Add planet app state
        planetAppState = new PlanetAppState(rootNode, sun);
        stateManager.attach(planetAppState);
        // Add planet
        FractalDataSource planetDataSource = new FractalDataSource(4);
        planetDataSource.setHeightScale(900f);
        Planet planet = Utility.createEarthLikePlanet(getAssetManager(),
                293710.0f, null, planetDataSource);
        planet.addControl(new RigidBodyControl(new PlanetCollisionShape(planet
                .getLocalTranslation(), planet.getRadius(), planetDataSource),
                0f));
        planetAppState.addPlanet(planet);
        rootNode.attachChild(planet);
        bulletAppState.getPhysicsSpace().add(planet);

        // Add moon
        FractalDataSource moonDataSource = new FractalDataSource(5);
        moonDataSource.setHeightScale(300f);
        moon = Utility.createMoonLikePlanet(getAssetManager(), 50000,
                moonDataSource);
        moon.setLocalTranslation(new Vector3f(10f, 10f, 1505000f));
        RigidBodyControl moonControl = new RigidBodyControl(
                new PlanetCollisionShape(moon.getLocalTranslation(),
                        moon.getRadius(), moonDataSource), 0f);
        moon.addControl(moonControl);
        planetAppState.addPlanet(moon);
        // add saucer

        addSaucer();
        jumpgateSpatial = assetManager.loadModel("JumpGate.j3o");
        jumpgateSpatial.setLocalScale(10000f);
        BoundingBox jbv = (BoundingBox) jumpgateSpatial.getWorldBound();
        CylinderCollisionShape jshape = new CylinderCollisionShape(
                new Vector3f(jbv.getXExtent(), jbv.getYExtent(),
                        jbv.getZExtent()), 1);
        ;
        jumpGateControl = new RigidBodyControl(jshape, 0);
        jumpgateSpatial.addControl(jumpGateControl);
        jumpGateControl.setMass(0f);
        jumpGateControl.setPhysicsLocation(gate1vector);
        jumpGateControl.setPhysicsRotation(new Quaternion().fromAngleAxis(
                90 * FastMath.DEG_TO_RAD, new Vector3f(1, 0, 0)));

        Spatial jumpgateSpatial2 = assetManager.loadModel("JumpGate.j3o");
        jumpgateSpatial2.setLocalScale(10000f);

        BoundingBox jbv2 = (BoundingBox) jumpgateSpatial2.getWorldBound();
        CylinderCollisionShape jshape2 = new CylinderCollisionShape(
                new Vector3f(jbv2.getXExtent(), jbv2.getYExtent(),
                        jbv2.getZExtent()), 1);
        ;

        Quaternion roll180 = new Quaternion();
        roll180.fromAngleAxis(FastMath.PI / 2, new Vector3f(0, 1, 0));

        jumpGateControl2 = new RigidBodyControl(jshape2, 0);
        jumpgateSpatial2.addControl(jumpGateControl2);
        jumpGateControl2.setMass(0f);
        jumpGateControl2.setPhysicsLocation(gate2vector);
        jumpGateControl2.setPhysicsRotation(new Quaternion().fromAngleAxis(
                90 * FastMath.DEG_TO_RAD, new Vector3f(1, 0, 0)));

        Spatial spaceStationSpatial = assetManager
                .loadModel("SpaceStation.blend");
        spaceStationSpatial.setLocalScale(3500f);

        BoundingBox sbv = (BoundingBox) spaceStationSpatial.getWorldBound();

        CompoundCollisionShape shape3 = new CompoundCollisionShape();
        shape3.addChildShape(
                new CylinderCollisionShape(new Vector3f(sbv.getXExtent(), sbv
                        .getYExtent(), sbv.getZExtent()), 1), new Vector3f(0,
                        0, 0));
        RigidBodyControl spaceStationControl = new RigidBodyControl(shape3, 0);
        spaceStationSpatial.addControl(spaceStationControl);
        spaceStationControl.setMass(0f);
        spaceStationControl.setPhysicsLocation(new Vector3f(10000f, -10f,
                705000f));

        BlenderKey blenderKey = new BlenderKey(
                "objects/creatures/alien/alienmodel.blend");

        Spatial alien = (Spatial) assetManager.loadModel(blenderKey);
        alien.setLocalScale(20 * 2000f);
        alienControl = new RigidBodyControl(3 * 500f);
        alien.addControl(alienControl);

        alienControl.setPhysicsLocation(new Vector3f(11000f, -50f, 755000f));
        //
        BlenderKey blenderKey2 = new BlenderKey(
                "objects/creatures/spaceman/man.mesh.xml");

        Spatial man = (Spatial) assetManager.loadModel(blenderKey2);
        man.setLocalScale(200f);
        spacemanControl = new RigidBodyControl(4 * 500f);
        man.addControl(spacemanControl);

        spacemanControl
                .setPhysicsLocation(new Vector3f(10700f, -590f, 775000f));

        createNewOtoBot();
        BulletAppState bas = app.getStateManager().getState(
                BulletAppState.class);
        bas.getPhysicsSpace().addAll(spaceStationSpatial);

        bas.getPhysicsSpace().addAll(man);
        bas.getPhysicsSpace().addAll(alien);
        bas.getPhysicsSpace().addAll(jumpgateSpatial);
        bas.getPhysicsSpace().addAll(jumpgateSpatial2);
        bas.getPhysicsSpace().addAll(moon);
        bas.getPhysicsSpace().addAll(planet);
        bas.getPhysicsSpace().setGravity(new Vector3f(0, 0, 0));

        rootNode.attachChild(man);
        rootNode.attachChild(alien);
        rootNode.attachChild(spaceStationSpatial);
        rootNode.attachChild(jumpgateSpatial);
        rootNode.attachChild(jumpgateSpatial2);
        rootNode.attachChild(moon);

        setupChaseCamera();
        registerInput();

        try {
            System.out.println("connecting to " + serverName);
            myClient = Network.connectToServer(serverName, portNumber);
            System.out.println("connected to " + serverName);
            Serializer.registerClass(ActionMessage.class);
            myClient.addMessageListener(new ClientListener(app, myClient),
                    ActionMessage.class);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        if (myClient != null) {
            myClient.start();
        } else {
            System.out.println("myClient == null " + serverName);
        }
    }

    public void clientConnected(Client c) {
        System.out.println("clientConnected ");
    }

    private PhysicsSpace getPhysicsSpace() {
        return bulletAppState.getPhysicsSpace();
    }

    public void addSaucer() {

        ufoNode = (Node) assetManager.loadModel("usaucer_v01.j3o");
        ufoNode.setLocalScale(200f);
        BoundingBox bv = (BoundingBox) ufoNode.getWorldBound();
        CylinderCollisionShape shape = new CylinderCollisionShape(new Vector3f(
                bv.getXExtent(), bv.getYExtent(), bv.getZExtent()), 1);
        ufoControl = new RigidBodyControl(shape, 500f);
        ufoNode.addControl(ufoControl);
        System.out.println("addSaucer 200:");
        ufoControl.setPhysicsLocation(new Vector3f(10850f, -5979f, 785020f));
        BulletAppState bas = app.getStateManager().getState(
                BulletAppState.class);
        bas.getPhysicsSpace().addAll(ufoNode);
        rootNode.attachChild(ufoNode);
    }

    public void addNewSaucer() {
        ufoNode2 = (Node) assetManager.loadModel("usaucer_v01.j3o");
        ufoNode2.setLocalScale(700f);
        bv = (BoundingBox) ufoNode2.getWorldBound();
        shape = new CylinderCollisionShape(new Vector3f(bv.getXExtent(),
                bv.getYExtent(), bv.getZExtent()), 1);
        ufoControl2 = new RigidBodyControl(shape, 500f);
        ufoNode2.addControl(ufoControl2);
        ufoControl2.setPhysicsLocation(new Vector3f(10850f, -5979f, 785020f));
        ufoControl2.setGravity(Vector3f.ZERO);
        ufoControl2.setLinearVelocity(Vector3f.ZERO);
        ufoControl2.clearForces();
        BulletAppState bas = app.getStateManager().getState(
                BulletAppState.class);
        bas.getPhysicsSpace().addAll(ufoNode2);
        rootNode.attachChild(ufoNode2);
    }

    public void createNewOtoBot() {
        BlenderKey otoblenderKey = new BlenderKey("Models/Oto/Oto.mesh.xml");
        Spatial otoBot = (Spatial) assetManager.loadModel(otoblenderKey);
        otoBot.setLocalScale(600f);
        RigidBodyControl otoControl = new RigidBodyControl(30 * 500f);
        otoBot.addControl(otoControl);
        otoControl.setPhysicsLocation(new Vector3f(10800f, -579f, 785000f));
        control = otoBot.getControl(AnimControl.class);
        channel = control.createChannel();
        for (String anim : control.getAnimationNames())
            System.out.println("otoBot can:" + anim);
        channel.setAnim("pull");
        BulletAppState bas = app.getStateManager().getState(
                BulletAppState.class);
        bas.getPhysicsSpace().addAll(otoBot);
        rootNode.attachChild(otoBot);
    }

    public void registerInput() {
        inputManager.addMapping("moveForward", new KeyTrigger(keyInput.KEY_UP),
                new KeyTrigger(keyInput.KEY_W));
        inputManager.addMapping("moveBackward", new KeyTrigger(
                keyInput.KEY_DOWN), new KeyTrigger(keyInput.KEY_S));
        inputManager.addMapping("moveRight",
                new KeyTrigger(keyInput.KEY_RIGHT), new KeyTrigger(
                        keyInput.KEY_D));
        inputManager.addMapping("moveLeft", new KeyTrigger(keyInput.KEY_LEFT),
                new KeyTrigger(keyInput.KEY_A));
        inputManager.addMapping("moveUp", new KeyTrigger(keyInput.KEY_E));
        inputManager.addMapping("startServer", new KeyTrigger(keyInput.KEY_M));
        inputManager.addMapping("moveDown", new KeyTrigger(keyInput.KEY_Q));
        inputManager.addMapping("toggleRotate", new MouseButtonTrigger(
                MouseInput.BUTTON_LEFT));
        inputManager.addMapping("rotateRight", new MouseAxisTrigger(
                MouseInput.AXIS_X, true));
        inputManager.addMapping("rotateLeft", new MouseAxisTrigger(
                MouseInput.AXIS_X, false));
        inputManager.addMapping("rotateUp", new MouseAxisTrigger(
                MouseInput.AXIS_Y, true));
        inputManager.addMapping("rotateDown", new MouseAxisTrigger(
                MouseInput.AXIS_Y, false));
        inputManager.addListener(this, "moveForward", "moveBackward",
                "moveRight", "moveLeft", "moveUp", "moveDown");
        inputManager.addListener(this, "rotateRight", "rotateLeft", "rotateUp",
                "rotateDown", "toggleRotate", "startServer");
        // Toggle mouse cursor
        inputManager.addMapping("TOGGLE_CURSOR", new MouseButtonTrigger(
                MouseInput.BUTTON_LEFT), new KeyTrigger(KeyInput.KEY_SPACE));
        inputManager.addListener(actionListener, "TOGGLE_CURSOR");
        // Toggle wireframe
        inputManager.addMapping("TOGGLE_WIREFRAME", new KeyTrigger(
                KeyInput.KEY_T));
        inputManager.addListener(actionListener, "TOGGLE_WIREFRAME");
        // Collision test
        inputManager.addMapping("COLLISION_TEST", new MouseButtonTrigger(
                MouseInput.BUTTON_RIGHT));
        inputManager.addListener(actionListener, "COLLISION_TEST");
    }

    public void toggleToFullscreen() {
        GraphicsDevice device = GraphicsEnvironment
                .getLocalGraphicsEnvironment().getDefaultScreenDevice();
        DisplayMode[] modes = device.getDisplayModes();
        int i = 0; // note: there are usually several, let's pick the first
        settings.setResolution(modes[i].getWidth(), modes[i].getHeight());
        settings.setFrequency(modes[i].getRefreshRate());
        settings.setBitsPerPixel(modes[i].getBitDepth());
        settings.setFullscreen(device.isFullScreenSupported());
        app.setSettings(settings);
        app.restart(); // restart the context to apply changes
    }

    long time = 0;

    public void simpleUpdatePlayer2(float tpf) {
        System.out.println("LOOP simpleUpdatePlayer2 player 2");
        int speed = 8000;
        Vector3f camDir = cam.getDirection().clone().multLocal(speed * tpf);
        Vector3f camUp = cam.getUp().clone().mult(speed * tpf);
        Quaternion roll = new Quaternion();
        camDir.y = 0;
        // ufoDirection2.set(0, 0, 0);
        // ufoControl2.setLinearVelocity(Vector3f.ZERO);
        if (doRoll == true) {
            roll.fromAngleAxis(FastMath.QUARTER_PI / 3, cam.getDirection());
        }
        if (ufoControl2 == null) {
            System.out.println("ufoControl2 == null");
        }
        ufoControl2.setPhysicsRotation(roll);

        if (System.currentTimeMillis() - time > 1000) {
            System.out.println("LOOP BREAK");
            ufoDirection2.set(0, 0, 0);
            ufoControl2.setLinearVelocity(Vector3f.ZERO);
            time = 0;
            player2update = false;
        }
    }

    private boolean doRoll = false;

    public boolean isDoRoll() {
        return doRoll;
    }

    public void setDoRoll(boolean doRoll) {
        this.doRoll = doRoll;
    }

    @Override
    public void simpleUpdate(float tpf) {
        playtime = System.currentTimeMillis() - starttime;
        int speed = 25 * 80000;
        Vector3f camDir = cam.getDirection().clone().multLocal(speed * tpf);
        Vector3f camUp = cam.getUp().clone().mult(speed * tpf);
        Quaternion roll = new Quaternion();
        camDir.y = 0;
        ufoDirection.set(0, 0, 0);
        ufoControl.setLinearVelocity(Vector3f.ZERO);
        if (left) {
            roll.fromAngleAxis(-FastMath.QUARTER_PI / 3, cam.getDirection());
            ufoDirection.set(cam.getLeft().multLocal(speed * tpf));
        }
        if (right) {
            roll.fromAngleAxis(FastMath.QUARTER_PI / 3, cam.getDirection());
            ufoDirection.set(cam.getLeft()).multLocal(-speed * tpf);
        }
        if (up) {
            roll.fromAngleAxis(0, cam.getDirection());
            ufoDirection.addLocal(camUp);
        }
        if (down) {
            roll.fromAngleAxis(0, cam.getDirection());
            ufoDirection.addLocal(cam.getUp().multLocal(-speed * tpf));
        }
        if (forward) {
            roll.fromAngleAxis(0, cam.getDirection());
            ufoDirection.set(camDir);
        }
        if (backward) {
            roll.fromAngleAxis(0, cam.getDirection());
            ufoDirection.set(camDir.multLocal(-1f));
        }
        ufoControl.setPhysicsRotation(roll);
        ufoControl.setLinearVelocity(ufoDirection);

        CollisionResults results = new CollisionResults();

        System.out.println("1 #Collisions between" + ufoNode.getName()
                + " and " + jumpgateSpatial.getName() + ": " + results.size());
        ufoNode.collideWith((BoundingBox) jumpgateSpatial.getWorldBound(),
                results);
        System.out.println("2 #Collisions between" + ufoNode.getName()
                + " and " + jumpgateSpatial.getName() + ": " + results.size());
        CollisionResults results2 = new CollisionResults();

        // Use the results

        if (results.size() > 0 && playtime > 50000) {
            System.out.println("playtime" + playtime);
            System.out.println("#Collisions between" + ufoNode.getName()
                    + " and " + jumpgateSpatial.getName() + ": "
                    + results.size());

            // how to react when a collision was detected
            CollisionResult closest = results.getClosestCollision();
            System.out.println("What was hit? "
                    + closest.getGeometry().getName());
            System.out
                    .println("Where was it hit? " + closest.getContactPoint());
            System.out.println("Distance? " + closest.getDistance());
            ufoControl
                    .setPhysicsLocation(jumpGateControl2.getPhysicsLocation());
            System.out.println("Warped");

        } else {
            // how to react when no collision occured
        }

        if (results2.size() > 0) {
            System.out.println("Number of Collisions between"
                    + ufoNode.getName() + " and " + moon.getName() + ": "
                    + results2.size());

            // how to react when a collision was detected
            CollisionResult closest2 = results2.getClosestCollision();
            System.out.println("What was hit? "
                    + closest2.getGeometry().getName());
            System.out.println("Where was it hit? "
                    + closest2.getContactPoint());
            System.out.println("Distance? " + closest2.getDistance());
        }
        Message message = new ActionMessage(1, myClient.getId(), right);
        if (myClient != null) {
            myClient.send(message);
        }
        if (player2update == true) {
            System.out.println("simpleUpdatePlayer2 player 2 "
                    + message.toString());
            time = System.currentTimeMillis();
            simpleUpdatePlayer2(tpf);
        }
    }

    boolean player2update = false;

    public boolean isPlayer2update() {
        return player2update;
    }

    public void setPlayer2update(boolean player2update) {
        this.player2update = player2update;
    }
}

2 个答案:

答案 0 :(得分:3)

尽管在子类中实现了Serialization接口,但父级的字段不会被序列化。需要提供两种方法readObjectwriteObject来处理父类的序列化过程(code

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Vector3fSerializationExample {

    static class Vector3f {

        double x, y, z;

        Vector3f() {
        }

        Vector3f(double x, double y, double z) {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        @Override
        public String toString() {
            return "Vector3f [x=" + x + ", y=" + y + ", z=" + z + "]";
        }

    }

    static class Vector3fSubclass2 extends Vector3f implements Serializable {

        private static final long serialVersionUID = 1L;

        Vector3fSubclass2() {
        }

        Vector3fSubclass2(double x, double y, double z) {
            super(x, y, z);
        }
    }

    static class Vector3fSubclass extends Vector3f implements Serializable {

        private static final long serialVersionUID = 1L;

        Vector3fSubclass() {
        }

        Vector3fSubclass(double x, double y, double z) {
            super(x, y, z);
        }

        private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
            ois.defaultReadObject();

            x = ois.readDouble();
            y = ois.readDouble();
            z = ois.readDouble();

        }

        private void writeObject(ObjectOutputStream oos) throws IOException {
            oos.defaultWriteObject();

            oos.writeDouble(x);
            oos.writeDouble(y);
            oos.writeDouble(z);

        }

    }

    static class SerializationUtil {

        static Object deserialize(byte[] buff) throws IOException, ClassNotFoundException {

            ByteArrayInputStream in = new ByteArrayInputStream(buff);
            ObjectInputStream ois = new ObjectInputStream(in);
            Object obj = ois.readObject();
            ois.close();
            return obj;
        }

        static byte[] serialize(Object obj) throws IOException {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(out);
            oos.writeObject(obj);
            out.close();
            return out.toByteArray();

        }
    }

    public static void main(String[] args) throws Throwable {

        Vector3f v3f = new Vector3fSubclass(1, 2, 3);
        byte[] arr = SerializationUtil.serialize(v3f);
        System.out.println(SerializationUtil.deserialize(arr));

        v3f = new Vector3fSubclass2(1, 2, 3); //subclass without needed methods
        arr = SerializationUtil.serialize(v3f);
        System.out.println(SerializationUtil.deserialize(arr));
    }

}

输出:

Vector3f [x=1.0, y=2.0, z=3.0]
Vector3f [x=0.0, y=0.0, z=0.0]

答案 1 :(得分:2)

如果Vector3f中的组件是可序列化的 你可以编写一个类,让它扩展Vector3f并让它实现Serializable。