【问题标题】:How to draw around a texture in LibGDX?如何在 LibGDX 中绘制纹理?
【发布时间】:2017-10-09 20:22:36
【问题描述】:

我正在 libgdx 中制作一个游戏,其中主角身上有一盏灯,而光线没有到达的地方应该是黑暗的,我正在使用 SpriteBash 中的 setBlendFunction 来模拟光线。我的问题是我不知道如何才能使光纹理周围变暗,我可以调整光纹理的大小以适应整个屏幕,但这会很草率并且在代码中不方便。有没有人有任何想法?谢谢你。

这是显示我的问题的游戏图片

【问题讨论】:

    标签: java libgdx textures


    【解决方案1】:

    为什么不使用Box2dlight 来满足您的要求。在我看来,您可以使用着色器进行照明,但您想要的效果只能通过使用 box2d body 和 box2dlight 来实现。

    public class MyGdxGame extends ApplicationAdapter implements InputProcessor{
    
        SpriteBatch batch;
        OrthographicCamera cam;
    
        RayHandler rayHandler;
        World world;
        Texture texture;
        PointLight box2d;
    
        Box2DDebugRenderer renderer;
        Vector3 vector3;
        Array<Body> bodies;
    
        @Override
        public void create() {
    
            Pixmap pixmap=new Pixmap(1, 1, Pixmap.Format.RGBA8888);
            pixmap.setColor(Color.WHITE);
            pixmap.fillRectangle(0,0, pixmap.getWidth(), pixmap.getHeight());
    
            world=new World(new Vector2(0,-9.8f),false);
            rayHandler=new RayHandler(world);
    
            renderer=new Box2DDebugRenderer();
            bodies=new Array<>();
            vector3=new Vector3();
    
            batch=new SpriteBatch();
            cam = new OrthographicCamera();
            cam.setToOrtho(true,40,64);
    
            texture=new Texture(pixmap);
            rayHandler.setAmbientLight(0,0,0,.5f);
    
            box2d=new PointLight(rayHandler, 100, new Color(1,1,1,1), 25, 10, 10);
            Gdx.input.setInputProcessor(this);
    
    
            {
                BodyDef bodyDef = new BodyDef();
                bodyDef.position.set(20, 10);
                bodyDef.type = BodyDef.BodyType.StaticBody;
    
                PolygonShape p = new PolygonShape();
                p.setAsBox(8, 1.5f);
    
                FixtureDef fixtureDef = new FixtureDef();
                fixtureDef.shape = p;
    
                Body body = world.createBody(bodyDef);
                body.createFixture(fixtureDef);
    
                Sprite sprite=new Sprite(texture);
                sprite.setSize(8*2,1.5f*2);
                body.setUserData(sprite);
            }
    
            {
                BodyDef bodyDef = new BodyDef();
                bodyDef.position.set(20, 40);
                bodyDef.type = BodyDef.BodyType.StaticBody;
    
                PolygonShape p = new PolygonShape();
                p.setAsBox(8, 1.5f);
    
                FixtureDef fixtureDef = new FixtureDef();
                fixtureDef.shape = p;
    
                Body body = world.createBody(bodyDef);
                body.createFixture(fixtureDef);
    
                Sprite sprite=new Sprite(texture);
                sprite.setSize(8*2,1.5f*2);
    
                body.setUserData(sprite);
            }
        }
    
        @Override
        public void render() {
    
            Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
            Gdx.gl.glClearColor(1,1,1,1);
    
            world.step(1/60f,4,6);
    
            renderer.render(world,cam.combined);
            batch.setProjectionMatrix(cam.combined);
    
            batch.begin();
            world.getBodies(bodies);
    
            for (Body body:bodies){
                Sprite sprite=(Sprite) body.getUserData();
                sprite.setPosition(body.getPosition().x-sprite.getWidth()/2,body.getPosition().y-sprite.getHeight()/2);
                sprite.draw(batch);
            }
    
            batch.draw(texture,100,100);
            batch.end();
    
            rayHandler.setCombinedMatrix(cam);
            rayHandler.updateAndRender();
        }
    
        @Override
        public void resize(int width, int height) {
    
        }
    
        @Override
        public void dispose() {
            batch.dispose();
            rayHandler.dispose();   
        }
    
        @Override
        public boolean keyDown(int keycode) {
            return false;
        }
    
        @Override
        public boolean keyUp(int keycode) {
            return false;
        }
    
        @Override
        public boolean keyTyped(char character) {
            return false;
        }
    
        @Override
        public boolean touchDown(int screenX, int screenY, int pointer, int button) {
            return false;
        }
    
        @Override
        public boolean touchUp(int screenX, int screenY, int pointer, int button) {
            return false;
        }
    
        @Override
        public boolean touchDragged(int screenX, int screenY, int pointer) {
    
            vector3.set(screenX,screenY,0);
            Vector3 v=cam.unproject(vector3);
            box2d.setPosition(v.x,v.y);
            return false;
        }
    
        @Override
        public boolean mouseMoved(int screenX, int screenY) {
            return false;
        }
    
        @Override
        public boolean scrolled(int amount) {
            return false;
        }
    }
    

    输出是:

    【讨论】:

    • 谢谢,但我尽量避免使用 box2d。
    • 使用box2d可以轻松满足您的要求,如果您以适当的方式玩物理体,box2d也不错。
    • 我同意,但现在我要走另一条路。谢谢你的回答。
    【解决方案2】:

    这通常使用 FrameBuffer 完成。

    您希望在resize() 方法中根据需要进行实例化和重新创建,以便它始终与屏幕/窗口的大小相匹配。在resize():

    if (frameBuffer != null && (frameBuffer.getWidth() != width || frameBuffer.getHeight() != height)){
        frameBuffer.dispose();
        frameBuffer = null;
    }
    if (frameBuffer == null){
        try {
            frameBuffer = new FrameBuffer(Pixmap.Format.RGBA8888, width, height, false);
        } catch (GdxRuntimeException e){ // device doesn't support 8888
            frameBuffer = new FrameBuffer(Pixmap.Format.RGB565, width, height, false);
        }
    }
    

    render(),在你的游戏中绘制任何东西之前,你首先在frameBuffer上绘制阴影贴图:

    frameBuffer.begin();
    Gdx.gl.glClearColor(/* ... */); // This will be your ambient color, a dark color, like gray
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    
    spriteBatch.setProjectionMatrix(camera.combined); // same camera as your game scene
    spriteBatch.setBlendFunction(GL20.GL_ONE, GL20.GL_ONE); //additive blending
    spriteBatch.begin();
    
    // draw light sprites, such as a white circle where your character is standing
    
    spriteBatch.end();
    frameBuffer.end();
    

    然后正常绘制你的游戏场景。在绘制之前,不要忘记将混合功能改回您通常使用的功能(默认为 GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)。最后,在游戏上绘制阴影贴图:

    // Use identity matrix so you don't have to worry about lining up the frame buffer texture
    spriteBatch.setProjectionMatrix(spriteBatch.getProjectionMatrix().idt());
    
    // Set multiplicative blending for shadows
    spriteBatch.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_COLOR); 
    
    spriteBatch.begin();
    spriteBatch.draw(frameBuffer.getColorBufferTexture(), -1, 1, 2, -2); //dimensions for full screen with identity matrix
    spriteBatch.end();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-04
      • 1970-01-01
      • 1970-01-01
      • 2014-08-06
      • 2014-01-28
      • 2014-09-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多