Drawing a partial sprite with batch-LibGdx - libgdx

I have a sprite like this.
I want to draw this sprite in such a way that sprite is growing from bottom to top, using sprite batch on tap.for that,I have written the following code:
if (MyInputProcessor.isTap)
{
Sprite stickSprite = new Sprite(stickTexture);
stickSprite.setPosition(stick.getX(),stick.getY());
for(float n=0;n<100;n++)
{
float i = 0.01f * n;
batch.draw(
stickSprite.getTexture(),
stick.getX(),
stick.getY(),
stickSprite.getWidth() / 2,
stickSprite.getHeight() / 2,
stickSprite.getWidth(),
stickSprite.getHeight()*i, //multiplying with height
stickSprite.getScaleX(),
stickSprite.getScaleY(),
0 ,
stickSprite.getRegionX(),
stickSprite.getRegionY(),
stickSprite.getRegionWidth(),
stickSprite.getRegionHeight(),
false,
false);
}
MyInputProcessor.isTap = false;
}
Here the i value increments but not taking effect in the code to scale.
Whats wrong with the code?

I called this method in render before drawing the sprite.
stickSprite.setSize(stickSprite.getWidth(), stickSprite.getHeight() + addincrementvalue);

Related

setCenter() Method is not properly centering sprite texture on box2d fixture

The past few days I've been trying to figure out a display bug I don't understand. I've been working on a simple 2d platformer with box2d and orthogonal Tiled maps. So far so good, the physics work and using the b2d debug renderer I can assert proper player fixture and camera movement through the level.
Now next step I've tried to load textures to display sprites instead of debug shapes. This is where I stumble. I can load animations for my player body/fixture, but when I use the setCenter() method to center the texture on the fixture it is always out of center.
I've tried approaches via halving texture witdths and heights hoping to center the texture on the player fixture but I get the exact same off position rendering. I've played aorund with world/camera/screen unit coordinates but the misalignement persists.
I'm creating the player in my Player class with the following code.
First I define the player in box2d:
//define player's physical behaviour
public void definePlayer() {
//definitions to later use in a body
BodyDef bdef = new BodyDef();
bdef.position.set(120 / Constants.PPM, 60 / Constants.PPM);
bdef.type = BodyDef.BodyType.DynamicBody;
b2body = world.createBody(bdef);
//Define needed components of the player's main fixture
FixtureDef fdef = new FixtureDef();
PolygonShape shape = new PolygonShape();
shape.setAsBox(8 / Constants.PPM, 16 / Constants.PPM); //size of the player hitbox
//set the player's category bit
fdef.filter.categoryBits = Constants.PLAYER_BIT;
//set which category bits the player should collide with. If not mentioned here, no collision occurrs
fdef.filter.maskBits = Constants.GROUND_BIT |
Constants.GEM_BIT |
Constants.BRICK_BIT |
Constants.OBJECT_BIT |
Constants.ENEMY_BIT |
Constants.TREASURE_CHEST_BIT |
Constants.ENEMY_HEAD_BIT |
Constants.ITEM_BIT;
fdef.shape = shape;
b2body.createFixture(fdef).setUserData(this);
}
Then I call the texture Region to be drawn in the Player class constructor:
//define in box2d
definePlayer();
//set initial values for the player's location, width and height, initial animation.
setBounds(0, 0, 64 / Constants.PPM, 64 / Constants.PPM);
setRegion(playerStand.getKeyFrame(stateTimer, true));
And finally, I update() my player:
public void update(float delta) {
//center position of the sprite on its body
// setPosition(b2body.getPosition().x - getWidth() / 2, b2body.getPosition().y - getHeight() / 2);
setCenter(b2body.getPosition().x, b2body.getPosition().y);
setRegion(getFrame(delta));
//set all the boolean flags during update cycles approprietly. DO NOT manipulate b2bodies
//while the simulation happens! therefore, only set flags there, and call the appropriate
//methods outside the simulation step during update
checkForPitfall();
checkIfAttacking();
}
And my result is
this, facing right
and this, facing left
Update:
I've been trying to just run
setCenter(b2body.getPosition().x, b2body.getPosition().y);
as suggested, and I got the following result:
facing right and facing left.
The sprite texture flip code is as follows:
if((b2body.getLinearVelocity().x < 0 || !runningRight) && !region.isFlipX()) {
region.flip(true, false);
runningRight = false;
} else if ((b2body.getLinearVelocity().x > 0 || runningRight) && region.isFlipX()) {
region.flip(true, false);
runningRight = true;
}
I'm testing if either the boolean flag for facing right is set or the x-axis velocity of my player b2body has a positive/negative value and if my texture region is already flipped or not and then use libGDX's flip() accordingly. I should not be messing with fixture coords anywhere here, hence my confusion.
The coordinates of box2d fixtures are offsets from the position, the position isn't necessarily the center (although it could be depending on your shape definition offsets). So in your case i think the position is actually the lower left point of the box2d polygon shape.
In which case you don't need to adjust for width and height because sprites are also drawn from bottom left position. So all you need is ;
setPosition(b2body.getPosition().x , b2body.getPosition().y );
I'm guessing you flip the box2d body when the player looks left the position of the shape is now bottom right so the sprite offset of width/2 and height/2 is from the bottom right instead. So specifically when you are looking left you need an offset of
setPosition(b2body.getPosition().x - getWidth() , b2body.getPosition().y );
I think looking right will be fixed from this, but i don't know for sure how you handle looking left in terms of what you do to the body, but something is done because the offset changes entirely as shown in your capture. If you aren't doing some flipping you could add how you handle looking right to the question.
EDIT
It seems the answer was that the sprite wasn't centered in the sprite sheet and this additional space around the sprite caused the visual impression of being in the wrong place (see comments).

