Box2d 在不同的屏幕尺寸下照亮不同的行为

问题描述 投票:0回答:1

我尝试玩一下灯光,但很快我就发现了我不理解的奇怪行为。谁能向我解释一下为什么会发生这种情况,如果是故意的,或者我做错了什么。

在第一张图片中,光线几乎穿过障碍物(这也很奇怪)。

当屏幕尺寸更改为更窄的宽度时,光线会更多地穿过障碍物。

红色背景是“黑条”,因为我使用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();
    }
}

非常感谢。如果需要更多信息,请告诉我,我将编辑问题。

java libgdx light box2dlights
1个回答
0
投票

确认@Mikhail Churbanov 所说的话并带来更多的知名度。文档提到我们有责任在调整大小时更新视口。我认为这是适合视口的点。我很困惑。

无论如何,我最终在 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秒),否则有时你会在没有应用灯光的情况下在视口上看到一条1px的线。

这样做给我带来了复杂的感觉。我不太相信这是这样做的方法,嘿,它有效!

© www.soinside.com 2019 - 2024. All rights reserved.