2015-01-04 2 views
0

Я пытаюсь избавиться от необходимости масштабировать все координаты на моих спрайтах при использовании Box2D и LibGDX.Почему простое масштабирование в LibGDX и Box2D работает правильно?

Вот настройки для моего окна просмотра и физики мира:

// Used to create an Extend Viewport 
public static final int MIN_WIDTH = 480; 
public static final int MIN_HEIGHT = 800; 
// Used to scale all sprite's coordinates 
public static final float PIXELS_TO_METERS = 100f; 
// Used with physics world. 
public static final float GRAVITY = -9.8f; 
public static final float IMPULSE = 0.15f; 
world.setGravity(new Vector2(0f, GRAVITY)); 

Когда я применить линейный импульс к моему характеру (когда пользователь нажимает на экран) все работает отлично:

body.setLinearVelocity(0f, 0f); 
body.applyLinearImpulse(0, IMPULSE, body.getPosition().x, body.getPosition().y, true); 

Тело имеет плотность 0f, но изменение этого параметра до 1f или даже 100f не имеет никакого реального эффекта.

Это означает, что я должен масштабировать все места спрайтов в методе рисования на PIXELS_TO_METERS. Я подумал (возможно, неправильно), что могу просто масштабировать GRAVITY и IMPULSE на PIXELS_TO_METERS и заставить его работать точно так же. Кажется, это не так. Гравитация кажется очень маленькой, и применение импульса почти не имеет никакого эффекта.

// Used to scale all sprite's coordinates 
public static final float PIXELS_TO_METERS = 1f; 
// Used with physics world. 
public static final float GRAVITY = -9.8f * 100; 
public static final float IMPULSE = 0.15f * 100; 

Итак:

1) почему не просто расширения все значения заставить его работать так же?

2) Есть ли лучший способ сделать это?

ответ

1

Похоже, вы слишком усложняете свой дизайн, используя некоторые воображаемые элементы пикселей (я сомневаюсь, что это фактические пиксели, о которых вы говорите). Я бы посоветовал вам использовать значимые единицы, например meters, и придерживаться его. Таким образом, используйте счетчики для всех координат (включая ваш виртуальный видовой экран). Таким образом, практически изменить вам код, чтобы выглядеть следующим образом:

// Used to create an Extend Viewport 
public static final float MIN_WIDTH = 4.8f; // at least 4.8 meters in width is visible 
public static final float MIN_HEIGHT = 8.0f; // at least 8 meter in height is visible 

Это полностью устраняет необходимость масштабирования метра в ваши мнимые единицы пикселей. Фактическое масштабирование от ваших единиц (размер виртуального видового экрана) до screen (values between -1 and +1) осуществляется с помощью camera. Вам не нужно думать о масштабировании единиц в вашем дизайне.

Обязательно удалите PIXELS_TO_METERS постоянный (не устанавливайте его на 1f, это только усложняет ваш код без усиления) и убедитесь, что вы вообще не используете воображаемые пиксели в своем коде. Последний включает в себя все спрайты, которые вы создаете, без явного указания его размера в метрах.

По-прежнему возможно «масштабировать» ваши юниты (в вашей игровой логике) по сравнению с единицами СИ по уважительным причинам. Например, при создании космической игры вы можете использовать очень большие числа при использовании счетчиков. Как правило, вы хотите сохранить значения около 1f, чтобы избежать ошибок с плавающей запятой. В этом случае может быть полезно использовать, например, декаметров (x10), гектометров (x100) или километров (x1000). Если вы это сделаете, убедитесь, что вы последовательны. Это может помочь добавить единицы в комментарии, чтобы вы не забыли правильно масштабировать (например, GRAVITY = -0.0098f; // kilometer per second per second).

+0

Благодарим вас за разъяснение, но это все еще не имеет для меня никакого смысла. В моей попытке просто умножить все значения мира физики на 100, не в основном ли я говорю, что 1 пиксель = 1 метр? Итак, мой 'MIN_WIDTH = 480f // метров' и ​​мой' MIN_HEIGHT = 800f // метров'. Установка моего параметра «GRAVITY = -980f» должна быть установлена ​​на «-980 метров в секунду в секунду»? Это мое понимание этого. В любом случае - вы по существу взяли мои «MIN_WIDTH» и «MIN_HEIGHT» и разделили их на 100. Таким образом, если я установил свои «PIXELS_TO_METERS» в 1, то это должно быть по сути одно и то же, но это не так. !Работа. – Townsfolk

+0

Извините, закончилось пространство. Установка моего масштаба на 1 (практически удаление шкалы) нарушает его. Все очень неровно. Я предполагаю, что мне нужно установить конфигурацию в 100 x этих значений на моем рабочем столе и в Android Launcher, правильно? Ужасно жаль, я знаю, что здесь что-то не хватает, не могли бы вы добавить некоторые биты кода о том, как использовать эти новые значения? Я, очевидно, не использую их правильно. – Townsfolk

+0

Попытайтесь не думать в своих воображаемых пикселях (например, когда вы сравниваете свои воображаемые пиксели с метрами (вы говорите «1 пиксель = 1 метр»), вы просто слишком усложняете вещи). Для каких значений вам нужно больше разъяснений? Вы не указали достаточно подробных сведений о том, как вы используете значения в своем вопросе, чтобы показывать фактические изменения в вашем коде. Если вы столкнулись с проблемой (пикселированной?), Тогда подумайте о предоставлении достаточной информации, необходимой для решения этой проблемы. В любой пусковой установке нет конфигурации, которая должна быть настроена на использование значимых единиц вместо ваших воображаемых пикселей. – Xoppa

0

Я реализовал, как это:

// in declaration 
float PIXELS_TO_METERS = 32; // in my case: 1m = 32 pixels 
Matrix4 projection = new Matrix4(); 

// in creation 
viewport = new FitViewport(
     Application.width 
     , Application.height 
     , Application.camera); 
viewport.apply(); 

// set vieport dimensions 
camera.setToOrtho(false, gameWidth, gameHeight); 

// in render 
projection.set(batch.getProjectionMatrix()); 
projection.scl(PIXELS_TO_METERS); 
box2dDebugRenderer.render(world, projection); 

// in player body creation 
BodyDef bodyDef = new BodyDef(); 
bodyDef.type = BodyDef.BodyType.DynamicBody; 
bodyDef.position.x = getPosition().x/PIXELS_TO_METERS; 
bodyDef.position.y = getPosition().y/PIXELS_TO_METERS; 

CircleShape shape = new CircleShape(); 
shape.setRadius((getBounds().width * 0.5f)/PIXELS_TO_METERS); 

// in player update 
setPosition(
    body.getPosition().x * PIXELS_TO_METERS - playerWidth, 
    body.getPosition().y * PIXELS_TO_METERS - playerHeight); 

Так установить пикселы метр в Box2D методы, которые вы должны разделить пиксель-позицию по PIXELS_TO_METERS и установить метр пиксели в позиции игрока нужно умножить Box2D значения от PIXELS_TO_METERS.

Правильно настройте PIXELS_TO_METERS, сколько пикселей на ваших экранах соответствует 1 метру.

Удачи.