Creating sprite from texture atlas

In my libGdx project,I created a sprite from texture atlas,using createSprite().
I want to implement the sprite as rotated.
How can I do it?Here is my Code:
reelSprite = atlas.createSprite("reel");
Inside render():
for (Wall lWalls : leftWalls){
reelSprite.setOrigin(lWalls.getX(), lWalls.getY());
reelSprite.setRotation(180);
batch.draw(reelSprite, lWalls.getX(), lWalls.getY());
}
This code is not working.Please tell me what wrong I did.
You should use setRotation before you draw the sprite:
https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/g2d/Sprite.html#setRotation-float-
And even before that set rotation point:
https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/g2d/Sprite.html#setOrigin-float-float-
float rotate = 0;
rotate += (sprite.getRotation() - 40) * Gdx.graphics.getDeltaTime();
if(Math.abs(rotate) > 10) // change the number to set the rotation power cap
{
rotate = -10;
}
sprite.rotate(rotate);
I changed the code like this...
for (Wall lWalls : leftWalls){
reelSprite1.setPosition(lWalls.getX(), lWalls.getY());
reelSprite1.setOrigin(reelSprite1.getWidth()/2,reelSprite1.getHeight()/2);
reelSprite1.setRotation(180);
reelSprite1.draw(batch);
then it worked.

How to automatically loop a background actor object in Libgdx?

I would like to make a 2D Side-scroller game, where the game world/game stage is moving to the left, i.e. The background is transitioning to the left like Flappy Bird. Any ideas how I am able to automatically loop a background Actor object which has the same width and height as the Stage's Orthographic camera?
Well it is really simple. All you need to do is use the moveBy(x, y) method on the Actor instance.
float xMovingDelta = 10;
float yMovingDelta = 10;
actor.moveBy(xMovingDelta, yMovingDelta);
// Make sure you call the moveBy() method in a loop eg. the render() method.
Here is an example from my past game: It uses a Table instance but they both have the moveBy() method.
private void mMenuToDiffMenuAnimation() { // I call this method from the render() meth.
if(difficultyTable.getX() > (540 - 64)){
menuTable.moveBy(-30, 0);
difficultyTable.moveBy(-30, 0);
}else {
fromMMToDiffMenu = false;
/* When the table's xPos is greater than 540 -64 stop the animation.*/
}
}

How to stop a sprite at exact touchdown position coordinates

I want to move a sprite (which happens to be a Rectangle) from any position of the screen and make it stop at exactly the touched position of the screen. Now, I can stop my sprite already, but not at the exact touched position. I cannot find a good way of doing this without sacrificing either accuracy or risking the sprite to not stop at all.
Naturally - the problem arises because the current position is Float, so that Vector will never (or extremely rarely) have the exact same coordinates as the touch point (which is an int).
In the code below, I stop my sprite by simply checking the distance between the current position and the target position (i.e. the touched position Vector3), like so if (touch.dst(currentPsition.x, currentPosition.y, 0) < 4).
For example, if the sprite is at position (5,5) and I touch the screen at (100,100), it will stop at like (98.5352,96.8283).
My question is, how do I stop the sprite at exactly the touch position, without having to approximate?
void updateMotion() {
if (moveT) {
movement.set(velocity).scl(Gdx.graphics.getDeltaTime());
this.setPosition(currentPosition.add(movement));
if (touch.dst(currentPosition.x, currentPosition.y, 0) < 4)
moveT = false;
}
}
public void setMoveToTouchPosition(boolean moveT) {
this.moveT = moveT;
this.touch = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
GameScreen.getCamera().unproject(touch);
currentPosition = new Vector2(this.x, this.y);
direction.set(new Vector2(touch.x, touch.y)).sub(currentPosition).nor();
velocity = new Vector2(direction).scl(speed);
}
Of course sprite can't move smoothly to touch position and then stop in exactly the same position because of many reasons. Just change this
if (touch.dst(currentPosition.x, currentPosition.y, 0) < 4)
moveT = false;
to this
if (touch.dst(currentPosition.x, currentPosition.y, 0) < 2) {
currentPosition.x = touch.x;
currentPosition.y = touch.y;
moveT = false;
}
A quick yet acceptable solution to this could be the use of the Rectangle class. Considering you make a Rectangle surrounding the moving entity and constantly update it's bounds based on its current location, it's texture width, and it's texture height. You could stop it when it overlaps with the "target position". If you do this you guarantee yourself that it will stop exactly at that position. For example:
Texture entityTexture = new Texture("assets/image.png");
Rectangle entityBounds = new Rectangle();
entityBounds.set((currentPosition.x, currentPosition.y, entityTexture .getWidth(), entityTexture .getHeight()));
Rectangle targetBounds = new Rectangle();
targetBounds.set((targetPosition.x, targetPosition.y, 1, 1)); // make width and height 1 by 1 for max accuracy
public void update(){
// update bounds based on new position
entityBounds.set((currentPosition.x, currentPosition.y, entityTexture.getWidth(), entityTexture.getHeight()));
targetBounds.set((targetPosition.x, targetPosition.y, 1, 1));
if(entityBounds.overlaps(targetBounds)){
// do something
}
}

AS3 sprite with rectangle is empty and returns 0 for width and other properties

I have an array of sprites:
for (i = 0; i < 3; i++) {
var newLine:Sprite = new Sprite();
newLine.graphics.beginFill(0xFFFFFF);
newLine.graphics.drawRect((uiSizeX * (.25 + .25 * i)) + (doorSizeX - lineLengths[0][i]) / 2, uiSizeY * .5, lineLengths[0][i], lineHeight);
newLine.name = "lines" + i;
lines.push(newLine);
}
I later add each to a background Sprite:
for (i = 0; i < 3; i++) {
uiContainer.addChild(doors[i]);
uiContainer.addChild(lines[i]);
}
And later wish to change the width of the rectangles contained in each. When I set the width property using the array reference:
lines[i].width = lineLengths[trialNumber][i];
The rectangle moves towards the center of the stage and uiContainer. Trying to set the x value results in even stranger behavior. I've gathered from answers to other questions that this is because the sprite is empty, which is confusing since it seems like it should have a rectangle in it. How do I access or change the properties of the rectangle or make it so the sprite is not empty?
Never try to directly change the width or height of a sprite, unless you really really have to, because it leads to all sorts of unexpected behavior.
If you want to resize the sprite, then redraw the rectangle:
var sprite = lines[i];
sprite.graphics.beginFill(0xFFFFFF);
sprite.graphics.drawRect(newWidth, newHeight);
Also don't forget to call endFill:
sprite.graphics.endFill();
You should probably wrap all this logic into a separate class so that you can redraw your sprites more easily. Even better, create a class that extends Sprite and that contains all the logic to redraw/resize.