【问题标题】:How do I serialize a JBox2d World object?如何序列化 JBox2d World 对象?
【发布时间】:2013-10-07 22:54:25
【问题描述】:

我有一个连接了多个客户端的服务器。每个客户都有一个他们可以控制的身体(玩家),但可能会发生碰撞,因此他们需要查看其他人的身体才能知道为什么他们的某些动作会受到限制。

我的解决方案是将“世界”对象传递给对象输入/输出流。然后我使用处理解析和绘制每个身体。这是我得到的错误:

java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: org.jbox2d.dynamics.World
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at Client.setup(Client.java:30)
    at processing.core.PApplet.handleDraw(PApplet.java:2280)
    at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:243)
    at processing.core.PApplet.run(PApplet.java:2176)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.io.NotSerializableException: org.jbox2d.dynamics.World
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at Player.sendWorld(Player.java:57)
    at Server.draw(Server.java:54)
    at processing.core.PApplet.handleDraw(PApplet.java:2305)
    ... 3 more

很明显 World 需要被序列化/可序列化才能通过套接字传递。知道我会怎么做吗?我是否需要为每个主体执行此操作,创建 xml/json 然后传递它而不是简单地发送世界?

服务器输出

public void sendWorld(World world) {
    try {
        out.writeObject(world);
        out.flush(); // or maybe out.reset()
    } catch (IOException e) {
        e.printStackTrace();
    }
}

客户输入

try {
    bodySocket = new Socket(serverHostname, port);
    in = new ObjectInputStream(bodySocket.getInputStream());
    Object next = in.readObject();
    System.out.println("Getting world");
    if (next instanceof World) {
        this.world = (World) next;
    }
} catch (UnknownHostException e) {
    System.err.println("Don't know about host: " + serverHostname);
    System.exit(1);
} catch (IOException e) {
    System.err.println("Couldn't get I/O for " + "the connection to: "
            + serverHostname);
    e.printStackTrace();
    System.exit(1);
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

客户抽奖

public void draw() {
    // Background
    background(100);
    // Bodies (includes floors, walls, and players)
    for (Body body = world.getBodyList(); body != null; body = body
            .getNext()) {
        Vec2 playerLoc = body.getPosition();
        rectMode(PApplet.RADIUS);
        fill(255, 100);
        rect(playerLoc.x, fieldBottom - playerLoc.y, 10, 10);
    }
}

【问题讨论】:

  • 如果我不能很快解决这个问题,我最终可能会遍历世界主体列表并创建一个 json 对象来保存每个主体的用户数据、坐标和对象类型。网络效率会更高,但写起来不那么容易。

标签: java json serialization objectoutputstream jbox2d


【解决方案1】:

为此我做了序列化包:)

我包括对 protobufs 的序列化,这对您来说可能是最好的(它最大程度地减小了大小)。你可以序列化世界、身体、关节、形状,任何你想要的粒度。

查看PbSerializer

这里是关于 protobufs 的文档: https://code.google.com/p/protobuf/

【讨论】:

  • 我无法让它工作。所有带有示例的文档似乎都适用于 c++ 而不是 java。我尝试了几件事,最终放弃了。确实应该有一个类似于 C# 的页面,不仅提供可用的方法,而且提供如何使用它们的简短示例。
  • 文档是用 C++ 和 Java 编写的,请再次检查:developers.google.com/protocol-buffers/docs/javatutorial :) 或者更重要的是,您不必担心制作协议缓冲区,因为我已经这样做了。只需使用我在 jbox2d-serialization 包中创建的 PbSerializer 和 PbDeserializer 类即可。
  • 感谢您的回信。我查看了您链接到的页面,但没有真正看到任何有关 Java 序列化的示例。也许我只是错过了。我确实看到了一些方法,但没有看到它们的使用方式和期望值。我确实尝试了 PS & PD 类,但是当我最终编译它时,我的对象编写器会通过它。我最终编写了自己的 JSON 解析器,但我希望看到从服务器传递到客户端的世界对象的骨架示例!我很好奇您是否决定通过套接字发送字符串或对象。
  • protobuf 对象具有字节序列化方法,它非常高效且压缩得非常好。我真的会考虑了解它们,它们是一个很好的工具,可以很好地为您服务(它们在行业中也很受欢迎)。你是什​​么意思“我的对象作家会通过它”?此外,您所要做的就是在您序列化的世界上调用 build(),然后您可以执行类似“toByteArray()”或类似的操作,查看 protobuf javadoc 以获得最佳序列化方法。
【解决方案2】:

您可以查看 JBbSerializer 类。来自它的 javadoc:“jbox2d 的序列化器,用于序列化物理世界的任何方面”,因此它可能会满足您的需求。在 jbox2d-serialization 项目中查找它(应该随您的下载一起提供)。不过,这可能比它的价值更麻烦。

【讨论】:

  • 谢谢,这可能有效... PbSerializer pbs = new PbSerializer();生成器 obj = pbs.serializeWorld(world);然后在客户端 if (next instanceof Builder) { this.world = pbd.deserializeWorld((PbWorld)next);
猜你喜欢
  • 1970-01-01
  • 2011-02-27
  • 1970-01-01
  • 2015-06-28
  • 2011-04-06
  • 1970-01-01
  • 1970-01-01
  • 2019-08-12
相关资源
最近更新 更多