我正在尝试将精灵绘制到我从tilemap对象层创建的实体上
当我将sprite绘制到我从代码手动创建的实体上时,它可以正常工作。然而,当我尝试在我从tilemap创建的身体上绘制精灵时,它不会将精灵放到身体上。
它在世界上吸引它们,但在错误的地方,有点像投影矩阵没有设置或错误或其他东西。
我在stackexchange上发现了一个同样的问题他/她描述了同样的问题和代码示例。可悲的是,没有回复/解决方案。我有同样的问题,但我不使用每米转换像素。
stackoverflow上的第一篇帖子......温柔......:)
这是链接:
https://gamedev.stackexchange.com/questions/86474/box2d-shape-fixture-position-vs-body-position
让我提供一个screentshot以及我的问题:
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();
}
}
获取来自不同对象层的实体的类:
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;
}
}