Box2d body leaves trail - libgdx

I am trying to shoot a bullet that is a box2d body with linear impulse applied. Everything is fine except that it appears to leave trails and the movement is not smooth. Here's an image of how it is appearing ..this is one bullet .. but is leaving trail while moving ...
This is a single bullet ..rest are just trails that were not cleared. Here is the render method of screen ,
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
frameTime = Math.min(delta, 0.25f);
accumulator += frameTime;
while (accumulator >= TIME_STEP) {
world.step(TIME_STEP, 6, 2);
accumulator -= TIME_STEP;
}
stage.act();
stage.draw();
}
Here's the bullet actor
public class Bullet extends Actor {
Sprite bulltetSprite = new Sprite(new Texture(Gdx.files.internal("bullet1.png")));
float x, y;
Body body;
public Bullet(Body b) {
this.body = b;
}
#Override
public void act(float delta) {
x = body.getPosition().x * Constants.PPM;
y = body.getPosition().y * Constants.PPM;
super.act(delta);
}
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch,parentAlpha);
batch.draw(bulltetSprite, x - Constants.BULLET_WIDTH / 2, y - Constants.BULLET_HEIGHT / 2, Constants.BULLET_WIDTH, Constants.BULLET_HEIGHT);
}
}
What am I missing here, so the bullet with move smoothly ...
Edit: The trails appear even when I am not using sprites and just rendering with Box2dDebugRenderer.
Edit 2 : It appears it has to do with the physics. The density I was using for the bullet was way too low .. after setting the density to higher value it seems to work fine now.

Related

Sprite rotation with touch pad

I'am having a issue or just don't know how to make it to work so everything is seen in image.
rotation = lerp(rotation, realRotation, delta / 2);
IMAGE GIF
You want to linearly interpolate ship rotation between a particular angle(set by TouchPad) to original(default) value.
I am trying to achieve your requirement in my code.
public class TestGame1 extends Game {
Stage stage;
Touchpad touchpad;
Image image;
float angle=0;
Texture shipTex;
#Override
public void create() {
stage=new Stage();
image=new Image(shipTex=new Texture("ship1.png"));
image.setPosition(300,300);
image.setSize(100,107);
image.setOrigin(50,53);
Skin skin=new Skin(Gdx.files.internal("skin/uiskin.json"));
touchpad=new Touchpad(10,skin);
touchpad.setPosition(100,100);
Gdx.input.setInputProcessor(stage);
stage.addActor(image);
stage.addActor(touchpad);
}
#Override
public void render() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl.glClearColor(0,0,0,1);
stage.act();
stage.draw();
float knobX=touchpad.getKnobPercentX();
float knobY=touchpad.getKnobPercentY();
if(knobX!=0 && knobY!=0) {
float radAngle = MathUtils.atan2(knobY, knobX);
angle = MathUtils.radiansToDegrees * radAngle;
angle -= 90;
if (angle > 360)
angle -= 360;
}
else
angle=MathUtils.lerpAngleDeg(angle,0,Gdx.graphics.getDeltaTime());
image.setRotation(angle);
}
#Override
public void dispose() {
stage.dispose();
shipTex.dispose();
}
}

Libgdx Box2D create Bodies

in my libgdx tiles 2D jump and run game I want to create Bodies every second at the positin of my cannons, but as far as I am, only one cannon shoots every second.
Can anyone help me how to fix this?
Heres where I create my cannons:
//create cannon bodies/fixtures
cannons = new Array<Cannon>();
for (MapObject object : map.getLayers().get(5).getObjects().getByType(RectangleMapObject.class)) {
recta = ((RectangleMapObject) object).getRectangle();
cannons.add(new Cannon(screen, recta.getX(), recta.getY()));
}
}
public float X() {
return recta.getX();
}
public float Y() {
return recta.getY();
}
Here I add canons( that works for every position) :
private Array<Bullet> bullets;
public Cannon(PlayScreen screen, float x, float y) {
super(screen, x, y);
setBounds(getX(), getY(), getWidth(), getHeight());
}
public Cannon() {
super();
}
#Override
protected void defineTrap() {
b2body = Body.addStatic(b2body, world, 0f, getX(), getY(), 32, x.CANNON_BIT, "cannon");
createBullet();
}
public void createBullet() {
bullets = new Array<Bullet>();
bullets.add(new Bullet(screen, getX(), getY()));
}
Here I add the first bullet(that waoks too for all cannons):
public Bullet(PlayScreen screen, float x, float y) {
super(screen, x, y);
setBounds(getX(), getY(), getWidth(), getHeight());
}
public Bullet() {
}
#Override
public void defineTrap() {
b2body = Body.addDynamic(b2body, world, 0f, getX(), getY(), 8, x.BULLET_BIT, "bullet");
b2body.setLinearVelocity(new Vector2(-1f, 0));
b2body.setGravityScale(0);
}
And here I want every cannon to shoot, but only one does (its my render mehtod):
if (TimeUtils.timeSinceNanos(startTime) > 1000000000) {
bullets = new Array<Bullet>();
bullets.add(new Bullet(this, creator.X(), creator.Y()));
startTime = TimeUtils.nanoTime();
}
I hope you can help me!
You should iterate through all cannons and call some method that can access the private field bullets, I called it addBullet(Screen, float, float). You might to need to do something with creator before addBullet() as I'm unsure what you are doing with it.
if (TimeUtils.timeSinceNanos(startTime) > 1000000000) {
for(int i = 0; i < Cannons.size; i++) {
Cannon cannon = cannons.get(i);
cannon.addBullet(this, creator.X(), creator.Y());
}
startTime = TimeUtils.nanoTime();
}
Then create the addBullet method in the Cannon class.
public void addBullet(Screen screen, float x, float y) {
bullets.add(new Bullet(screen, x, y));
}
As far as I can tell there is no reason to reinitialize the bullet array every time as you have been doing. Just use pop(); or removeIndex(index); to remove the array items that are no longer used. You could add some more methods to the Cannon class
public void removeLastBullet() {
bullets.pop();
}
public void removeBullet(int i) {
bullets.removeIndex(i);
}

