为LibGDX使用Physics Body Editor时出错

在我的游戏中,我一直在尝试使用libgdx的物理主体编辑器,但是我一直在得到一个错误。 所以我认为我的代码可能有些问题,所以我把这个例子从网站( http://www.aurelienribon.com/blog/projects/physics-body-editor/ )上取下来,然后试着运行它。 但是我在同一行代码中得到了相同的确切错误。

从网站的例子中创建错误的代码行是

BodyEditorLoader loader = new BodyEditorLoader(Gdx.files.internal("data/test.json")); 

和错误是

线程“LWJGL应用程序”exceptioncom.badlogic.gdx.utils.GdxRuntimeException:java.lang.NoSuchMethodError:com.badlogic.gdx.utils.JsonReader.parse(Ljava / lang / String;)Ljava / lang / Object; 在com.badlogic.gdx.backends.lwjgl.LwjglApplication $ 1.run(LwjglApplication.java:118)引起:java.lang.NoSuchMethodError:com.badlogic.gdx.utils.JsonReader.parse(Ljava / lang / String;) Ljava /郎/对象; aurelienribon.bodyeditor.BodyEditorLoader.readJson(BodyEditorLoader.java:179)at aurelienribon.bodyeditor.BodyEditorLoader。(BodyEditorLoader.java:41)at com.Jon.App.App.createBottle(App.java:129)at com.Jon .App.App.create(App.java:76)at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:132)at com.badlogic.gdx.backends.lwjgl.LwjglApplication $ 1.run( LwjglApplication.java:112)

有想法该怎么解决这个吗?

显然JSON API最近已经改变了,但是物理主体编辑器有一个维护问题。

有关详情, 请访问https://code.google.com/p/libgdx/issues/detail?id=1418

问题是,随着更新版本的libGDX,他们的API已经改变。 这就是为什么你得到像java.lang.NoSuchMethodError这样的错误。

解决方法是使用BodyEditorLoader类的更新版本。 原作者Aurelien Ribon没有足够的时间更新和replace存储库; 其他人已经做出了改变。

此代码应该与libGDX版本1.9.5一起使用。 当你想要使用BodyEditorLoader ,只要引用这个类,就像你在其他类中一样。


