Прежде чем я решил, что хочу использовать box2d для всей своей игровой физики, я настроил все неанимированные формы с помощью shaperenderer. Я преобразовал свой мир и форму box2d в метры с масштабом 32 ppm, но все мои обычные формы по-прежнему нарисованы с помощью пикселей.
Поскольку мой круг box2d был масштабирован вместе с камерой, он отлично отображается с нужным размером. Однако все фигуры, которые я нарисовал с помощью пикселей с помощью shaperenderer, находятся вне поля зрения.
Насколько я понимаю, я должен иметь возможность просто масштабировать все размеры исходных форм с помощью PPM, поскольку я уже масштабировал камеру?
public class Controller extends Game {
public OrthographicCamera cam;
public ShapeRenderer shape;
public ShapeRenderer circle;
public FitViewport viewport;
public Stage stage;
public World world;
public Body ball;
public Box2DDebugRenderer box2DDebugRenderer;
@Override
public void create() {
cam = new OrthographicCamera();
viewport = new FitViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), cam);
cam.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
shape = new ShapeRenderer();
circle = new ShapeRenderer(); //balls shot from cannon
world = new World(new Vector2(0, 0), true);
box2DDebugRenderer = new Box2DDebugRenderer();
setScreen(new GameScreen(this));
//setScreen(new TitleScreen(this));
}
@Override
public void dispose() {
shape.dispose();
stage.dispose();
circle.dispose();
box2DDebugRenderer.dispose();
world.dispose();
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void resize(int width, int height) {
viewport.update(width, height);
}
public Body createBall(){
Body bBody;
BodyDef def = new BodyDef();
def.type = BodyDef.BodyType.DynamicBody;
def.position.set(500,500);
def.fixedRotation = true;
bBody = world.createBody(def);
return bBody;
}
}
А вот фактический экран игры, на котором реализованы все исходные формы и формы box2d:
import static com.mygdx.game.Utils.Constants.PPM;
public class GameScreen extends ScreenAdapter {
Controller game;
//x-axis length for top/bottom bar
private float goalWidth;
//y-axis height for back bar
private float goalHeight;
private float goalPostThickness;
//Screen height and width
private float screenWidth;
private float screenHeight;
//How far down/up posts are from edge of screen
private float goalPostTopOffset;
private float goalPostBottomOffset;
private float cannonOriginX; //Variables used for starting position of balls
private float cannonOriginY;
float ballX;
float ballY;
public GameScreen (Controller game){
this.game = game;
}
@Override
public void show(){
game.ball = game.createBall();
// Create a circle shape and set its radius to 6
CircleShape circle = new CircleShape();
circle.setRadius(32/2/PPM);
// Create a fixture definition to apply our shape to
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.density = 0.5f;
fixtureDef.friction = 0.4f;
fixtureDef.restitution = 0.6f; // Make it bounce a little bit
// Create our fixture and attach it to the body
Fixture fixture = game.ball.createFixture(fixtureDef);
circle.dispose();
}
@Override
public void render(float delta){
//Logic
screenWidth = Gdx.graphics.getWidth();
screenHeight = Gdx.graphics.getHeight();
goalPostTopOffset = screenHeight/7;
goalPostBottomOffset = goalPostTopOffset * 3;
goalHeight = screenHeight - (goalPostTopOffset + goalPostBottomOffset);
goalWidth = screenWidth / 6;
goalPostThickness = screenWidth / 75;
cannonOriginX = goalWidth / 2; //Variables used for starting position of balls
cannonOriginY = (goalPostThickness*5) / 2;
ballX = 0 + cannonOriginX;
ballY = (goalPostBottomOffset - (goalPostBottomOffset / 4)) + cannonOriginY;
game.world.step(1/60f, 6, 2);
//Draw
game.cam.update();
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
game.box2DDebugRenderer.render(game.world, game.cam.combined.scl(PPM));
game.shape.setProjectionMatrix(game.cam.combined);
drawNonAnimated();
drawAnimated();
}
@Override
public void hide(){
}
//draws stationary objects such as goal posts
public void drawNonAnimated(){
//Top goal bar
game.shape.setColor(1, 1, 1, 1);
game.shape.begin(ShapeRenderer.ShapeType.Filled);
game.shape.rect(screenWidth - goalWidth, screenHeight - goalPostTopOffset, goalWidth, goalPostThickness);
game.shape.end();
//Bottom goal bar
game.shape.setColor(1, 1, 1, 1);
game.shape.begin(ShapeRenderer.ShapeType.Filled);
game.shape.rect(screenWidth - goalWidth, goalPostBottomOffset, goalWidth, goalPostThickness);
game.shape.end();
//Back goal bar
game.shape.setColor(1, 1, 1, 1);
game.shape.begin(ShapeRenderer.ShapeType.Filled);
game.shape.rect(screenWidth - goalPostThickness, goalPostBottomOffset, goalPostThickness, goalHeight);
game.shape.end();
//Cannon platform
game.shape.setColor(1, 1, 1, 1);
game.shape.begin(ShapeRenderer.ShapeType.Filled);
game.shape.rect(0, goalPostBottomOffset - (goalPostBottomOffset / 4),goalWidth, goalPostThickness*2);
game.shape.end();
//Cannon
game.shape.setColor(1, 1, 1, 1);
game.shape.begin(ShapeRenderer.ShapeType.Filled);
game.shape.rect(0, goalPostBottomOffset - (goalPostBottomOffset / 4), cannonOriginX,
cannonOriginY, goalWidth, goalPostThickness*5, 1, 1, 45);
game.shape.end();
}
public void drawAnimated(){
//Ball(s)
game.circle.setColor(1, 1, 1, 1);
game.circle.begin(ShapeRenderer.ShapeType.Filled);
game.circle.circle(ballX, ballY, goalPostThickness * 2.5f);
game.circle.end();
game.cam.update();
ballX += 1;
}
}
Как я упоминал ранее, форма круга, визуализированная с помощью box2d, отлично отображается в масштабе PPM. Однако все фигуры, которые я нарисовал с помощью shaperenderer, находятся за пределами экрана.
Спасибо за ответ. Я использую fitviewport, но проблемы с масштабированием все еще возникают. Окно просмотра решало проблемы с разным соотношением сторон между устройствами, но объекты в моей игре по-прежнему рендерились слишком большими / слишком маленькими. Это было проблемой, так как игра становилась очень простой / сложной с объектами разного размера. Не уверен, что так должно быть, и я просто сделал что-то не так.
Одна из возможностей - Constants.PPM. Если это как-то изменится, это может быть проблемой. (Если это общедоступный статический финал, все должно быть в порядке). Еще вы можете использовать высоту и ширину экрана для определения размеров и прочего. Вы можете попробовать сделать это другим способом, например, используя ограничивающую рамку, которая не меняет и не использует константы ширины и высоты, которые вы передаете в ExtendsViewport. Уловка состоит в том, чтобы никогда не использовать Gdx.graphics.getWidth () или getHeight () для чего-то, кроме пользовательского интерфейса или чего-то, что не влияет на игровой процесс.
Кроме того, если вы используете сцену, вам не нужно хранить экземпляр камеры или области просмотра. Вы всегда можете выполнить stage.getViewport (). GetCamera (), если вам это нужно.




Я не собираюсь отвечать на ваш вопрос, потому что у меня нет опыта работы с box2d, но я рекомендую вам не беспокоиться о масштабировании всего до размера экрана. Я рекомендую вам поместить все, что вы хотите визуализировать, на сцену, а затем использовать ExtendsViewport, чтобы вам не приходилось беспокоиться о масштабировании, потому что это Viewport всегда будет иметь одинаковую высоту или одинаковую ширину. Если вы используете FitViewport, я считаю, что он всегда будет отображать одно и то же, независимо от разрешения. Есть много окон просмотра, которые вы можете использовать, чтобы упростить себе задачу.