I want the sprite to get attached with a polygon shape body. When I run the code, both the sprite and body is getting displayed but they are not linked with each other. I looked at all the stack overflow questions but nothing helped.
I am creating this in a class and I am instantiating this from main class.
This is my code,
public SpriteButtons(PlayScreen screen) {
this.world = screen.getWorld();
batch = new SpriteBatch();
region = new TextureRegion(screen.getAtlas().findRegion("fireball"), 0, 0, 16, 16);
sprite = new Sprite(region);
this.gamecame = new OrthographicCamera();
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.StaticBody;
bodyDef.position.set(0, 0);
body = world.createBody(bodyDef);
PolygonShape shape = new PolygonShape();
shape.setAsBox(0.2f, 0.2f);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = 1f;
sprite.setSize(25, 25);
Fixture fixture = body.createFixture(fixtureDef);
}
public OrthographicCamera getGamecame() {
return gamecame;
}
public void render(float dt) {
sprite.setPosition(body.getPosition().x - sprite.getWidth()/2f,
body.getPosition().y - sprite.getHeight()/2f );
Gdx.app.log("" + body.getPosition().x, "");
batch.begin();
sprite.draw(batch);
setRegion(region);
batch.end();
}
My output is as follows,
The badlogic sprite is not getting attached with a polygon body and I am instantiating this class from main class and I will be calling this class render method from main class render method. Sorry if the question seems stupid. I don't know where I am missing this. Please help..!! Thanks in advance..!!
You must update sprite's position according to the body position in the render method - if you are not doing this how the sprite can know that it is attached to body?
Please notice that box2d body's origin is in the center of the body when libgdx'es sprite's origin is at it's left botto corner. Then you need to subtract half of width and height of body's position.
So this is what you've got to do:
//render()
sprite.setPosition(body.getPosition().x - sprite.getWidth()/2f,
body.getPosition().y - sprite.getHeight()/2f );
...
sprite.draw(batch);
...
try doing this
batch.draw(sprite, sprite.getX(), sprite.getY()); and change body's inital postion somewher above,so that it fall and you can check under gravity by initializing world like world = new World(new Vector2(0, -98f), true);
i'm using LibGDX and trying to learn box2D, but this units conversions are confusing me, what i think: i got a 256x256 pixels image and want to create a body representing this image, using the 1:32 scale, so everytime i want to pass values to the box2D scale i must divide it by 32 or mutiply by 1/32(it's the same equation), and everytime i want to get values from this world to pixel scale i must mutiply it by 32, but the problems still the same: can't get good simulations, i'll put my code here for you see how i'm doing things(i'll put the variables too so you can just ctrl+c and ctrl+v):
private SpriteBatch batch;
private ShapeRenderer srender;
private Texture img;
private World world;
private Body bad, bridge;
private OrthographicCamera cam, cam2;
private Box2DDebugRenderer render;
#Override
public void create () {
srender = new ShapeRenderer();
batch = new SpriteBatch();
img = new Texture("badlogic.jpg");
cam = new OrthographicCamera(500f, 500f);
cam.translate(250f, 250f);
cam.update();
//Used to draw the box2D world scaled to the pixels size
cam2 = new OrthographicCamera(500 * 0.03125f, 500 * 0.03125f);
cam2.translate(250f * 0.03125f, 250f * 0.03125f);
cam2.update();
render = new Box2DDebugRenderer();
world = new World(new Vector2(0f, -10f), true);
BodyDef bdef = new BodyDef();
bdef.type = BodyType.DynamicBody;
bad = world.createBody(bdef);
PolygonShape pshape = new PolygonShape();
pshape.setAsBox(img.getWidth() * 0.03125f, img.getHeight() * 0.03125f);
FixtureDef fdef = new FixtureDef();
fdef.shape = pshape;
bad.createFixture(fdef);
/*Criando a ponte*/
bdef.type = BodyType.StaticBody;
bridge = world.createBody(bdef);
pshape.setAsBox(500f * 0.03125f, 5f * 0.03125f);
bridge.createFixture(fdef);
bad.setTransform(new Vector2(250f * 0.03125f, 500f * 0.03125f) , 0);
bridge.setTransform(new Vector2(250f * 0.03125f, 0f * 0.03125f), 0);
batch.setProjectionMatrix(cam.combined);
srender.setProjectionMatrix(cam.combined);
}
#Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(img, (bad.getPosition().x - img.getWidth()/2 * 0.03125f) * 32,
(bad.getPosition().y - img.getHeight()/2 * 0.03125f) * 32);
batch.end();
render.render(world, cam2.combined);
srender.begin(ShapeRenderer.ShapeType.Filled);
srender.circle(250f, 500f, 5f);
srender.circle(250f, 0f, 5f);
srender.end();
world.step(1/60f, 6, 2);
}
if you run this code you will see that the box created still not fitting the image size, the image stop walking on the middle of the screen while it should stop only at the bottom, can anyone help me here? thanks for attention.
Ps:i have already heard about changing the viewport, but i'm still trying to learn this conversions, after that i'll go look for the viewports.
This is what I have:
...
private Array<Sprite> fireballFadeOutAnim;
private Array<Sprite> bucketFadeOutAnim;
private TextureAtlas fballAnimSheet;
private TextureAtlas bucketAnimSheet;
private Animation catch_animation;
private Animation visual_feedback;
private float elapsedTime = 0f;
...
#Override
public void create () {
...
fballAnimSheet = new TextureAtlas("animations/fireball_fadeout.txt");
bucketAnimSheet = new TextureAtlas("animations/bucket_fadeout.txt");
fireballFadeOutAnim = fballAnimSheet.createSprites("fireball_fadeout");
bucketFadeOutAnim = bucketAnimSheet.createSprites("bucket_fadeout");
catch_animation = new Animation(1/15f, fballAnimSheet.getRegions(), Animation.PlayMode.NORMAL);
visual_feedback = new Animation(1/15f, bucketAnimSheet.getRegions(), Animation.PlayMode.LOOP);
...
}
#Override
public void render () {
...
// Set the anim_elipsed_time
elapsedTime += Gdx.graphics.getDeltaTime();
...
// I try to draw them later on (under the render method) like this:
// Start and draw animation of fireball catch
batch.begin();
batch.draw(catch_animation.getKeyFrame(elapsedTime, true), fireBallRect.getX(), fireBallRect.getY());
batch.end();
}
I can see both animations happening extremely fast (they look like a white-flash), they do not loop even if the animation mode is set to "LOOP".
What am I doing wrong ? I can't seem to be able to slow them down or to have them LOOP. Thanks much.
Edited:
As requested, I upload all the code
public class MainActivity extends ApplicationAdapter {
public enum State {
PAUSE,
RUN,
RESUME,
STOPPED
}
public static State state = State.RUN;
private SpriteBatch batch;
private OrthographicCamera camera;
private Stage stage;
private Texture backgroundImage;
private Texture bucketImage;
private Texture fireballImage;
private Texture heart;
private TextureRegion criticalTexture;
private Sprite backgroundSprit;
private Sprite bucketSprite;
private Sprite fireballSprite;
private Sprite heartSprite;
private Rectangle bucketRect;
private Rectangle fireBallRect;
private Rectangle bucketSpriteRect;
private ShapeRenderer bucketRenderer;
private ShapeRenderer fireballRenderer;
private Button pauseButton;
private Array<Rectangle> fireballArray;
private Skin progressBarSkin;
private long lastFireballTime;
public static Sound bucket_tap;
public static Sound bucket_drag;
private Sound fireball_missed_sound;
private Sound catchFireball;
private Sound pauseBtnSound;
private Music bgMusic;
private float volume = 0.30f; // music and sfx volume control
public static int w;
public static int h;
private int barLength = 325;
private int numberOfFails = 10; // change numberOfFails to increase or decrese
// the total num. of missed fireballs the player
private int deductedBarSegment = barLength / numberOfFails;
private int numOfBallsLeft = numberOfFails; // use this var to check how many fballs left
private long fireballFrequency = 1000000000L; // change fireballFrequency to increase or decrease
// the number of fireballs on the screen
private int fireballSpeed = 400; // change the fireballSpeed to increase or decrease
// the speed at which the fireballs fall
private InputProcessor gameInputProcessor; // this sets the game input controller for the bucket
private InputMultiplexer multiplexer; // this sets the input processors from the game and UI
/************************************ Animation Properties ************************************/
private TextureAtlas fballAtlas;
private TextureAtlas bucketAtlas;
private Animation catch_animation;
private Animation visual_feedback;
private float elapsedTime = 0f;
private Actor feedbackPanel;
/**********************************************************************************************/
#Override
public void create () {
// Parse Test
//ParseObject testObject = new ParseObject("TestObject");
//testObject.put("foo", "bar");
//testObject.saveInBackground();
// Catch the dynamic size of the screen based on the device that's ran on
w = Gdx.graphics.getWidth();
h = Gdx.graphics.getHeight();
// Set up the camera
camera = new OrthographicCamera();
camera.setToOrtho(false, (float)w, (float)h);
// Instantiate the batch
batch = new SpriteBatch();
/***************************** These renders are for debugging only *****************************/
bucketRenderer = new ShapeRenderer();
fireballRenderer = new ShapeRenderer();
/**************************************************************************************************/
/******************************************** Stage and HUD ***************************************/
stage = new Stage();
pauseButton = new Button(new TextureRegionDrawable(
new TextureRegion(new Texture(Gdx.files.internal("images/pase_button_red.png")))),
new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("images/pase_button_white.png")))));
pauseButton.setX(flipCoordinates(w, 150));
pauseButton.setY(flipCoordinates(h, 170));
pauseButton.act(Gdx.graphics.getDeltaTime());
stage.addActor(pauseButton);
pauseButton.addListener(new ChangeListener() {
#Override
public void changed (ChangeEvent event, Actor actor) {
// Do something when the pauseButton is pressed
// Control multiple touches on the pauseButton
if(state == State.RUN) {
state = State.PAUSE;
pauseBtnSound.play();
// Set the pauseButton icon to the white version
//pauseButton.setColor(Color.WHITE);
}
else {
state = State.RUN;
pauseBtnSound.play();
}
}
});
// Add the critical_life indicator to the stage as an actor
criticalTexture = new TextureRegion(new Texture(Gdx.files.internal("images/critical_life.png")));
feedbackPanel = new Actor() {
public void draw(Batch batch, float alpha) {
batch.draw(criticalTexture, getX(), getY(), getOriginX(), getOriginY(), getWidth(), getHeight(),
getScaleX(), getScaleY(), getRotation());
}
};
feedbackPanel.setBounds(w / 2, h / 2,
criticalTexture.getRegionWidth(), criticalTexture.getRegionHeight());
// Set up an Action for the critical life actor
feedbackPanel.addAction(forever(sequence(scaleTo(2, 2, 0.5f), scaleTo(1, 1, 0.5f), delay(0.5f))));
feedbackPanel.act(Gdx.graphics.getDeltaTime());
stage.addActor(feedbackPanel);
/**************************************************************************************************/
/*********************************** Set up the Input Controllers *********************************/
// The multiplexer helps target several input processes (in this case, the stage and the
// InputProcessor.class)
multiplexer = new InputMultiplexer();
multiplexer.addProcessor(stage);
multiplexer.addProcessor(new GameInputProcessor());
// InputAdaptor
Gdx.input.setInputProcessor(multiplexer);
/**************************************************************************************************/
backgroundImage = new Texture("images/bg.jpg");
bucketImage = new Texture("images/bucket_small.png");
fireballImage = new Texture("images/fireball_small.png");
heart = new Texture("images/heart.png");
/*************************************** Animations Setup *****************************************/
fballAtlas = new TextureAtlas("animations/fireball_fadeout.txt");
bucketAtlas = new TextureAtlas("animations/bucket_fadeout.txt");
catch_animation = new Animation(0.50f, fballAtlas.getRegions());
visual_feedback = new Animation(0.15f, bucketAtlas.getRegions());
/**************************************************************************************************/
// Instantiate all sounds
bucket_tap = Gdx.audio.newSound(Gdx.files.internal("sounds/bucket_tap.ogg"));
bucket_drag = Gdx.audio.newSound(Gdx.files.internal("sounds/bucket_drag.ogg"));
fireball_missed_sound = Gdx.audio.newSound(Gdx.files.internal("sounds/fireball_missed.ogg"));
catchFireball = Gdx.audio.newSound(Gdx.files.internal("sounds/fastSteam.ogg"));
pauseBtnSound = Gdx.audio.newSound(Gdx.files.internal("sounds/pauseBtn_sound.ogg"));
bgMusic = Gdx.audio.newMusic(Gdx.files.internal("sounds/music_bg.mp3"));
bgMusic.setLooping(true);
bgMusic.play(); // <----------- turn bg music on/off
// Instantiate the progressBarSkin
progressBarSkin = new Skin();
progressBarSkin.add("progressBarBg", new Texture("images/progress-bar_bg.png"));
progressBarSkin.add("progressBar", new Texture("images/progress-bar_dynamic_red.png"));
// Create bg sprite
backgroundSprit = new Sprite(backgroundImage);
//backgroundSprit.setPosition((float)w / 2, (float)h / 2);
//backgroundSprit.setSize((float)w, (float)h);
// Bucket sprite
bucketSprite = new Sprite(bucketImage);
// Fireball sprite
fireballSprite = new Sprite(fireballImage);
// Heart sprite
heartSprite = new Sprite(heart);
// Set the bucketRect into the rect from the bucketSprite (THE GREEN ONE)
bucketSpriteRect = bucketSprite.getBoundingRectangle();
bucketSpriteRect.x = w / 2 - 100 / 2;
bucketSpriteRect.y = 20;
bucketSpriteRect.setSize(200, 200);
// Set the collision rectangle (THE RED ONE)
bucketRect = new Rectangle();
bucketRect.x = bucketSpriteRect.getX() + 70; // <---- adjust position left/right
bucketRect.y = bucketSpriteRect.getY() + 150; // <---- adjust position up/down
bucketRect.setSize(100, 10);
// Set a rectangle for each fireball sprite (THE WHITE ONE)
fireBallRect = new Rectangle();
fireBallRect.x = fireballSprite.getX();
fireBallRect.y = fireballSprite.getY();
fireBallRect.width = 55;
fireBallRect.height = 55;
fireballArray = new Array<Rectangle>();
}
#Override
public void render () {
// Devide the Render method into a few switch cases based on the game's state
switch (state) {
case RUN:
// Do all the batch drawing here
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
elipsedTime += Gdx.graphics.getDeltaTime();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(backgroundSprit, 0, 0, w, h);
batch.draw(bucketSprite, bucketSpriteRect.x, bucketSpriteRect.y,
bucketSprite.getWidth() - 160, bucketSprite.getHeight() - 140);
for(Rectangle fireball: fireballArray) {
batch.draw(fireballSprite, fireball.x, fireball.y,
fireballSprite.getWidth() - 20, fireballSprite.getHeight() - 20);
}
batch.draw(progressBarSkin.getSprite("progressBarBg"), 200, flipCoordinates(h, 170));
batch.draw(progressBarSkin.getSprite("progressBar"),
210, flipCoordinates(h, 162), barLength, 6); // <---- modify x, x, <x>, x to adjust the length of the life-bar
batch.draw(heartSprite, 95, flipCoordinates(h, 200), 90, 76);
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
batch.end();
/***************************************Debugging Rectangles************************************/
// Draw rects around sprites
// bucketRenderer.begin(ShapeRenderer.ShapeType.Line);
// bucketRenderer.setColor(Color.GREEN);
// bucketRenderer.rect(bucketSpriteRect.getX(), bucketSpriteRect.getY(),
// bucketSprite.getWidth() - 160, bucketSprite.getHeight() -140);
// bucketRenderer.end();
//
// bucketRenderer.begin(ShapeRenderer.ShapeType.Line);
// bucketRenderer.setColor(Color.RED);
// bucketRenderer.rect(bucketRect.getX(), bucketRect.getY(), 100, 10);
// //bucketRenderer.point(bucketRect.getX(), bucketRect.getY(), 0f);
// bucketRenderer.end();
//
// fireballRenderer.begin(ShapeRenderer.ShapeType.Line);
// fireballRenderer.setColor(Color.WHITE);
// fireballRenderer.rect(fireBallRect.x, fireBallRect.y,
// fireballSprite.getWidth() - 20, fireballSprite.getHeight() - 20);
// fireballRenderer.end();
// To avoid sprite flickering, surround batch.draw with a game state check
if (state != State.PAUSE) {
Iterator<Rectangle> iter = fireballArray.iterator();
while(iter.hasNext()) {
fireBallRect = iter.next();
fireBallRect.y -= fireballSpeed * Gdx.graphics.getDeltaTime();
// Remove the fireBallRect from the array as soon as it leaves the screen
if(fireBallRect.y + 106 < 0) {
iter.remove();
// The player missed the fireball, play a the fireball_missed_sound
fireball_missed_sound.play();
// Subtract a ball from the total number allowed to be missed
numOfBallsLeft --;
// Call life deduction
deductLifePoints();
// Check to see if this is the last fball left to fail
if (numOfBallsLeft == 1) {
}
// Check to see if life points are 0 or < 0
if (numOfBallsLeft <= 0) {
// Game over logic
barLength = 0;
// Set the game state to PAUSED
//state = State.PAUSE;
//bucketSprite.setColor(Color.RED);
batch.begin();
batch.draw(bucketSprite, bucketSpriteRect.x, bucketSpriteRect.y,
bucketSprite.getWidth() - 160, bucketSprite.getHeight() - 140);
batch.end();
}
}
// Collision detector
if(bucketRect.overlaps(fireBallRect)) {
catchFireball.play(volume);
// Start and draw animagion of fireball catch
batch.begin();
batch.draw(catch_animation.getKeyFrame(elapsedTime, true), fireBallRect.getX(), fireBallRect.getY());
batch.end();
// Remove the fireball that collides with the bucket
iter.remove();
}
}
}
// Touch input controller
if(Gdx.input.isTouched()) {
Vector3 touchPos = new Vector3();
touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touchPos);
if(touchPos.y <= 250) {
bucketSpriteRect.setX(touchPos.x - 115);
bucketRect.setX(touchPos.x - 50); // <---- adjust position left/right on touch
}
}
if(TimeUtils.nanoTime() - lastFireballTime > fireballFrequency) {
fireBallRect = new Rectangle();
fireBallRect.x = MathUtils.random(50, w - 270);
fireBallRect.y = h;
fireBallRect.width = 75;
fireBallRect.height = 75;
fireballArray.add(fireBallRect);
lastFireballTime = TimeUtils.nanoTime();
}
/**************************************************************************************************/
break;
case PAUSE:
// Pause the game here
/******************************** Redraw the sprites to avoid flickering **************************/
batch.begin();
batch.draw(backgroundSprit, 0, 0, w, h);
batch.draw(bucketSprite, bucketSpriteRect.x, bucketSpriteRect.y,
bucketSprite.getWidth() - 160, bucketSprite.getHeight() - 140);
for(Rectangle fireball: fireballArray) {
batch.draw(fireballSprite, fireball.x, fireball.y,
fireballSprite.getWidth() - 20, fireballSprite.getHeight() - 20);
}
batch.draw(progressBarSkin.getSprite("progressBarBg"), 200, flipCoordinates(h, 170));
batch.draw(progressBarSkin.getSprite("progressBar"),
210, flipCoordinates(h, 162), barLength, 6); // <---- modify x, x, <x>, x to adjust the length of the life-bar
batch.draw(heartSprite, 95, flipCoordinates(h, 200), 90, 76);
//pauseButton.draw(batch, 1);
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
batch.end();
/**************************************************************************************************/
break;
case RESUME:
break;
default:
break;
}
}
/************************************* Implement Dispose **************************************/
#Override
public void dispose() {
batch.dispose();
bucketRenderer.dispose();
fireballRenderer.dispose();
backgroundImage.dispose();
bucketImage.dispose();
fireballImage.dispose();
bucket_tap.dispose();
bucket_drag.dispose();
catchFireball.dispose();
bgMusic.dispose();
fireball_missed_sound.dispose();
progressBarSkin.dispose();
fballAtlas.dispose();
stage.dispose();
}
/************************************* Flip Coordinates Method ********************************/
public static float flipCoordinates(float height, float xORy) {
float newPosition = height - xORy;
return newPosition;
}
/************************************** Deduces Life Points ***********************************/
private void deductLifePoints() {
barLength -= deductedBarSegment;
}
/************************************** Set the Game's state **********************************/
public void setGameState(State s) {
this.state = s;
}
/******************************** Android's Lyfe-Cycle Overrides ******************************/
#Override
public void pause() {
super.pause();
this.state = State.PAUSE;
}
#Override
public void resume() {
super.resume();
this.state = State.PAUSE;
}
}
The first parameter of the Animation constructor is the frameDuration in seconds. You are passing it 1/15f, which is really fast. Try something greater, like 0.15f.
I'm trying to make a 2D car side scrolling game. I'm using wheel joints to move the car.
Here is the screenshot when car is not moving.
Screenshot of car when not moving
And when the car is moving. You can see sprites are not in correct position.
Screenshot when the car is moving
Here is the constructor of car object.
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.set(x, y);
//Chassis
PolygonShape chassisShape = new PolygonShape();
chassisShape.setAsBox(width, height);
chassisFixtureDef.shape = chassisShape;
chassis = world.createBody(bodyDef);
// Car Body Sprite
Sprite body = new Sprite(new Texture(Gdx.files.internal("data/body.png")));
body.setSize(5f, 2f);
body.setPosition(0f, 0);
body.setOrigin(body.getWidth() / 2, body.getHeight() / 2);
chassis.setUserData(body);
chassis.createFixture(chassisFixtureDef);
//Left Wheel
CircleShape wheelShape = new CircleShape();
wheelShape.setRadius(height / 1.5f);
wheelFixtureDef.shape = wheelShape;
leftWheel = world.createBody(bodyDef);
//Sprite Test
wheel = new Sprite(new Texture(Gdx.files.internal("data/wheel.png")));
wheel.setSize(1f, 1f);
wheel.setOrigin(wheel.getWidth() / 2, wheel.getHeight() / 2);
leftWheel.setUserData(wheel);
leftWheel.createFixture(wheelFixtureDef);
//Right Wheel
rightWheel = world.createBody(bodyDef);
rightWheel.setUserData(wheel);
rightWheel.createFixture(wheelFixtureDef);
//Left Axis
WheelJointDef def = new WheelJointDef();
def.bodyA = chassis;
def.bodyB = leftWheel;
def.frequencyHz = chassisFixtureDef.density;
def.localAnchorA.set(-width / 2 * 1.7f + wheelShape.getRadius(), -height / 2 * 2.5f);
def.localAxisA.set(Vector2.Y);
def.maxMotorTorque = chassisFixtureDef.density * 30;
leftAxis = (WheelJoint) world.createJoint(def);
def.bodyB = rightWheel;
def.localAnchorA.x *= -1;
rightAxis = (WheelJoint) world.createJoint(def);
And Here is the code to draw sprites relevant to bodies on screen.
for (Body body : bodies)
if (body.getUserData() != null && body.getUserData() instanceof Sprite){
Sprite sprite = (Sprite)body.getUserData();
sprite.setPosition(body.getPosition().x - sprite.getWidth()/2, body.getPosition().y - sprite.getHeight()/2);
sprite.setRotation(body.getAngle() * MathUtils.radiansToDegrees);
sprite.draw(batch);
}
Sorry if couldn't make my question very specific or clear. I'm new to Stackoverflow.
Edit [Solved]
Just placed in render method [Correct]
renderer.render(world, camera.combined);
after gl.clear
I was doing it after drawing everything on screen. [Wrong]
seems like you update your physic after rendering it, because your physic-debugged polygon moved already further than the sprite shows up. You could try to first update your physics and then draw your sprites.
There shouldn't be something wrong with the code / calculations itself.
If you're already doing so it's probably because the updates of your physic simulation updates more frequently than your rendering-loop.
I am trying to make a dynamic body which should move ahead a bit and then fall according to its gravity(as decided by the box2d engine). The problem is that right after moving upto a certain distance, instead of moving down, it is going up. This is the code i am using:
public class AngryBirdsTrajectoryPrototype implements ApplicationListener
{
private SpriteBatch spriteBatch;
private Texture backgroundTexture;
private Sprite backgroundSprite;
private static Sprite ball_in_hand;
private Texture ball_in_hand_Texture;
private static com.badlogic.gdx.physics.box2d.Body b2Body;
private com.badlogic.gdx.physics.box2d.World box2Dworld;
private boolean isBallShooted;
#Override
public void create() {
spriteBatch = new SpriteBatch();
Texture.setEnforcePotImages(false);
backgroundTexture = new Texture(Gdx.files.internal("angrybirds/background.png"));
backgroundTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
backgroundSprite = new Sprite(backgroundTexture);
backgroundSprite.setPosition(0, 0);
ball_in_hand_Texture = new Texture(Gdx.files.internal("test/ball_in_hand.png"));
ball_in_hand_Texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
ball_in_hand = new Sprite(ball_in_hand_Texture);
this.box2Dworld = new com.badlogic.gdx.physics.box2d.World(new Vector2(0.0F, 10.0F), true);
}
#Override
public void render() {
Gdx.gl.glClearColor(0.5f, 0.5f, 0.5f, 1f);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
if(!isBallShooted)
{
isBallShooted = true;
shoot(this.box2Dworld, 27.0F, 0.F);
}
box2Dworld.step(1.0f/60.0f, 6, 2);
spriteBatch.begin();
backgroundSprite.draw(spriteBatch);
Array<Body> bodies = new Array<Body>();
box2Dworld.getBodies(bodies);
for (Body body : bodies)
{
ball_in_hand.setPosition(30.0F * body.getPosition().x, 30.0F * body.getPosition().y);
Gdx.app.error("", "angleDegree= " + body.getAngle());
}
ball_in_hand.draw(spriteBatch);
spriteBatch.end();
}
#Override
public void dispose() {
spriteBatch.dispose();
backgroundTexture.dispose();
}
public static void shoot(com.badlogic.gdx.physics.box2d.World var1, float var2, float var3)
{
BodyDef var4 = new BodyDef();
var4.position.set(ball_in_hand.getX() / 30.0F, ball_in_hand.getY() / 30.0F);
var4.type = BodyType.DynamicBody;
var4.bullet = true;
var4.angularDamping = 0.5F;
b2Body = var1.createBody(var4);
CircleShape var6 = new CircleShape();
var6.setRadius(0.4F);
FixtureDef var7 = new FixtureDef();
var7.density = 0.8F;
var7.shape = var6;
var7.restitution = 0.7F;
var7.friction = 1.0F;
b2Body.createFixture(var7);
float var9 = var2 * 9.0F;
Vector2 var10 = new Vector2(var9 * (float)Math.cos((double)var3), var9 * (float)Math.sin((double)var3));
b2Body.applyForce(var10, b2Body.getWorldCenter(), true);
}
}
This is the output i am getting.
This is the output i want to achieve:
I have tried all possible options but none of them is working. Please help me. Thanks in advance.
Try this:
You should set your gravity to a negative number because of the Box2d coordinate system, like this:
enter code here`this.world = new World(new Vector2(0, -9.8f), true);
You should create a camera for your physics world and convert all your sizes to meters. For example, you can set 100 pixels = 1 meter in the box2d world, so you will need to set your camera's width and height in meters, too. Here is a full working example.
You can also get delta like this: Gdx.graphics.getDeltaTime()
Please let me know if it helped.
I think the problem in your code is in the create method:
this.box2Dworld = new com.badlogic.gdx.physics.box2d.World(new Vector2(0.0F, 10.0F), true)
You should use a negative value of gravity in y-direction like:
this.box2Dworld = new com.badlogic.gdx.physics.box2d.World(new Vector2(0.0F, -10.0F), true)
Also, please use debug-renderer to spot the error.