Box2d Освещение разного поведения с разным размером экрана
Я попытался немного поиграть с освещением, но очень быстро наткнулся на странное поведение, которое я не понимаю. Может ли кто-нибудь объяснить мне, почему это происходит, если это нарочно, или я делаю что-то не так.
На первом изображении свет проходит через препятствие (что тоже странно).
Когда размер экрана изменяется на меньшую ширину, свет проходит еще больше через препятствие.
Красный фон - "черная полоса", так как я использую FitViewport. "Реальный" мир имеет badlogic.jpg повсюду.
На следующих рисунках вы можете увидеть, как это работает без рендеринга света - экран отображает один и тот же мир независимо от размера экрана (только масштабированный). Вот как я ожидал бы, что это будет работать даже с освещением.
Проект стандартный, сгенерированный генератором проекта libgdx. Весь мой код только один класс, поэтому я могу загрузить его здесь:
package com.gobanit.sandbox.main;
import com.badlogic.ashley.core.Engine;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
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.Box2DDebugRenderer;
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.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
import box2dLight.PointLight;
import box2dLight.RayHandler;
public class SandboxTestGame extends ApplicationAdapter {
SpriteBatch batch;
World world;
Engine engine;
Viewport viewport;
Box2DDebugRenderer debugRenderer;
Texture texture;
RayHandler rayHandler;
Body playerBody;
@Override
public void create () {
batch = new SpriteBatch();
texture = new Texture(Gdx.files.internal("badlogic.jpg"));
engine = new Engine();
world = new World(new Vector2(0, 0), true);
viewport = new FitViewport(1000, 500);
viewport.getCamera().position.set(new Vector3(0, 0, 0));
debugRenderer = new Box2DDebugRenderer();
rayHandler = new RayHandler(world);
rayHandler.setShadows(true);
createPlayerBody();
createObstacleBody();
PointLight l1 = new PointLight(rayHandler, 100, null, 500, 0, 0);
l1.attachToBody(playerBody);
//l1.setSoft(true);
//new PointLight(rayHandler, 100, null, 500, 0, 200);
}
private void createObstacleBody() {
BodyDef bodyDef = new BodyDef();
bodyDef.position.add(new Vector2(-10000, 100));
bodyDef.type = BodyType.StaticBody;
Body body = world.createBody(bodyDef);
FixtureDef fixDef = new FixtureDef();
PolygonShape shape = new PolygonShape();
shape.set(new float[] {0f,0f,0f,40f,20000f,40f,20000f,0f});
fixDef.shape = shape;
body.createFixture(fixDef);
body.setActive(true);
}
private void createPlayerBody() {
BodyDef bodyDef = new BodyDef();
bodyDef.position.add(new Vector2(100, 50));
bodyDef.type = BodyType.DynamicBody;
Body body = world.createBody(bodyDef);
FixtureDef fixDef = new FixtureDef();
CircleShape circle = new CircleShape();
circle.setRadius(20);
fixDef.shape = circle;
body.createFixture(fixDef);
body.setActive(true);
playerBody = body;
}
@Override
public void render () {
update();
draw();
}
private void draw() {
Gdx.gl.glClearColor(100, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
viewport.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.setProjectionMatrix(viewport.getCamera().combined);
batch.begin();
batch.draw(texture, -1000, -1000, 2000, 2000);
batch.end();
debugRenderer.render(world, viewport.getCamera().combined);
rayHandler.setCombinedMatrix((OrthographicCamera) viewport.getCamera());
rayHandler.render();
}
private void update() {
world.step(1f/60f, 8, 3);
rayHandler.update();
if(Gdx.input.isKeyPressed(Keys.D)) {
//viewport.getCamera().position.add(new Vector3(1,0,0));
playerBody.applyForceToCenter(100, 0, true);
}
if(Gdx.input.isKeyPressed(Keys.A)) {
//viewport.getCamera().position.add(new Vector3(-1,0,0));
playerBody.applyForceToCenter(-100, 0, true);
}
if(Gdx.input.isKeyPressed(Keys.W)) {
//viewport.getCamera().position.add(new Vector3(0,1,0));
playerBody.applyForceToCenter(0, 100, true);
}
if(Gdx.input.isKeyPressed(Keys.S)) {
//viewport.getCamera().position.add(new Vector3(0,-1,0));
playerBody.applyForceToCenter(0, -100, true);
}
viewport.getCamera().position.set(new Vector3(playerBody.getPosition().x, playerBody.getPosition().y, 0));
}
@Override
public void dispose () {
batch.dispose();
texture.dispose();
world.dispose();
debugRenderer.dispose();
rayHandler.dispose();
}
}
Большое спасибо. Если потребуется дополнительная информация, скажите мне, и я отредактирую вопрос.
1 ответ
чтобы подтвердить то, что сказал @Михаил Чурбанов, и привлечь больше внимания. В документации упоминается, что мы несем ответственность за обновление области просмотра при изменении размера. Я думал, что это точка подходящего видового экрана. Я смущен.
В любом случае, я использовал эту функцию в своем resize() следующим образом:
if(viewport.getRightGutterWidth() > 0){
rayHandler.useCustomViewport(viewport.getRightGutterWidth()-5,viewport.getBottomGutterHeight()-5, (int)(height*SCREEN_RATIO)+10,height+10);
}else{
rayHandler.useCustomViewport(viewport.getRightGutterWidth()-5,viewport.getBottomGutterHeight()-5, width+10,(int)(width/SCREEN_RATIO)+10);
}
- Первое условие позволяет отличить вертикальное/горизонтальное изменение размера.
- использование getRightGutterWidth и getBottomGutterHeight для позиционирования области просмотра
- Использование коэффициента постоянной экрана для определения ширины или высоты в зависимости от случая
- И последнее, но не последнее: к сожалению, пришлось добавить крошечные отступы (5 и 10), иначе вы когда-нибудь увидите линию в 1 пиксель на випорте без включенного света.
Это вызывает у меня смешанные чувства. Я не особо верю, что это так, эй, это работает!