0
\$\begingroup\$

Recently I have read that you can work with 2 cameras whenever you involve Box2d, which only works in meters.

In my Renderer class, I receive all the entities in the game and then draw them. I work with ashley library so all my entities are a formed by components.

Now, in my renderer method I check if the current Entity has BodyComponent. If true, then it draws the Sprite in the physicsCam, who has a Viewport of meters. Otherwise, it will just draw the Sprite in sceneCam, which has a Viewport of pixels.

My problem is I try to draw the Sprite according to the Body's position in meters, but it is drawn not exactly where the body is.

NOTE: I also have PhysicsDebugSystem which basically just call the DebugRenderer.render() method.

Here is my RenderSystem class:

package engine.systems;

import com.badlogic.ashley.core.Component;
import com.badlogic.ashley.core.ComponentMapper;
import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.Family;
import com.badlogic.ashley.systems.IteratingSystem;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.utils.Array;

import engine.Values;
import engine.components.BodyComponent;
import engine.components.SpriteComponent;
import engine.components.TransformComponent;

public class RenderSystem extends IteratingSystem{

    private SpriteBatch batch;
    private Array<Entity> renderQueue;
    private OrthographicCamera sceneCam;
    private OrthographicCamera physicsCam;
    private ComponentMapper<SpriteComponent> txt;
    private ComponentMapper<TransformComponent> trs;

    @SuppressWarnings("unchecked")
    public RenderSystem(SpriteBatch batch) {
        super(Family.all(TransformComponent.class, SpriteComponent.class).get());
        txt = ComponentMapper.getFor(SpriteComponent.class);
        trs = ComponentMapper.getFor(TransformComponent.class);
        sceneCam = new OrthographicCamera(Values.WIDTH, Values.HEIGHT);
        sceneCam.setToOrtho(false);
        physicsCam = new OrthographicCamera(Values.WIDTH, Values.HEIGHT);
        physicsCam.setToOrtho(false);
        renderQueue = new Array<Entity>();
        this.batch = batch;
    }

    @Override
    public void update(float deltaTime) {
        super.update(deltaTime);
        Gdx.gl.glClearColor(230/255f, 242/255f, 242/255f, 0);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        sceneCam.update();
        physicsCam.update();
        batch.enableBlending();
        batch.begin();
        for (Entity entity : renderQueue) {
            Component comp = entity.getComponent(BodyComponent.class);
            if(comp == null) {
                batch.setProjectionMatrix(sceneCam.combined);
            } else {
                batch.setProjectionMatrix(physicsCam.combined);
            }
            SpriteComponent texture = txt.get(entity);
            TransformComponent transform = trs.get(entity);
            if (texture.region == null || transform.isHidden) {
                continue;
            }
            texture.region.setPosition(transform.position.x, transform.position.y);
            texture.region.setRotation(transform.rotation);
            texture.region.setScale(transform.scale.x, transform.scale.y);
            texture.region.draw(batch);
        }
        batch.end();
        renderQueue.clear();
    }

    @Override
    protected void processEntity(Entity entity, float deltaTime) {
        renderQueue.add(entity);
    }

    public OrthographicCamera getCamera() {
        return sceneCam;
    }

}

In my GameWorld class I construct the ball in this method:

public void initBall() {
        Entity entity = new Entity();
        float x = Values.WIDTH/2*Values.PPM;
        float y = Values.HEIGHT*Values.PPM;
        SpriteComponent txt = new SpriteComponent();
        txt.region = skin.getSprite("soccerball");
        txt.region.setSize(Values.BALL_WIDTH, Values.BALL_HEIGHT);
        entity.add(txt);
        TransformComponent trs = new TransformComponent();
        trs.isHidden = false;
        trs.position.x = x;
        trs.position.y = y;
        entity.add(trs);
        BodyComponent bc = new BodyComponent();
        BodyDef bodyDef = new BodyDef();
        // Set our body to dynamic
        bodyDef.type = BodyDef.BodyType.DynamicBody;

        // Set our body's starting position in the world
        bodyDef.position.set(x, y+Values.BALL_HEIGHT/2);
        bc.body = world.createBody(bodyDef);
        bc.body.applyAngularImpulse(50f, true);

        CircleShape circle = new CircleShape();
        circle.setRadius(Values.BALL_WIDTH/2f);
        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.shape = circle;
        fixtureDef.density = 20f;
        fixtureDef.friction = 0.4f;
        fixtureDef.restitution = 0.6f;
        bc.body.createFixture(fixtureDef);
        circle.dispose();
        entity.add(bc);
        engine.addEntity(entity);
    }

Here's the screenshot I took during the simulation: enter image description here

\$\endgroup\$
-1
\$\begingroup\$

You can instantiate as many OrthographicCameras as you want. However, each frame will be rendered using only one camera. You can make it so every other frame renders with another view point (e.q. camera) in the world.

For example, we have a blue team playing soccer against a red team. We can instantiate two camera's - one that looks at the field from the blue teams' perspective and one that looks at the field from the red teams' perspective.

In the example above we can switch between the two camera's on-the-fly:

@Override
public void update(float deltaTime) {
    super.update(deltaTime);
    Gdx.gl.glClearColor(230/255f, 242/255f, 242/255f, 0);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    if (blueTeamPerspective) {
        blueCamera.update();
        batch.begin();
        batch.setProjectionMatrix(blueCamera.combined);
    } else if (redTeamPerspective) {
        redCamera.update();
        batch.begin();
        batch.setProjectionMatrix(redCamera.combined);
    }

    batch.end();
}

I hope this helps!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.