Draw font on top of box2d body - libgdx

How can I draw text (font) on top of my static box2d body?
Background: Im able to draw sprites on top of bodies correctly.
I do this by having a box2dSpriteBatch which is projected on box2dCamera like so box2dSpriteBatch.setProjectionMatrix(box2dCamera.combined); And then simply rendering the sprite in the correct spot using getPosition of the body.
But if i try the same way for fonts, unfortunately it scales incredibly large, and if i try to scale the font down it doesn't appear. So im assuming I need to draw the text in window coordinates instead of box2d.
My attempt:
in show():
windowCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
in my Render method i call
windowSpriteBatch.setProjectionMatrix(windowCamera.combined);
also in Render i render the font
whiteFont.setScale(0.7f, 0.7f);
sb.begin();
whiteFont.draw(sb, "2", body.getPosition().x, (questionLineBody.getPosition().y)*PPM);
sb.end();

The solution was to Basically * my x position by PPM.
ie.
Add these lines to the Render method:
windowCamera.position.y = box2dCamera.position.y * PPM;
windowCamera.update();
windowSpriteBatch.setProjectionMatrix(windowCamera.combined);
And Render the font like so:
whiteFont.draw (sb,"2", body.getPosition().x * PPM, body.getPosition().y * PPM);

Related

Render BitmapFont in 3D libgdx with ModelBatch

I want to render a BitmapFont within a libgdx ModelBatch. I've only found samples with "SpriteBatch". Of course I can move the SpriteBatch around in 3D space, but it is either rendered before or after the "ModelBatched" objects. But I'd like to have it rendered in the correct z position.
E.g.
Render modelInstanceA (z=20)
Render Font (z=30)
Render modelInstanceB (z=40)
Then modelInstanceB should cover Render Font should cover modelInstanceB.
In other words I'd like to render a font within a ModelBatch context.
modelBatch.begin(camera);
modelBatch.render(modelInstanceA);
modelBatch.render(font);
modelBatch.render(modelInstanceB);
modelBatch.end();
Is there a built in way to achieve this?
If the models are opaque, you could draw your text with SpriteBatch after the modelBatch.end() call, but you'd need to call Gdx.gl.glEnable(GL20.GL_DEPTH_TEST); before spriteBatch.begin(). Then disable it after spriteBatch.end() to clean up (libgdx classes by default expect it to be off).

Text scaling and positioning in libgdx

I am working with libgdx. I need to scale and position text. Let's say I want to draw X that is 30 pixels hight and I want it to be in the middle of the screen. I want to draw more of those in diffrent locations and with different scales.
Is there any way how could I achieve that? I can't find the solution anywhere. I dont want to create more BitmapFonts if possible.
If you want to handle all platforms (android, html, ios, desktop) you need to use several BitmapFonts in order to avoid ugly scaling. Otherwise, if you don't need to deploy to HTML, you can use the gdx-freetype extension (see here https://github.com/libgdx/libgdx/wiki/Gdx-freetype).
Assuming you go with BitmapFont, you can simply use code similar to this to center your text:
String text = "Your text here!";
TextBounds bounds = font.getBounds(text);
font.draw(batch, text, (width - bounds.width) / 2.0f, (height - bounds.height) / 2.0f);
For scaling, you can set the scale in font.draw, but you probably want several BitmapFont of various sizes to avoid ugly artifacts.

How can I avoid sprite distortion as the frame's bounding box changes?

I have a spritesheet (packed by the wonderful TexturePacker) that looks like so:
and the animation as an animation works well using the current code.
However, when the animation moves to a frame where the bounding box is smaller (e.g. when the legs are closer, when the figure is kneeling, etc.), the image distorts so that the smaller bounding box fills the bounding box of the sprite.
How can I fix this?
The spritesheet above is a frame-extraction from a sample Adobe flash animation.
Easier way:
You can make all the textureregions the same size.
Hard way:
Keep it like this, but you need to save and calculate the size and position of every textureregion to draw.
I personally recommend you the first option, just make all the image the same size.
cant give you a link but here is what i do for these situations
while making the texture packer strip the white space
make a array of AtlasSprite for images
then in my render method
public void render(float delta) {
atlasSprite = animation.getKeyFrame(statetime, Animation.LOOPING);
atlasSprite.draw(batcher)
};
in my update method, which gives exact rectangular bounds of the current image displayed. Since you have stripped the whitespace and used AtlasSprite so bounds will be without blank whitespace.
public void update(float delta) {
bounds = sprite.getBoundingRectangle();
}
P.S. this is just a pseudo code and many syntatical error could be there its just to give you a idea