Fix touchDragged logic

What i want:
I want allow the user to drag and drop the actors he puts on the screen
1) An actor (32x32 pixel) can be put in a certain area defined by me (a centered rectangle 5x5, 32 pixel each cell)
2) The actors are snapped to an imaginary grid of the screen when added to the stage.
3) This snap to grid is needed also during the drag and drop
4) An actor can't be moved on another one
5) An actor must be rotated by 90 degrees when the user clicks on it
6) The actor can't be moved outside the bounds
What actually i get:
1) ok
2) ok
3) ok (with bugs)
4) not implemented yet
5) ok (with bugs)
6) not implemented yet
The bugs are:
1) The rotations is applied in any case. I don't want this behavior. I don't want to rotate an actor if the user is just doing drag and drop. (i know that this happens because i put this part of the code in the touchDown method)
2) This is hard to describe with my english, i'll try.
I put an actor and i can move it (when i say "move" i mean drag and drop).
I put a second actor and i can move it.
Now, if i try to move the first actor i put, the second one moves over the first (overlapping to it) and starts moving along with it!
Now the code:
Events in the GameStage
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
translateScreenToWorldCoordinates(screenX, screenY);
// check if the user clicked or not in the center area
if(!centerArea.contains(touchPoint.x, touchPoint.y)) {
return true;
}
// rotation
Iterator<Square> squareIterator = squares.iterator();
while(squareIterator.hasNext()) {
Square nextSquare = squareIterator.next();
if(nextSquare.getBounds().contains(touchPoint.x, touchPoint.y)) {
nextSquare.rotate();
return true;
}
}
// add an Actor
touchPoint.set(touchPoint.x - Constants.SQUARE_SIZE / 2, touchPoint.y - Constants.SQUARE_SIZE / 2, 0f);
float snapX = Math.round((touchPoint.x / Constants.SQUARE_SIZE)) * Constants.SQUARE_SIZE;
float snapY = Math.round((touchPoint.y / Constants.SQUARE_SIZE)) * Constants.SQUARE_SIZE;
Square square = new Square(snapX, snapY);
squares.add(square);
addActor(square);
return true;
}
public boolean touchDragged(int screenX, int screenY, int pointer) {
Vector3 newTouchPoint = new Vector3(screenX, screenY, 0f);
getCamera().unproject(newTouchPoint.set(screenX, screenY, 0f));
Square next = null;
Iterator<Square> squareIterator = squares.listIterator();
while(squareIterator.hasNext()) {
next = squareIterator.next();
if(next.getBounds().contains(newTouchPoint.x, newTouchPoint.y)) {
next.setX(newTouchPoint.x - Constants.SQUARE_SIZE / 2);
next.setY(newTouchPoint.y - Constants.SQUARE_SIZE / 2);
continue;
}
}
newTouchPoint.set(newTouchPoint.x - Constants.SQUARE_SIZE / 2, newTouchPoint.y - Constants.SQUARE_SIZE / 2, 0f);
float snapX = Math.round((newTouchPoint.x / Constants.SQUARE_SIZE)) * Constants.SQUARE_SIZE;
float snapY = Math.round((newTouchPoint.y / Constants.SQUARE_SIZE)) * Constants.SQUARE_SIZE;
next.setX(snapX);
next.setY(snapY);
return true;
}
private void translateScreenToWorldCoordinates(int x, int y) {
getCamera().unproject(touchPoint.set(x, y, 0f));
}
Actor
public class Square extends GameActor {
private float rotation;
private ShapeRenderer shapeRenderer;
public Square(float x, float y) {
super(x, y);
shapeRenderer = new ShapeRenderer();
}
#Override
protected void initializeSprite() {
texture = new Texture(Gdx.files.internal(Constants.SQUARE_LOCATION));
}
#Override
public void act(float delta) {
super.act(delta);
}
#Override
protected void updateBounds() {
bounds.setPosition(x, y);
}
public void rotate() {
rotation -= 90;
if(rotation <= -360) {
rotation = 0;
}
setRotation(rotation);
}
public void setX(float x) {
this.x = x;
}
public void setY(float y) {
this.y = y;
}
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
/*shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
shapeRenderer.setColor(Color.RED);
shapeRenderer.rect(bounds.getX(), bounds.getY(), Constants.SQUARE_SIZE, Constants.SQUARE_SIZE);
shapeRenderer.end();*/
//batch.begin();
batch.draw(texture, x, y, texture.getWidth() / 2, texture.getHeight() / 2,
texture.getWidth(), texture.getHeight(), 1, 1, rotation, 0, 0, Constants.SQUARE_SIZE, Constants.SQUARE_SIZE, false, false);
}
}
I hope you can help me, i'm new to Libgdx, thank you.
UPDATE
I fixed the rotation bug moving its logic inside the touchUp method.

