Scaling an image with LibGDX SpriteBatches - java

I have my image (for the sake of explaining, lets call it Image.png) and I'm trying to get it to scale to properly fit in my Bodies I have drawn. The bodies and everything work with the debug but I'm not a fan of it.. I'm using a SpriteBatch to draw the background image onto the screen(it would be nice to scale that too). How would I scaleImage.png to the same size/position as a Dynamic body that has been rendered?
EDIT:
While drawing the images, I cant get them to match up with the debug render Bodies..
Creating Body:
BodyDef bodydef2 = new BodyDef();
bodydef2.type = BodyType.DynamicBody;
bodydef2.position.set(camera.viewportWidth + 30.0f, (int)(Math.random()*camera.viewportHeight)%(LastPlatformY+5)+20);
//System.out.println(bodydef2.position.y + " " + LastPlatformY);
Body block = world.createBody(bodydef2);
PolygonShape Shape2 = new PolygonShape();
Shape2.setAsBox(750*WORLD_TO_BOX, 200*WORLD_TO_BOX);
FixtureDef fixtureDef2 = new FixtureDef();
fixtureDef2.shape = Shape2;
fixtureDef2.density = 1000.0f;
fixtureDef2.friction = 0.0f;
fixtureDef2.restitution = 0;
block.setLinearVelocity(new Vector2((float) (Platform_Velocity*-1), 0));
block.createFixture(fixtureDef2);
//Lock 'block' to X-Axis, Relative to floor.
PrismaticJointDef jointDef = new PrismaticJointDef();
jointDef.collideConnected = true;
jointDef.initialize(block, groundBody, block.getWorldCenter(), new Vector2(1, 0));
world.createJoint(jointDef);
Platforms.add(block);
Platforms_Created++;
LastPlatformY = (int)bodydef2.position.y;
Drawing Image:
sp.draw(platforms, (float)(Platforms.get(i).getPosition().x), (float)(Platforms.get(i).getPosition().y), 75,20);
EDIT #2:
turns out that if your camera is smaller than the size of your screen you have to do some compensation to account for that variation in positions.. Problem solved, thanks!

Just save the size of your body in two variables while creating your body and then call the appropriate draw method.
To get the position of your object call body.getPosition().
For example
Texture t = assetManager.get("your texture", Texture.class);
BodyDef bodyDef = new BodyDef();
body.type = BodyType.DynamicBody
float width = 64 * WORLD_TO_BOX;
float height = 64 * WORLD_TO_BOX;
Shape shape = new PolygonShape();
float[] points = new float[]{0,0,width,0,width,height,0, height};
shape.set(points);
FixtureDef def = new FixtureDef();
def.shape = shape;
...
body.createFixture(def);
shape.dispose();
And later when you want to draw
public void render(Spritebatch batch) {
batch.draw(t, body.getPosition().x * BOX_TO_WORLD, body.getPosition().y * BOX_TO_WORLD, width * BOX_TO_WORLD, height * BOX_TO_WORLD);
}

Related

Set appearance stream on highlight annotation with iText7

