tiledmap objectlayer から作成したボディにスプライトを描画しようとしています。
コードから手動で作成したボディにスプライトを描画すると、正常に動作します。ただし、タイルマップから作成したボディにスプライトを描画しようとすると、スプライトがボディに配置されません。
それはそれらを世界に描画しますが、間違った場所に、投影行列が設定されていないか間違っているかのようなものです。
stackexchange で同じ問題を抱えている人を見つけました。彼/彼女は同じ問題をコード例で説明しています。悲しいことに、返信/解決策はありません。私は同じ問題を抱えていますが、ピクセル/メートル変換は使用していません。
スタックオーバーフローの最初の投稿...優しくしてください.. :)
これはリンクです:
https://gamedev.stackexchange.com/questions/86474/box2d-shape-fixture-position-vs-body-position
私の問題のスクリーンショットも提供させてください:
http://i.imgur.com/o6WC8ks.png
コード:
ゲームコード:
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.utils.Array;
import com.seve.carramps.entities.Car;
import com.seve.carramps.handlers.MapObjectLoad;
public class testLevel implements Screen {
private World world;
private Box2DDebugRenderer debugRenderer;
private SpriteBatch batch;
private OrthographicCamera camera;
private final float TIMESTEP = 1 / 60f;
private final int VELOCITYITERATIONS = 8, POSITIONITERATIONS = 3;
private Array<Body> pigs;
private Car car;
static int userd = 0;
TiledMap map;
OrthogonalTiledMapRenderer renderer;
// The pixels per tile. If your tiles are 16x16, this is set to 16f
private static float ppt = 32f;
private Sprite carSprite, wheelSprite, treeSprite;
private Array<Body> tmpBodies = new Array<Body>();
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
world.step(TIMESTEP, VELOCITYITERATIONS, POSITIONITERATIONS);
camera.position.set(car.getChassis().getPosition().x, car.getChassis()
.getPosition().y, 0);
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
world.getBodies(tmpBodies);
for (Body body : tmpBodies) {
if (body.getUserData() != null
&& body.getUserData() instanceof Sprite) {
Sprite sprite = (Sprite) body.getUserData();
sprite.setPosition(body.getPosition().x - sprite.getWidth() / 2,(body.getPosition().y - sprite.getHeight() / 2));
sprite.setRotation(body.getAngle() * MathUtils.radiansToDegrees);
sprite.draw(batch);
}
}
batch.end();
debugRenderer.render(world, camera.combined);
}
@Override
public void show() {
setupWorld();
map = new TmxMapLoader().load("carground.tmx");
renderer = new OrthogonalTiledMapRenderer(map);
createCar();
new MapObjectLoad(map, ppt, world, "ground", BodyType.StaticBody, null, null);
new MapObjectLoad(map, ppt, world, "ramps", BodyType.DynamicBody, null, "ramp");
new MapObjectLoad(map, ppt, world, "treeWalls", BodyType.DynamicBody, treeSprite, "treeWall");
new MapObjectLoad(map, ppt, world, "enemies", BodyType.DynamicBody, null, "enemy");
carSprite = new Sprite(new Texture("car.png"));
carSprite.setSize(4, 2);
carSprite
.setOrigin(carSprite.getWidth() / 2, carSprite.getHeight() / 2);
car.getChassis().setUserData(carSprite);
wheelSprite = new Sprite(new Texture("wheel.png"));
wheelSprite.setSize(0.9f, 0.9f);
wheelSprite.setOrigin(wheelSprite.getWidth() / 2,
wheelSprite.getHeight() / 2);
car.getLeftWheel().setUserData(wheelSprite);
car.getRightWheel().setUserData(wheelSprite);
inputProcessor();
}
private void createCar() {
// car
FixtureDef fixtureDef = new FixtureDef(), wheelFixtureDef = new FixtureDef();
fixtureDef.density = 5;
fixtureDef.friction = .4f;
fixtureDef.restitution = .3f;
wheelFixtureDef.density = fixtureDef.density * 1.5f;
wheelFixtureDef.friction = 50;
wheelFixtureDef.restitution = .4f;
car = new Car(world, fixtureDef, wheelFixtureDef, -2.5f, 5, 3.8f, 1.7f);
}
private void setupWorld() {
world = new World(new Vector2(0, -9.81f), true);
debugRenderer = new Box2DDebugRenderer();
batch = new SpriteBatch();
camera = new OrthographicCamera();
}
private void inputProcessor() {
Gdx.input.setInputProcessor(new InputMultiplexer(new InputAdapter() {
@Override
public boolean keyDown(int keycode) {
switch (keycode) {
case Keys.ESCAPE:
((Game) Gdx.app.getApplicationListener())
.setScreen(new testLevel());
break;
}
return false;
}
@Override
public boolean scrolled(int amount) {
camera.zoom += amount / 25f;
return true;
}
}, car));
}
@Override
public void resize(int width, int height) {
camera.viewportWidth = width / 25;
camera.viewportHeight = height / 25;
}
@Override
public void hide() {
dispose();
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void dispose() {
world.dispose();
debugRenderer.dispose();
carSprite.getTexture().dispose();
}
}
さまざまな objectlayer からボディを取得するクラス:
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.maps.Map;
import com.badlogic.gdx.maps.MapObject;
import com.badlogic.gdx.maps.MapObjects;
import com.badlogic.gdx.maps.objects.EllipseMapObject;
import com.badlogic.gdx.maps.objects.PolygonMapObject;
import com.badlogic.gdx.maps.objects.PolylineMapObject;
import com.badlogic.gdx.maps.objects.RectangleMapObject;
import com.badlogic.gdx.maps.objects.TextureMapObject;
import com.badlogic.gdx.math.Ellipse;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.ChainShape;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.Shape;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.utils.Array;
public class MapObjectLoad {
// The pixels per tile. If your tiles are 16x16, this is set to 16f
private static float ppt = 32f;
public MapObjectLoad(Map map, float pixels, World world, String layer,
BodyDef.BodyType bodytype, Sprite sprite, String userData) {
buildShapes(map, pixels, world, layer, bodytype, sprite, userData);
}
// public MOL(Map map, float pixels, World world, String layer,
// BodyDef.BodyType bodytype, String userData) {
//
// buildShapes(map, pixels, world, layer, bodytype, null , userData);
//
// }
public Array<Body> buildShapes(Map map, float pixels, World world,
String layer, BodyDef.BodyType bodytype, Sprite sprite, String userData) {
ppt = pixels;
Body body = null;
MapObjects objects = map.getLayers().get(layer).getObjects();
Array<Body> bodies = new Array<Body>();
for (MapObject object : objects) {
if (object instanceof TextureMapObject) {
continue;
}
Shape shape;
if (object instanceof RectangleMapObject) {
// System.out.println("Rectangle found");
shape = getRectangle((RectangleMapObject) object);
} else if (object instanceof PolygonMapObject) {
// System.out.println("Polygon found");
shape = getPolygon((PolygonMapObject) object);
} else if (object instanceof PolylineMapObject) {
// System.out.println("Polyline found");
shape = getPolyline((PolylineMapObject) object);
} else if (object instanceof EllipseMapObject) {
// System.out.println("Circle found");
shape = getCircle((EllipseMapObject) object);
} else {
continue;
}
BodyDef bd = new BodyDef();
bd.type = bodytype;
// bd.position.set(0, 0);
body = world.createBody(bd);
body.createFixture(shape, 1).setUserData(userData);
// sprite = new Sprite(new Texture("treeWall.png"));
// sprite.setSize(.5f, 2);
// sprite.setOrigin(sprite.getWidth() / 2, sprite.getHeight() / 2);
// body.setUserData(sprite);
bodies.add(body);
shape.dispose();
}
return bodies;
}
private static PolygonShape getRectangle(RectangleMapObject rectangleObject) {
Rectangle rectangle = rectangleObject.getRectangle();
PolygonShape polygon = new PolygonShape();
Vector2 size = new Vector2(
(rectangle.x + rectangle.width * 0.5f) / ppt,
(rectangle.y + rectangle.height * 0.5f) / ppt);
polygon.setAsBox(rectangle.width * 0.5f / ppt, rectangle.height * 0.5f
/ ppt, size, 0.0f);
return polygon;
}
private static CircleShape getCircle(EllipseMapObject object) {
Ellipse ellipse = object.getEllipse();
CircleShape circleShape = new CircleShape();
circleShape.setRadius((ellipse.width / 2) / ppt);
// circleShape.setPosition(new Vector2((ellipse.x + (ellipse.width / 2))
// / ppt, (ellipse.y - (ellipse.height / 2)) / ppt));
circleShape.setPosition(new Vector2((ellipse.x + (ellipse.width / 2))
/ ppt, ellipse.y / ppt));
return circleShape;
}
private static PolygonShape getPolygon(PolygonMapObject polygonObject) {
PolygonShape polygon = new PolygonShape();
float[] vertices = polygonObject.getPolygon().getTransformedVertices();
float[] worldVertices = new float[vertices.length];
for (int i = 0; i < vertices.length; ++i) {
// System.out.println(vertices[i]);
worldVertices[i] = vertices[i] / ppt;
}
polygon.set(worldVertices);
return polygon;
}
private static ChainShape getPolyline(PolylineMapObject polylineObject) {
float[] vertices = polylineObject.getPolyline()
.getTransformedVertices();
Vector2[] worldVertices = new Vector2[vertices.length / 2];
for (int i = 0; i < vertices.length / 2; ++i) {
worldVertices[i] = new Vector2();
worldVertices[i].x = vertices[i * 2] / ppt;
worldVertices[i].y = vertices[i * 2 + 1] / ppt;
}
ChainShape chain = new ChainShape();
chain.createChain(worldVertices);
return chain;
}
}
車を作成するクラス:
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
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.physics.box2d.World;
import com.badlogic.gdx.physics.box2d.joints.WheelJoint;
import com.badlogic.gdx.physics.box2d.joints.WheelJointDef;
public class Car extends InputAdapter{
private Body chassis, leftWheel, rightWheel;
private WheelJoint leftAxis, rightAxis;
public Body getLeftWheel() {
return leftWheel;
}
public Body getRightWheel() {
return rightWheel;
}
private float motorSpeed = 75;
public Car(World world, FixtureDef chassisFixtureDef,
FixtureDef wheelsFixtureDef, float x, float y, float width,
float height) {
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.set(x, y);
// CHASSIS
PolygonShape chassisShape = new PolygonShape();
// chassisShape.set(new float[] {x1, y1, x2, y2}); //counterclockwise
// order
chassisShape.set(new float[] { -width / 2, -height / 2, width / 2,
-height / 2, width / 2 * .4f, height / 2, -width / 2 * .8f,
height / 2 * .8f });
chassisFixtureDef.shape = chassisShape;
chassis = world.createBody(bodyDef);
chassis.createFixture(chassisFixtureDef).setUserData("car");;
// LEFT WHEEL
CircleShape wheelShape = new CircleShape();
wheelShape.setRadius(height / 3.5f);
wheelsFixtureDef.shape = wheelShape;
leftWheel = world.createBody(bodyDef);
leftWheel.createFixture(wheelsFixtureDef);
// RIGHT WHEEL
rightWheel = world.createBody(bodyDef);
rightWheel.createFixture(wheelsFixtureDef);
//left axis;
WheelJointDef axisDef = new WheelJointDef();
axisDef.bodyA = chassis;
axisDef.bodyB = leftWheel;
axisDef.localAnchorA.set(-width / 2 * 1f + wheelShape.getRadius(), -height / 2 * .7f);
axisDef.frequencyHz = chassisFixtureDef.density; // = density af chassis (5) så den kan holde chassis
axisDef.localAxisA.set(Vector2.Y);
// axisDef.maxMotorTorque = 50;
axisDef.maxMotorTorque = chassisFixtureDef.density * 50;
leftAxis = (WheelJoint) world.createJoint(axisDef);
//right axis
axisDef.bodyB = rightWheel;
axisDef.localAnchorA.set(width / 2 * .15f + wheelShape.getRadius(), -height / 2 * .8f);
rightAxis = (WheelJoint) world.createJoint(axisDef);
}
@Override
public boolean keyDown(int keycode) {
switch (keycode) {
case Keys.W:
System.out.println("test");
leftAxis.enableMotor(true);
leftAxis.setMotorSpeed(-motorSpeed);
break;
case Keys.S:
leftAxis.enableMotor(true);
leftAxis.setMotorSpeed(motorSpeed);
break;
}
return true;
}
@Override
public boolean keyUp(int keycode) {
switch (keycode) {
case Keys.W:
case Keys.S:
leftAxis.enableMotor(false);
break;
}
return true;
}
public Body getChassis() {
return chassis;
}
}