I am trying to use BitMapFont in libgdx based game.I do this:
BitmapFont font;
this.font = new BitmapFont();
render{
Gdx.gl.glClearColor(0x64 / 255.0f, 0x95 / 255.0f, 0xed / 255.0f,
0xff / 255.0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.app.log(TAG, " FPS: " + Gdx.graphics.getFramesPerSecond());
batch.setProjectionMatrix(CameraManager.camera.combined);
batch.begin();
font.setColor(Color.BLACK);
font.draw(batch, "Time", 4, 4);
batch.end();
}
And my camera is managed as:
public class CameraManager {
public static OrthographicCamera camera;
public CameraManager(){
camera = new OrthographicCamera(Constants.VIEWPORT_WIDTH, Constants.VIEWPORT_HEIGHT);
camera.viewportWidth = (camera.viewportHeight)
* ((float) Gdx.graphics.getWidth() / (float) Gdx.graphics
.getHeight());
camera.position.set(camera.viewportWidth / 2,
camera.viewportHeight / 2, 0);
camera.update();
}
public void resize(int width, int height) {
camera.viewportWidth = (camera.viewportHeight)
* ((float) width / (float) height);
camera.update();
}
}
But instead of text, several rectangles are displayed whose color is the color I pass to setColor().I really have no idea whats happening here. Most of the tutorials use this simple piece of code.But it is just not working for me.
Please advise.
I would recommend downloading some .ttf fonts and passing them in into the bitmap font object like so
BitmapFont font = new BitmapFont(Gdx.files.internal("fontfile.ttf"));
Here are a lot of great .ttf fonts you can download https://www.google.com/fonts
Related
I would like to have a TV screen on my stage. I have a master scene containing the TV screen and some other things (some sprites) and the scene corresponding to what I want to render in the TV.
So I would like to render the TV scene through an OrthographicCamera and then put the result in something like a sprite which can then be rendered through the master orthographic camera, how to do that?
I know that one can use multiple camera in multiple viewports but these are directly rendered on the pixels of my computer screen.
Any advice would be much appreciated
This can be achieved by rendering the scene from the perspective of a screen camera to a FrameBuffer and then taking the TextureRegion from the FrameBuffer and rendering that to screen and then render the scene again.
For example:
In the above example the cyan rect shows what the in-scene camera sees, and this is rendered to the grey box, it is possible to move both the scene camera and the main camera independentely.
By creating and grabbing the TextureRegion from a FrameBuffer
screenFrameBuffer = new FrameBuffer(Pixmap.Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(),true);
screenTexture = new TextureRegion(screenFrameBuffer.getColorBufferTexture());
screenTexture.flip(false, true);
all render calls can be made to affect only the screenFrameBuffer by calling screenFrameBuffer.begin(), after screenFrameBuffer.end() is called the next draw call will again affect the actual screen/window.
So in in the render method you can first draw your scene to the FrameBuffer
screenFrameBuffer.begin();
renderScene(screenCamera, Color.DARK_GRAY);
screenFrameBuffer.end();
And then draw it again, followed by the "screen" as a sprite:
renderScene(sceneCamera, Color.BLACK);
batch.setProjectionMatrix(sceneCamera.combined);
batch.begin();
batch.draw(screenTexture, -sceneCamera.viewportWidth / 2.0f,-sceneCamera.viewportHeight / 2.0f,0,0,screenCamera.viewportWidth,screenCamera.viewportHeight,1.0f, 1.0f, 0.0f);
batch.end();
Complete source code for the gif above is:
package com.bornander.sandbox;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.*;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.FrameBuffer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.RandomXS128;
import com.badlogic.gdx.math.Vector2;
public class MyGdxGame implements ApplicationListener {
public static class Ball {
public Vector2 position = new Vector2();
public Vector2 velocity = new Vector2();
public float size = 1.0f;
public Color color = new Color();
public void render(ShapeRenderer shapeRenderer) {
shapeRenderer.setColor(color);
shapeRenderer.circle(position.x, position.y, size, 16);
}
public void update() {
position.x += velocity.x * Gdx.graphics.getDeltaTime();
position.y += velocity.y * Gdx.graphics.getDeltaTime();
}
}
static RandomXS128 rnd = new RandomXS128();
OrthographicCamera sceneCamera;
OrthographicCamera screenCamera;
ShapeRenderer shapeRenderer;
SpriteBatch batch;
FrameBuffer screenFrameBuffer;
TextureRegion screenTexture;
Ball[] balls;
private static float rnd(float min, float max) {
return min + rnd.nextFloat() * (max - min);
}
#Override
public void create() {
float aspectRatio = (float) Gdx.graphics.getWidth() / (float)Gdx.graphics.getHeight();
sceneCamera = new OrthographicCamera(100.0f, 100.0f / aspectRatio);
screenCamera = new OrthographicCamera(32.0f, 32.0f / aspectRatio);
batch = new SpriteBatch();
screenFrameBuffer = new FrameBuffer(Pixmap.Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(),true);
screenTexture = new TextureRegion(screenFrameBuffer.getColorBufferTexture());
screenTexture.flip(false, true);
shapeRenderer = new ShapeRenderer();
balls = new Ball[128];
for(int i = 0; i < balls.length; ++i) {
balls[i] = new Ball();
balls[i].position.set(0, 0);
balls[i].velocity.set(rnd(-4, 4), rnd(-4, 4));
balls[i].size = rnd(1, 1);
balls[i].color.set(rnd(0.5f, 1.0f), rnd(0.5f, 1.0f), rnd(0.5f, 1.0f), 1.0f);
}
}
private void renderScene(Camera camera, Color background) {
camera.update();
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClearColor(background.r, background.g, background.b, background.a);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
for(int i = 0; i < balls.length; ++i) {
balls[i].render(shapeRenderer);
}
shapeRenderer.end();
}
#Override
public void render() {
float cs = 8.0f;
for(int i = 0; i < balls.length; ++i)
balls[i].update();
if (Gdx.input.isKeyPressed(Input.Keys.LEFT))
sceneCamera.position.x -= cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT))
sceneCamera.position.x += cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.UP))
sceneCamera.position.y -= cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.DOWN))
sceneCamera.position.y += cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.A))
screenCamera.position.x -= cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.D))
screenCamera.position.x += cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.W))
screenCamera.position.y -= cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.S))
screenCamera.position.y += cs * Gdx.graphics.getDeltaTime();
// Render to framebuffer, clear the background to DARK_GRAY
screenFrameBuffer.begin();
renderScene(screenCamera, Color.DARK_GRAY);
screenFrameBuffer.end();
// Render to window/screen, clear backgroun to BLACK
renderScene(sceneCamera, Color.BLACK);
// Draw the framebuffer's texture as a sprite using a normal SpriteBatch
batch.setProjectionMatrix(sceneCamera.combined);
batch.begin();
batch.draw(screenTexture, -sceneCamera.viewportWidth / 2.0f,-sceneCamera.viewportHeight / 2.0f,0,0,screenCamera.viewportWidth,screenCamera.viewportHeight,1.0f, 1.0f, 0.0f);
batch.end();
// This just draws the outline of what the screen camera looks at
shapeRenderer.setProjectionMatrix(sceneCamera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
shapeRenderer.setColor(Color.CYAN);
shapeRenderer.rect(
screenCamera.position.x - screenCamera.viewportWidth / 2.0f,
screenCamera.position.y - screenCamera.viewportHeight / 2.0f,
screenCamera.viewportWidth,
screenCamera.viewportHeight
);
shapeRenderer.end();
}
#Override
public void dispose() {
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}
How can I drag a texture (image) without making it jump and centering itself on the mouse cursor (what I have below in my code)?
When I click on the texture, nothing should happen, and when I drag, the mouse cursor should stay in place (relative to the edges of the texture).
Example: https://s31.postimg.org/ojapwbj6j/Untitled_1.jpg
SpriteBatch batch;
Texture texture;
OrthographicCamera camera;
Vector3 spritePosition = new Vector3();
float offsetX, offsetY;
Vector3 input;
#Override
public void create () {
batch = new SpriteBatch();
texture = new Texture("badlogic.jpg");
camera = new OrthographicCamera();
camera.setToOrtho(false);
}
#Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(texture, spritePosition.x, spritePosition.y);
batch.end();
if (Gdx.input.justTouched()){
int x1 = Gdx.input.getX();
int y1 = Gdx.input.getY();
input = new Vector3(x1, y1, 0);
camera.unproject(input);
offsetX = x1 - spritePosition.x;
offsetY = y1 - spritePosition.y;
}
if (Gdx.input.isTouched()) {
spritePosition.set(Gdx.input.getX() - offsetX, Gdx.input.getY() - offsetY, 0);
}
}
What you need to do is work out the offset of the mouse position relative to your image, and subtract that, rather than half the width / height as you're doing at the moment.
Here's some very rough pseudocode to show what I mean - You'll need to rewrite as Java...
if Gdx.input.justTouched {
get mouse position from Gdx.input
camera.unproject it into cameraX and cameraY
offsetX = cameraX - imageX
offsetY = cameraY - imageY
}
if Gdx.input.isTouched {
spritePisition.set(Gdx.input.getX() - offsetX, Gdx.input.getY - offsetY)
}
Why are you using camera.unproject?
Try this:
Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(texture, spritePosition.x, spritePosition.y);
batch.end();
if (Gdx.input.isTouched()) {
spritePosition.set(Gdx.input.getX() - texture.getWidth() / 2, Gdx.input.getY() + texture.getHeight() / 2, 0);
}
}
I am trying a box2d body to rotate following the mouse. Here's an image to clarify what I mean.
The red and blue circles are current point of the mouse and the body (of corresponding color) moving/rotating to follow it. Basically the rectangle should rotate with its one end pointed towards where the mouse pointer is.
Here's my code so far,
World world;
Body body, bullet;
Box2DDebugRenderer debugRenderer;
OrthographicCamera camera;
#Override
public void create() {
world = new World(new Vector2(0, 0f), true);
debugRenderer = new Box2DDebugRenderer();
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(10, 10);
body = world.createBody(bodyDef);
PolygonShape shape = new PolygonShape();
shape.setAsBox(2, 5);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = 1f;
Fixture fixture = body.createFixture(fixtureDef);
shape.dispose();
Gdx.input.setInputProcessor(this);
camera = new OrthographicCamera(200, 100 * (h / w));
camera.position.set(camera.viewportWidth / 2f, camera.viewportHeight / 2f, 0);
camera.update();
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
world.step(Gdx.graphics.getDeltaTime(), 6, 2);
camera.update();
debugRenderer.render(world, camera.combined);
}
#Override
public boolean mouseMoved(int screenX, int screenY) {
int mouseX = screenX;
int mouseY = Gdx.graphics.getHeight() - screenY;
float rotateAngle = MathUtils.radiansToDegrees * MathUtils.atan2((float) mouseY - (float) body.getPosition().y, (float) mouseX - (float) body.getPosition().x);
body.setTransform(body.getPosition(), rotateAngle / 57.2957795f);
return true;
}
And here's a gif of how it appears now.
as you can see the body gets skewed and also doesn't rotate properly. What am I missing?
The skew looks like a problem with aspect correction, try,
camera = OrthographicCamera(200, 100 * (w / h));
or even,
camera = OrthographicCamera(200, 100);
To get the end of the box to follow the mouse as in the picture just redefine the box,
shape.setAsBox(5, 2, Vector2(offset, 0), 0);
My game has an end of level screen, on which I wish to display an animated player score. If you have seen the one in Angry birds and many other games, the score text starts at "000000" and increments rapidly until it reachs the actual score the player achieved. I have tried to write this with a while loop, and a for loop but it just doesn't work properly - I am obvioulsy still misunderstanding how the update method works. Here is my render() method of my End of Level screen:
#Override
public void render (float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
timeElapsed = delta;
while(this.iCounter < this.score) {
font.draw(batch, "Score: " + this.iCounter, screenWidth / 2, screenHeight / 2);
if(timeElapsed > 1.0f) {
iCounter = iCounter + 10;
}
timeElapsed = 0.0f;
}
batch.end();
}
The above just seems to crash the screen.
I just want the score to start at zero and then every half a second for example increase the score until it reaches the actual score.
Has anyone got any ideas on how to do this properly as I just can't seem to get this working.
You are calling font.draw() multiple times inside the render. The result would be multiple scores, drawn over ach other.
Note, that render is called once per frame and you want to animate the score over n Frames.
So your variable iCounter should be a class variable, and you increment and draw it once inside the render method. Yoou may also want to store a constant scorePerSecond, which defines how much the iCounter increments per second.
So the result should look like this:
public static final int SCORE_PER_SECOND = 100;
private int iCounter;
public void render (float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
iCounter = Math.min((int)(iCounter+SCORE_PER_SECOND*delta), score)
font.draw(batch, "Score: " + this.iCounter, screenWidth / 2, screenHeight / 2);
batch.end();
}
The render method is called every frame and all the drawing you put in there should just be for a single frame. What it's doing is trying to run your entire look in a single frame, and hence looking like it's crashed.
What you need to do is get rid of the loop and just add an amount to iCounter each frame (i.e. each time render() is called).
Here's your coded edited into a very simple implementation to show what I mean...
#Override
public void render (float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
font.draw(batch, "Score: " + this.iCounter, screenWidth / 2, screenHeight / 2);
if (this.iCounter < this.score) {
this.iCounter++;
}
batch.end();
}
This will increment the score every single frame, which I think is probably what you want. Eitehr way it should provide a good starting point.
Thanks to everyone above who helped me. This is how I got it working in the end.
time += delta;
if (time >= this.SCORE_DELAY) {
if (iCounter < this.score) {
iCounter = iCounter + 10;
}
time -= this.SCORE_DELAY;
}
SCORE_DELAY is declared as a float and I have got the setting at 0.15f which seems to be a good rate.
private static float SCORE_DELAY = 0.15f;
Hi i am new to libgdx and try to build a ludo game.right know i could draw the board but when i try to show dice or any peaces nothing happens I attach game code .
please read and help.
public void create() {
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
batch = new SpriteBatch();
camera = new OrthographicCamera(1, h / w);
boardtexture = new Texture(Gdx.files.internal("data/ludo-boardx2.png"));
boardtexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
boardsprite = new Sprite(boardtexture);
boardsprite.setSize(1f,
1f * boardsprite.getHeight() / boardsprite.getWidth());
boardsprite.setOrigin(boardsprite.getWidth() / 2,
boardsprite.getHeight() / 2);
boardsprite.setPosition(-boardsprite.getWidth() / 2,
-boardsprite.getHeight() / 2);
Texture dice = new Texture(Gdx.files.internal("data/dices.png"));
dice.setFilter(TextureFilter.Linear, TextureFilter.Linear);
dtemp = new Sprite(dice);
dtemp.setSize(1f, 1f * dtemp.getHeight() / dtemp.getWidth());
dtemp.setPosition(0f, 0f);
// System.out.println(w/2+" " +h/2);
// System.out.println(dtemp.getWidth()+":"+dtemp.getHeight());
// animatedDice.setPosition(new Vector2(0, 0));
System.out.println(animatedDice.getX() + ":" + animatedDice.getY()
+ "\n" + w + ":" + h);
}
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
// camera.update();
handleInput();
batch.begin();
boardsprite.draw(batch);
dtemp.draw(batch);
//animatedDice.draw(batch);
batch.end();
// animatedDice.update();
}
You are drawing your die at a position of (w/2, h/2), which is way out of range of your viewport. You set your viewport so the X coordinate of the right side of your screen is 0.5, but your sprite's left side is at x=w/2, where w is the number of pixels wide your window is.
Even if you had set your camera size to match the window ((w, h)), you would have an issue here because you'd be drawing your sprite so its left edge matched the right edge of the screen. By default, the origin of your die sprite will be its lower left corner.
If you aren't planning to zoom your scene in and out, it might be simpler to set your camera viewport to the size of the window by using camera = new OrthographicCamera(w, h); Then you'll know that your units are equivalent to pixels.