Make actor clip child Image

I want an actor that draws a drawable, but clips it to the size of the actor. I'm deriving this class from Widget, and using some hard-coded values as a simple test:
public class MyWidget extends Widget {
public MyWidget(Drawable drawable) {
setDrawable(drawable);
setSize(100, 100);
}
public void draw(Batch batch, float parentAlpha) {
clipBegin(getX(), getY(), 20, 20);
drawable.draw(batch, getX(), getY(), 500, 500);
clipEnd();
}
}
No clipping is performed though, the drawable spills out of the bounds of the actor. This actor is part of a Table, if it matters. I believe I am using the clipBegin() / clipEnd() methods incorrectly. What is the right way to do this?
Thanks
This is what I found based on the comments and my own experimentation. It's important to flush the batch before starting the clip and after drawing to ensure the proper drawing gets clipped.
public void draw(Batch batch, float parentAlpha) {
batch.flush();
if (clipBegin(getX(), getY(), 20.0f, 20.0f)) {
//do your drawing here
drawable.draw(batch, getX(), getY(), 500, 500);
batch.flush();
clipEnd();
}
}

Libgdx: Dynamically increasing size of Pixmap

I am new to Libgdx. I have a requirement where I have multiple balls in a game and I want to increase the ball diameter every time the user touches the ball. I used the method pixmap.drawCircle() to create the ball and every time a user touches the ball, I call a method increaseBallDia() to increase the ball size. Since there is no method to increase the height and width of an existing Pixmap, in increaseBallDia() method, I create a new Pixmap with increased width and height and then draw a ball with incremented diameter.
The problem is that my increaseBallDia() is not working properly and there is no increment to the height and width of the Pixmap. Due to this as the ball diameter increases it covers the entire Pixmap area and appears like a rectangle instead of a circle.
Any pointers on how to solve this would be greatly appreciated.
Following is the relevant code snippet:
public class MyActor extends Actor {
int actorBallDia = 90;
Pixmap pixmap = new Pixmap(actorBallDia, actorBallDia,Pixmap.Format.RGBA8888);
float actorX, actorY;
Texture texture;
public void increaseBallDia() {
actorBallDia = actorBallDia + 5;
int radius = actorBallDia / 2 - 1;
Pixmap pixmap = new Pixmap(actorBallDia, actorBallDia,
Pixmap.Format.RGBA8888);
pixmap.drawCircle(pixmap.getWidth() / 2 , pixmap.getHeight() / 2,
radius);
pixmap.fillCircle(pixmap.getWidth() / 2 , pixmap.getHeight() / 2,
radius);
texture = new Texture(pixmap);
}
public void createYellowBall() {
pixmap.setColor(Color.YELLOW);
int radius = actorBallDia / 2 - 1;
pixmap.drawCircle(pixmap.getWidth() / 2, pixmap.getHeight() / 2,
radius);
pixmap.setColor(Color.YELLOW);
pixmap.fillCircle(pixmap.getWidth() / 2, pixmap.getHeight() / 2,
radius);
texture = new Texture(pixmap);
}
#Override
public void draw(Batch batch, float alpha) {
if (texture != null) {
batch.draw(texture, actorX, actorY);
}
}
public void addTouchListener() {
addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y,
int pointer, int button) {
MyActor touchedActor = (MyActor) event.getTarget();
touchedActor.actorTouched = true;
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y,
int pointer, int button) {
MyActor touchedActor = (MyActor) event.getTarget();
touchedActor.actorTouched = false;
}
});
}
#Override
public void act(float delta) {
if (actorTouched) {
increaseBallDia();
}
}
Regards,
RG
You should create the pixmap with its biggest possible dimensions. When the ball is meant to be small, just scale it down as you wish.