as3 image over another using bitmap

Ok so im trying to load a bitmap image as a background using this:
screenBitmapData.copyPixels(tilesBitmapData,new Rectangle(sourceX,sourceY,tileSize,tileSize),new Point(destX,destY));
screenBitmap = new Bitmap(screenBitmapData);
addChild(screenBitmap);
This load my tiled map correctly and display it on the screen.
Now i want to add another image which will be used as my character and the frame displaying it contain my character movement and then display the image as follow:
screenBitmapData.copyPixels(playerSheetBitmapData, new Rectangle(currentSpriteColumn * CHAR_SPRITE_WIDTH, currentSpriteRow * CHAR_SPRITE_HEIGHT, CHAR_SPRITE_WIDTH, CHAR_SPRITE_HEIGHT), new Point(xPos, yPos), null, null,true);
I setted the alpha channel on my character image and this is the result when im moving around my map with it:
http://snag.gy/L2uuR.jpg
As you can see, the background image doesnt refresh. And i simply dont know how to do this. Im pretty new with flash and as3 and ive been trying for days to make it work. I know it have something to do with the copypixel or redrawing the background before i draw the sprite again... Any ideas?
You need to redraw the entire scene. All you're doing at the moment is drawing the player ontop of the result of your previous draw.
All you need to do in your case is draw the entire background each frame before you draw the character. It could look like this:
function renderScene():void
{
// Draw the background, which will replace all the current graphics
// on the Bitmap.
screenBitmapData.copyPixels(tilesBitmapData,new Rectangle(sourceX,sourceY,tileSize,tileSize),new Point(destX,destY));
// Then draw the player.
screenBitmapData.copyPixels(playerSheetBitmapData, new Rectangle(currentSpriteColumn * CHAR_SPRITE_WIDTH, currentSpriteRow * CHAR_SPRITE_HEIGHT, CHAR_SPRITE_WIDTH, CHAR_SPRITE_HEIGHT), new Point(xPos, yPos), null, null,true);
}
To actually clear the Bitmap though, you can just use fillRect() to fill it with a color (e.g. black):
// Fill the Bitmap with black.
screenBitmapData.fillRect( screenBitmapData.rect, 0x000000 );

rotating image using pixelbender

I have background image and smaller image. I copy the smaller image into the bigger image using copypixels like this:
destBitMap.copyPixels(img, new Rectangle(0, 0, img.width, img.height),
location);
Now I want to rotate the image before copying it. Whats the best way to do it?
I tried using Matrix and bitmapData.draw() but its unacceptable. it has pixelated edges.
I found this pixelbender filter : http://life.neophi.com/danielr/2009/07/image_rotation_with_pixel_bend.html
for rotating images. on the plus side, it is really fast. I never used pixelbender so Im curious if its possible to take that filter, apply it to bitmapimage and copy the rotated image into the background image.
This is what Ive tried (which doesnt work):
shader = new Shader(new RotateFilter() as ByteArray);
shader.data.origin.value = [resizedImage.width / 2, resizedImage.width / 2];
shader.data.rotation.value = [rotation];
filter = new ShaderFilter(shader);
var bm:BitmapImage = new BitmapImage();
bm.source = resizedImage;
bm.filters = [filter];
Whats next? Is this possible at all?
If you want to apply a single filter to a bitmap, use BitmapData.applyFilter() method. Obviously, you can do anything with the resultant bitmap. But, you have to apply all this on a lower level than UIComponent allows. If your resizedImage is type Bitmap, you do this:
resizedImage.bitmapData.applyFilter(resizedImage.bitmapData,resizedImage.bitmapData.rect,new Point(),filter);
After this, your resizedImage.bitmapData will contain a rotated bitmap.