I have a PDF viewer that doesn't show highlights if they do not have an appearance stream. I'm trying out iText 7 core in java to try and add highlight annotations to PDFs but these annotations do not have appearance streams, and thus I'm looking to try and add them myself when writing the annotations to the PDF file.
I've come across this old answer, but it's for C# and iText 5, and I can't seem to figure out how to replicate it in iText 7 with a successful result.
So my question is thus: how do you set appearance streams on the highlighting annotations in iText 7 core that are working?
The furthest I've gotten with the code is shown below. I'm using the RegexBasedLocationExtrationStrategy class to find the locations of all search words in the pdf.
RegexBasedLocationExtractionStrategy evntlstnr = new RegexBasedLocationExtractionStrategy(pattern);
for (int pIdx = 0; pIdx < pdfDoc.getNumberOfPages(); ++pIdx) {
final PdfPage page = pdfDoc.getPage(pIdx + 1);
new PdfCanvasProcessor(evntlstnr).processPageContent(page);
Collection<IPdfTextLocation> locations = evntlstnr.getResultantLocations();
for (IPdfTextLocation location : locations) {
Rectangle rect = location.getRectangle();
// Specify quad points in Z-like order
// [0,1] x1,y1 [2,3] x2,y2
// [4,5] x3,y3 [6,7] x4,y4
float[] quads = new float[8];
quads[0] = rect.getX();
quads[1] = rect.getY() + rect.getHeight();
quads[2] = rect.getX() + rect.getWidth();
quads[3] = quads[1];
quads[4] = quads[0];
quads[5] = rect.getY();
quads[6] = quads[2];
quads[7] = quads[5];
Color highlightColor = new DeviceRgb(0f, 0f, 1f);
PdfTextMarkupAnnotation highlight = PdfTextMarkupAnnotation.createHighLight(rect, quads);
highlight.setColor(highlightColor);
Rectangle appearRect = new Rectangle(0f, 0f, rect.getWidth(), rect.getHeight());
PdfFormXObject appearObj = new PdfFormXObject(appearRect);
final PdfResources appearRes = appearObj.getResources();
PdfExtGState extGState = new PdfExtGState();
extGState.setBlendMode(PdfExtGState.BM_MULTIPLY);
appearRes.addExtGState(extGState);
appearObj.setBBox(new PdfArray(new float[] {0f, 0f, rect.getWidth(), rect.getHeight()}));
PdfShading appearShading = new PdfShading.Axial(highlightColor.getColorSpace(), 0f, 0f, highlightColor.getColorValue(), 1f, 1f, highlightColor.getColorValue());
appearRes.addShading(appearShading);
appearRes.addColorSpace(highlightColor.getColorSpace());
PdfAnnotationAppearance appearance = new PdfAnnotationAppearance(appearObj.getPdfObject());
highlight.setNormalAppearance(appearance);
highlight.setFlag(PdfAnnotation.PRINT);
page.addAnnotation(highlight);
}
}
Using Samuel's answer I stumbled my way to a working answer.
I'm no expect in the PDF standard and this framework (iText), but my hypothesis, based on my working example below, is that the rectangle I was trying to write for the highlight is a crude fall-back method for "faking" the highlight rectangle when the viewer cannot render the annotations (since they have no appearance stream). Realizing this that the two operations are not linked, I came to the working example shown below. Hope this helps others in the future.
RegexBasedLocationExtractionStrategy evntlstnr = new RegexBasedLocationExtractionStrategy(pattern);
for (int pIdx = 0; pIdx < pdfDoc.getNumberOfPages(); ++pIdx) {
final PdfPage page = pdfDoc.getPage(pIdx + 1);
new PdfCanvasProcessor(evntlstnr).processPageContent(page);
Collection<IPdfTextLocation> locations = evntlstnr.getResultantLocations();
for (IPdfTextLocation location : locations) {
Rectangle rect = location.getRectangle();
// Specify quad points in Z-like order
// [0,1] x1,y1 [2,3] x2,y2
// [4,5] x3,y3 [6,7] x4,y4
float[] quads = new float[8];
quads[0] = rect.getX();
quads[1] = rect.getY() + rect.getHeight();
quads[2] = rect.getX() + rect.getWidth();
quads[3] = quads[1];
quads[4] = quads[0];
quads[5] = rect.getY();
quads[6] = quads[2];
quads[7] = quads[5];
Color highlightColor = new DeviceRgb(1f, 1f, 0f);
PdfTextMarkupAnnotation highlight = PdfTextMarkupAnnotation.createHighLight(rect, quads);
highlight.setColor(highlightColor);
highlight.setFlag(PdfAnnotation.PRINT);
page.addAnnotation(highlight);
PdfCanvas canvas = new PdfCanvas(page);
PdfExtGState extGState = new PdfExtGState();
extGState.setBlendMode(PdfExtGState.BM_MULTIPLY);
canvas.setExtGState(extGState);
canvas.rectangle(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
canvas.setFillColor(highlightColor);
canvas.fill();
canvas.release();
}
}

Use of texture in extrude geometry (GWT)

I'm creating shapes with extrude geometry on GWT, now I want to apply textures on it but I am not able to apply it directly. How can I do that?
My code looks like :
ExtrudeGeometry extrudeMaterialBoard = null;
shapeExtrude.getExtrudeSettings().amount = (int) getMaterialThickness();
shapeExtrude.getExtrudeSettings().curveSegments = 1;
shapeExtrude.getExtrudeSettings().bevelThickness= 5;
shapeExtrude.getExtrudeSettings().bevelSize= 5;
shapeExtrude.getExtrudeSettings().bevelEnabled= true;
shapeExtrude.getExtrudeSettings().material = 0;
shapeExtrude.getExtrudeSettings().extrudeMaterial = 1;
extrudeMaterialBoard = new ExtrudeGeometry(DrawShape.getBottomBoard(), shapeExtrude.getExtrudeSettings());
camera = new PerspectiveCamera(
70, // fov
getRenderer().getAbsoluteAspectRation(), // aspect
1, // near
1000 // far
);
camera.getPosition().setZ(400);
String texture1 = "uvgrid0.jpg";
MeshBasicMaterial material = new MeshBasicMaterial();
material.setColor(getColor(COLOR_TRANSPARENT));
Texture texture = new Texture(texture1);
material.setMap(texture);
mesh = new Mesh(extrudeMaterialBoard, material);
getScene().add(mesh);
getRenderer().render(getScene(), camera);
If I use cube geometry then its running properly. But in case of extrude geometry its not working.
Thanks in advance.

Rotate an image while it is being used

I am creating a car game and I want to rotate my car ( Image ) when I'm using the car but I don't know how. I've tried a few things that don't work. Here is what I have:
g2d.drawImage(DEFAULT_CAR_SKIN, DEFAULT_BOX.x, DEFAULT_BOX.y, null);
DEFAULT_BOX.setLocation(DEFAULT_BOX.x + 1, DEFAULT_BOX.y);
if (Game.rotateFront == true) {
AffineTransform identity = new AffineTransform();
AffineTransform trans = new AffineTransform();
trans.setTransform(identity);
trans.rotate(Math.toRadians(Game.Angle));
g2d.drawImage(DEFAULT_CAR_SKIN, trans, this);
}
But this code draws a new image but with the characteristics that I want.

Box2D crashes when destroying body (Expression: m_bodyCount < m_bodyCapacity)

Expression: m_bodyCount < m_bodyCapacity
That is the error I'm getting. The entire game crashes when I get this error. Now, here's the thing: I only get the error on certain I try to destroy, more specifically, bodies that were made during the game. What I mean is at the beginning of the game, I load the level and create all the bodies for each piece of the level. But, there are items that are made as the game runs, such as bullets, cannons, and coins. I can destroy any of the bodies created when the level is loaded, but when I try to destroy bodies created afterwards, I get the above error.
Here's an example. I spawn a CannonBall with my Cannon:
Cannon.class
if(reloadProgress >= RELOAD_TIME) {
CannonBall cannonBall = new CannonBall();
cannonBall.setXDirection(xDirection);
cannonBall.setYDirection(yDirection);
cannonBall.position.set(cannonBallPos);
Box2DHelper.makeFixture(cannonBall, BodyType.KinematicBody, origin, WorldController.b2world,
true, false);
Level.cannonBalls.add(cannonBall);
reloadProgress -= RELOAD_TIME;
} else {
reloadProgress += deltaTime;
}
Where Box2DHelper.makeFixture() is:
public static void makeFixture(GameObject object, BodyType type,
Vector2 origin, World b2world, boolean addUserData, boolean isMonster) {
BodyDef bodyDef = new BodyDef();
bodyDef.type = type;
bodyDef.position.set(object.position);
Body body = b2world.createBody(bodyDef);
if(addUserData)
body.setUserData(object);
object.body = body;
PolygonShape polygonShape = new PolygonShape();
origin.x = object.bounds.width / 2.0f;
origin.y = object.bounds.height / 2.0f;
polygonShape.setAsBox(object.bounds.width / 2.0f,
object.bounds.height / 2.0f, origin, 0);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = polygonShape;
if(isMonster) fixtureDef.filter.groupIndex = Constants.GROUP_MONSTER;
body.createFixture(fixtureDef);
polygonShape.dispose();
}
So now I've created my CannonBall and set its body. Now, after 10 seconds, if it hasn't hit anything, I destroy it:
CannonBall.class
if (existanceDuration >= CANNON_BALL_EXISTANCE_DURATION) {
//Destroy cannon ball
CollisionHandler.bodiesToRemoveList.add(this.body);
}
Now that I have added the body into the list, I have to remove it:
CollisionHandler.class:
public static void removeSpecifiedBodies() {
Iterator<Body> i = bodiesToRemoveList.iterator();
while (i.hasNext()) {
Body desBod = i.next();
removeObjectFromList(desBod); //This is just to remove the object as well
WorldController.b2world.destroyBody(desBod);
if (perCharHitAction == true) {
performCharacterDeathAction(Level.character);
perCharHitAction = false;
}
i.remove();
}
bodiesToRemoveList.clear();
}
But now, I need to actually call this method. I do this in my main update method, right after b2world.step():
WorldController.class:
public void update(float deltaTime) {
...
b2world.step(deltaTime, 8, 3);
if (CollisionHandler.bodiesToRemoveList.size() > 0)
CollisionHandler.removeSpecifiedBodies();
Now, like I stated before, this method works fine when I destroy objects made at the loading of the level, but on objects I later create, it doesn't.
Why does my game keep crashing after trying to destroy box2d bodies later created in my game?
Edit: I call this method right after the level has loaded for creating the object's bodies:
private void initPhysics() {
if (b2world != null)
b2world.dispose();
b2world = new World(new Vector2(0, -9.81f), true);
Vector2 origin = new Vector2();
b2world.setContactListener(new CollisionHandler());
// Create Box2D Fixtures
for (Grass grass : Level.grasses)
Box2DHelper.makeEdgeChain(grass, BodyType.StaticBody, origin,
b2world, true);
// Bricks
for (Brick brick : Level.bricks)
// Box2DHelper.makeFixture(brick, BodyType.KinematicBody, origin,
// b2world, true);
Box2DHelper.makeEdgeChain(brick, BodyType.StaticBody, origin,
b2world, true);
// Item Boxes
for (ItemBox box : Level.itemBoxes)
Box2DHelper.makeFixture(box, BodyType.KinematicBody, origin,
b2world, true, false);
//Enemies
for (Goomba goomba : Level.goombas)
Box2DHelper.makeFixture(goomba, BodyType.DynamicBody, origin,
b2world, true, true);
for (Koopa koopa : Level.koopas)
Box2DHelper.makeFixture(koopa, BodyType.DynamicBody, origin,
b2world, true, true);
// Cannons
for (Cannon cannon : Level.cannons)
Box2DHelper.makeFixture(cannon, BodyType.KinematicBody, origin,
b2world, true, true);
// Character
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.set(Level.character.position);
Body body = b2world.createBody(bodyDef);
body.setUserData(Level.character);
Level.character.body = body;
CircleShape polygonShapeHead = new CircleShape();
origin.x = Level.character.circleBoundOrigin.x * 2.0f;
origin.y = Level.character.circleBoundOrigin.y * 3.0f;
// polygonShapeHead.setAsBox(level.character.circleBoundOrigin.x,
// level.character.circleBoundOrigin.y, origin, 0);
polygonShapeHead.setPosition(origin);
polygonShapeHead.setRadius(Level.character.circleBoundOrigin.x);
FixtureDef fixtureDefHead = new FixtureDef();
fixtureDefHead.shape = polygonShapeHead;
fixtureDefHead.friction = Level.character.friction.x;
body.createFixture(fixtureDefHead);
polygonShapeHead.dispose();
PolygonShape polygonShapeBod = new PolygonShape();
origin = Level.character.rectBoundOrigin;
polygonShapeBod.setAsBox(Level.character.rectBoundOrigin.x,
Level.character.rectBoundOrigin.y, origin, 0);
FixtureDef fixtureDefBod = new FixtureDef();
fixtureDefBod.shape = polygonShapeBod;
fixtureDefBod.friction = Level.character.friction.x;
body.createFixture(fixtureDefBod);
polygonShapeBod.dispose();
}
Maybe the issue when creating bodies later in the game is the b2world?
I had the same Error - I figured out, that it happens if you destroy the same body multiple times.
In my case I put the body into a list in the contact listener.. but I didn't make sure it was in the list only once.
That also explains why your problem was fixed once you worked with a boolean flag, that also made sure the same body was only destroyed once.
In short: You get this error if you try to destroy the same body over and over again.

Libgdx: Is there an easy way to center text on each axis on a button?

I have been trying to figure out a way to center text on a button, but can't find an easy, multi-purpose way to. I can do it, but it will only work for a certain string, not for any string. i would like to know if there is a way to center any string on a button. My button in this case is 185x50.
I have been able to center this button on the screen, like so:
buttonX = WIDTH / 2 - (screen.getRegionWidth() / 2);
buttonY = HEIGHT / 2 - (screen.getRegionHeight() / 2);
Any help would be much appreciated. :)
Updated the answer to libgdx version 1.7.1-SNAPSHOT:
The easiest way to do this, is to use the TextButton class from libgdx. The text from a TextButton is centered by default. This still works!
Updated example:
final BitmapFont font = new BitmapFont();
final String text = "Test";
final GlyphLayout layout = new GlyphLayout(font, text);
// or for non final texts: layout.setText(font, text);
final float fontX = objectX + (objectWidth - layout.width) / 2;
final float fontY = objectY + (objectHeight + layout.height) / 2;
font.draw(batch, layout, fontX, fontY);
Outdated example:
This no longer works!
If you do not want to use it, you can get the font width and height with:
font.getBounds("Test text");
So you can do something like this:
String fontText = "";
fontX = buttonX + buttonWidth/2 - font.getBounds(fontText).width/2;
fontY = buttonY + buttonHeight/2 + font.getBounds(fontText).height/2;
For the newer version of libgdx the function BitMapFont.getBounds() isn't there in api anymore. You can use GlyphLayout to get bounds.For example,
BitmapFont font;
SpriteBatch spriteBatch;
//... Load any font of your choice first
FreeTypeFontGenerator fontGenerator = new FreeTypeFontGenerator(
Gdx.files.internal("myFont.ttf")
);
FreeTypeFontGenerator.FreeTypeFontParameter freeTypeFontParameter =
new FreeTypeFontGenerator.FreeTypeFontParameter();
freeTypeFontParameter.size = size;
fontGenerator.generateData(freeTypeFontParameter);
font = fontGenerator.generateFont(freeTypeFontParameter);
//Initialize the spriteBatch as requirement
GlyphLayout glyphLayout = new GlyphLayout();
String item = "Example";
glyphLayout.setText(font,item);
float w = glyphLayout.width;
font.draw(spriteBatch, glyphLayout, (Game.SCREEN_WIDTH - w)/2, y);
Try the following:
label.setPosition(Gdx.graphics.getWidth()/2-(label.getPrefWidth()/2),Gdx.graphics.getHeight()-(label.getPrefHeight()/2));

Categories