这是BodyEditorLoader类的更新版本。 小的修订包括新的readJson方法,replacemul(scale)被改为scl(scale) 。 你可以复制粘贴这个代码, 或者在GitHub上find它的源代码 。

 import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.physics.box2d.Body; import com.badlogic.gdx.physics.box2d.CircleShape; import com.badlogic.gdx.physics.box2d.FixtureDef; import com.badlogic.gdx.physics.box2d.PolygonShape; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.JsonReader; import com.badlogic.gdx.utils.JsonValue; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class BodyEditorLoader { // Model private final Model model; // Reusable stuff private final List<Vector2> vectorPool = new ArrayList<Vector2>(); private final PolygonShape polygonShape = new PolygonShape(); private final CircleShape circleShape = new CircleShape(); private final Vector2 vec = new Vector2(); // ------------------------------------------------------------------------- // Ctors // ------------------------------------------------------------------------- public BodyEditorLoader(FileHandle file) { if (file == null) throw new NullPointerException("file is null"); model = readJson(file.readString()); } public BodyEditorLoader(String str) { if (str == null) throw new NullPointerException("str is null"); model = readJson(str); } // ------------------------------------------------------------------------- // Public API // ------------------------------------------------------------------------- /** * Creates and applies the fixtures defined in the editor. The name * parameter is used to retrieve the right fixture from the loaded file. * <br/><br/> * * The body reference point (the red cross in the tool) is by default * located at the bottom left corner of the image. This reference point * will be put right over the BodyDef position point. Therefore, you should * place this reference point carefully to let you place your body in your * world easily with its BodyDef.position point. Note that to draw an image * at the position of your body, you will need to know this reference point * (see {@link #getOrigin(java.lang.String, float)}. * <br/><br/> * * Also, saved shapes are normalized. As shown in the tool, the width of * the image is considered to be always 1 meter. Thus, you need to provide * a scale factor so the polygons get resized according to your needs (not * every body is 1 meter large in your game, I guess). * * @param body The Box2d body you want to attach the fixture to. * @param name The name of the fixture you want to load. * @param fd The fixture parameters to apply to the created body fixture. * @param scale The desired scale of the body. The default width is 1. */ public void attachFixture(Body body, String name, FixtureDef fd, float scale) { RigidBodyModel rbModel = model.rigidBodies.get(name); if (rbModel == null) throw new RuntimeException("Name '" + name + "' was not found."); Vector2 origin = vec.set(rbModel.origin).scl(scale); for (int i=0, n=rbModel.polygons.size(); i<n; i++) { PolygonModel polygon = rbModel.polygons.get(i); Vector2[] vertices = polygon.buffer; for (int ii=0, nn=vertices.length; ii<nn; ii++) { vertices[ii] = newVec().set(polygon.vertices.get(ii)).scl(scale); vertices[ii].sub(origin); } polygonShape.set(vertices); fd.shape = polygonShape; body.createFixture(fd); for (int ii=0, nn=vertices.length; ii<nn; ii++) { free(vertices[ii]); } } for (int i=0, n=rbModel.circles.size(); i<n; i++) { CircleModel circle = rbModel.circles.get(i); Vector2 center = newVec().set(circle.center).scl(scale); float radius = circle.radius * scale; circleShape.setPosition(center); circleShape.setRadius(radius); fd.shape = circleShape; body.createFixture(fd); free(center); } } /** * Gets the image path attached to the given name. */ public String getImagePath(String name) { RigidBodyModel rbModel = model.rigidBodies.get(name); if (rbModel == null) throw new RuntimeException("Name '" + name + "' was not found."); return rbModel.imagePath; } /** * Gets the origin point attached to the given name. Since the point is * normalized in [0,1] coordinates, it needs to be scaled to your body * size. Warning: this method returns the same Vector2 object each time, so * copy it if you need it for later use. */ public Vector2 getOrigin(String name, float scale) { RigidBodyModel rbModel = model.rigidBodies.get(name); if (rbModel == null) throw new RuntimeException("Name '" + name + "' was not found."); return vec.set(rbModel.origin).scl(scale); } /** * <b>For advanced users only.</b> Lets you access the internal model of * this loader and modify it. Be aware that any modification is permanent * and that you should really know what you are doing. */ public Model getInternalModel() { return model; } // ------------------------------------------------------------------------- // Json Models // ------------------------------------------------------------------------- public static class Model { public final Map<String, RigidBodyModel> rigidBodies = new HashMap<String, RigidBodyModel>(); } public static class RigidBodyModel { public String name; public String imagePath; public final Vector2 origin = new Vector2(); public final List<PolygonModel> polygons = new ArrayList<PolygonModel>(); public final List<CircleModel> circles = new ArrayList<CircleModel>(); } public static class PolygonModel { public final List<Vector2> vertices = new ArrayList<Vector2>(); private Vector2[] buffer; // used to avoid allocation in attachFixture() } public static class CircleModel { public final Vector2 center = new Vector2(); public float radius; } // ------------------------------------------------------------------------- // Json reading process // ------------------------------------------------------------------------- private Model readJson(String str) { Model m = new Model(); JsonValue map = new JsonReader().parse(str); JsonValue bodyElem = map.getChild("rigidBodies"); for (; bodyElem != null; bodyElem = bodyElem.next()) { RigidBodyModel rbModel = readRigidBody(bodyElem); m.rigidBodies.put(rbModel.name, rbModel); } return m; } private RigidBodyModel readRigidBody(JsonValue bodyElem) { RigidBodyModel rbModel = new RigidBodyModel(); rbModel.name = bodyElem.getString("name"); rbModel.imagePath = bodyElem.getString("imagePath"); JsonValue originElem = bodyElem.get("origin"); rbModel.origin.x = originElem.getFloat("x"); rbModel.origin.y = originElem.getFloat("y"); // polygons JsonValue polygonsElem = bodyElem.getChild("polygons"); for (; polygonsElem != null ;polygonsElem = polygonsElem.next()){ PolygonModel polygon = new PolygonModel(); rbModel.polygons.add(polygon); JsonValue vertexElem = polygonsElem.child(); for (; vertexElem != null; vertexElem = vertexElem.next()) { float x = vertexElem.getFloat("x"); float y = vertexElem.getFloat("y"); polygon.vertices.add(new Vector2(x, y)); } polygon.buffer = new Vector2[polygon.vertices.size()]; } // circles JsonValue circleElem = bodyElem.getChild("circles"); for (; circleElem != null; circleElem = circleElem.next()) { CircleModel circle = new CircleModel(); rbModel.circles.add(circle); circle.center.x = circleElem.getFloat("cx"); circle.center.y = circleElem.getFloat("cy"); circle.radius = circleElem.getFloat("r"); } return rbModel; } // ------------------------------------------------------------------------- // Helpers // ------------------------------------------------------------------------- private Vector2 newVec() { return vectorPool.isEmpty() ? new Vector2() : vectorPool.remove(0); } private void free(Vector2 v) { vectorPool.add(v); } }