[libGDX] [box2D] Scale a Sprite to a Body

Hi, I’m tryin to put a Sprite over my bodyplayer, but I can’t…

My Sprite moves too fast…

This is my code:

[spoiler]


package com.me.mygdxgame;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
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.Fixture;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;

public class ScreenGame implements Screen{
	
	public BodyDef bDefPlayer;
	public Body bPlayer;
	public Fixture fPlayer;
	public FixtureDef fDefPlayer;
	public PolygonShape shape;
	
	public BitmapFont font;
	
	public SpriteBatch spriteBatch;
	
	public World world;
	public OrthographicCamera camera;
	public Box2DDebugRenderer renderer;
	
	public MyGdxGame game;
	
	public EntityPlayerController playerController;
	
	public Texture texture;
	public Sprite sprite;
	
	public static float WORLD_TO_BOX = 0.01f;
	public static float BOX_TO_WORLD = 100.0f;
	
	public ScreenGame(MyGdxGame game){
		this.game = game;
	}
	
	@Override
	public void render(float delta) {
		// TODO Auto-generated method stub
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
		Gdx.gl.glClearColor(0, 0, 0, 1);
		
		world.step(delta, 6, 6);
		renderer.render(world, camera.combined);
		
		playerController.jump();
		
		spriteBatch.setProjectionMatrix(camera.combined);
		spriteBatch.begin();
		sprite.setPosition(BOX_TO_WORLD * bPlayer.getPosition().x - sprite.getWidth() / 2,
				BOX_TO_WORLD * bPlayer.getPosition().y - sprite.getHeight() / 2);
		sprite.draw(spriteBatch);
		spriteBatch.end();
		
		playerController.drawFont();
		
		camera.position.x = bPlayer.getPosition().x;
		camera.position.y = bPlayer.getPosition().y;
		camera.update();
		
		if(Gdx.input.isKeyPressed(Keys.T)) camera.zoom++;
		else if(Gdx.input.isKeyPressed(Keys.Y)) camera.zoom--;
		
		if(camera.zoom >= 40) camera.zoom = 40;
		else if(camera.zoom <= 1) camera.zoom = 1;
		
	}

	@Override
	public void resize(int width, int height) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void show() {
		// TODO Auto-generated method stub
		world = new World(new Vector2(0, -60), true);
		camera = new OrthographicCamera(Gdx.graphics.getWidth() / 2,
				Gdx.graphics.getHeight() / 2);
		renderer = new Box2DDebugRenderer();
		font = new BitmapFont();
		spriteBatch = new SpriteBatch();
		
		createGround();
		createPlayer();
		
		playerController = new EntityPlayerController(this, world, bPlayer, fPlayer, fDefPlayer, camera);
		
		texture = new Texture(Gdx.files.internal("images/Cuadrado.png"));
		sprite = new Sprite(texture);
		bPlayer.setUserData(sprite);
		
		sprite.setPosition(BOX_TO_WORLD * bPlayer.getPosition().x - sprite.getWidth() / 2,
				BOX_TO_WORLD * bPlayer.getPosition().y - sprite.getHeight() / 2);
		
		/*jumperSprite.setPosition(
				PIXELS_PER_METER * jumper.getPosition().x
						- jumperSprite.getWidth() / 2,
				PIXELS_PER_METER * jumper.getPosition().y
						- jumperSprite.getHeight() / 2);
		jumperSprite.draw(spriteBatch);*/
	
	}

	@Override
	public void hide() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void pause() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void resume() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void dispose() {
		// TODO Auto-generated method stub
		world.dispose();
		font.dispose();
		spriteBatch.dispose();
	}
	
	public Body createPlayer(){
		bDefPlayer = new BodyDef();
		bDefPlayer.position.set(new Vector2(-40, 0));
		bDefPlayer.type = BodyType.DynamicBody;
		
		bPlayer = world.createBody(bDefPlayer);
		bPlayer.setFixedRotation(true);
		bPlayer.setBullet(true);
		bPlayer.setAwake(true);
		
		shape = new PolygonShape();
		shape.setAsBox(5, 10);
		
		fDefPlayer = new FixtureDef();
		fDefPlayer.density = 0f;
		fDefPlayer.restitution = 0f;
		fDefPlayer.friction = 0f;
		fDefPlayer.shape = shape;
		
		fPlayer = bPlayer.createFixture(fDefPlayer);
		
		shape.dispose();
		
		return bPlayer;
	}

	public void createGround(){
		BodyDef bdground = new BodyDef();
		bdground.position.set(0, -40);
		
		Body bground = world.createBody(bdground);
		
		PolygonShape ps = new PolygonShape();
		ps.setAsBox(Gdx.graphics.getWidth(), 10);
		
		Fixture fground = bground.createFixture(ps, 0.5f);
		
		ps.dispose();
	}
	
.


[/spoiler]

I don’t know scale a Sprite… I have try it so many times but I can’t WTF!!!

Can someone help me?

Thanks.

I’m not 100% sure but aren’t you supposed to give the Box2D renderer its own projection matrix?

For example in your render code (Matrix debugMatrix was declared earlier):

debugMatrix.set(cam.combined);
debugMatrix.scale(BOX_TO_WORLD, BOX_TO_WORLD, 1f);
renderer.render(world, debugMatrix);

I tryed put it but now the world don’t render… :-X

Why are you using BOX_TO_WORLD-value if you are using a camera?
You are rendering the box2d-world with the same camera as you do it with your sprite.


      sprite.setPosition(BOX_TO_WORLD * bPlayer.getPosition().x - sprite.getWidth() / 2,
            BOX_TO_WORLD * bPlayer.getPosition().y - sprite.getHeight() / 2);

Just remove BOX_TO_WORLD.
Steps:

  1. you zoom in
  2. render box2dworld
  3. modify the position with BOX_TO_WORLD value
  4. render sprite
    -> can’t work, the camera already did it for you, step 3 isn’t needed.
    think of a straight line in a coordinate system.
    y = x
    What you do is y = BOX_TO_WORLD*x
    -> if(box_to_world > 1) the sprite is more distant to Zero
    -> if(box_to_world < 1) the sprite is closer to Zero

In my opinion there is no reason for a BOX_TO_WORLD value, if you want a smaller box2d-world use camera and zoom in and it will look the same.
I know that a lot of tutorials are using such values, but I don’t agree with them.
hope it helps