LibGdx TiledMapRenderer leaves a flickering image after each render() call - libgdx

In LibGdx when I use the below code to render a tiled map the tiledMapRenderer.render() call leaves a flickering image in the black area after just one call (I tested this by rendering in the create method only) and I haven't been able to remove it. This flickering image becomes a problem when the window size changes.
TiledMap tiledMap;
OrthogonalTiledMapRenderer tMR;
ExtendViewport viewPort;
#Override
public void create () {
OrthographicCamera camera = new OrthographicCamera();
camera.setToOrtho(false, 512, 512);
viewPort = new ExtendViewport(512, 512, 512, 512, camera );
viewPort.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
tiledMap = new TmxMapLoader().load("LibGdxTutorial.tmx");
tMR = new OrthogonalTiledMapRenderer(tiledMap);
}
#Override
public void render () {
viewPort.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
tMR.setView((OrthographicCamera) viewPort.getCamera());
tMR.render();
}
This is the default window you get after pressing run
This is the window after I dragged the right side out
The map image on the right of the second photo is the full and correct one. The map image on the left is the flickering after image (it appears full because it's one frame). Any help would be appreciated, thanks.

You need to clear the screen each frame. This happens in the render method and should be used before you start drawing.
Gdx.gl.glClearColor(0f,0f,0f,1); // set the clear color
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // clear the screen with the given color.
.. draw next frame ..

Related

LibGdx View Port, resolutions, sprite size

Helllo, im new to libgdx, i need some help, if my desktoplauncher resolution is 480x320, sprite takes 80% of the screen, but if 1280x720, sprite is small, i need to make it look the same at all resoltions so how do i do this? may be easy for you, but not for my, im using libgdx 1.3.1
this is my libgdx code:
SpriteBatch batch;
Texture img;
Sprite mysprite;
#Override
public void create ()
{
batch = new SpriteBatch();
img = new Texture("badlogic.jpg");
mysprite = new Sprite(img);
stage = new Stage(new StretchViewport(480, 320));
}
StretchViewport myviewport = new StretchViewport(480, 320);
public void resize(int width, int height)
{
// use true here to center the camera
// that's what you probably want in case of a UI
stage.setViewport(myviewport);
stage.getCamera().position.set(640/2, 480/2, 0);
}
private Stage stage;
#Override
public void render ()
{
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
mysprite.draw(batch);
batch.end();
}
You are allready using the right thing: Viewport.
There are different Viewport classes, some of them support working with a virtual screen size, which is what you are looking for.
What is a virtual screen size? Well it is the screen size your code is working with and which is then scaled up to match the real resolution.
Basicly you can work with your own units and they are then automatically scaled up to match pixels.
I guess in your case there are 2 possible Viewport-types:
- StretchViewport supports virtual screen sizes and scales it up to match the real screen size and the real aspect ratio. If the real aspect ration does not match the virtual one the Sprites will be stretched, which could look strange.
- FitViewport is the same as the StretchViewport, but it will keep the aspect ratio. If the real aspect ration does not match the virtual one, black borders will appear.
How to use it:
First you need to create it:
myViewport = new StretchViewport(VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
Then set the Stages Viewport:
stage = new Stage(myViewport);
In the resize method you need to update your Viewport:
myViewport.update(width, height);
Thats all.
The stage now uses the Viewport and its camera to render. You don't need to touch the camera, unless you need to move it arround.
So your errors are:
stage = new Stage(new StretchViewport(480, 320));
Which creates a new StretchViewport you don't store/use.
stage.setViewport(myviewport);
You only need to set it once, when you create the stage
You never call update(width, height) for the Viewport.

Libgdx: Stage only renders at (0, 0)

I'm attempting to use LibGDX Stage for my GUI elements, but I'm having loads of difficulty getting it to render properly. Right now, I'm attempting to render a chat window in the lower left corner of the screen.
Here is the construction of the GUI objects:
stage = new Stage();
stage.setCamera(controller.getCamera());
uiSkin = new Skin(Gdx.files.internal("res/gui/skin/uiskin.json"));
Table table = new Table(uiSkin);
stage.addActor(table);
table.setSize(300, 260);
table.setPosition(0, 0);
table.setFillParent(false);
table.bottom();
table.left();
table.pad(10);
lblChatLabel = new Label("", uiSkin);
lblChatLabel.setWrap(true);
final ScrollPane scroll = new ScrollPane(lblChatLabel, uiSkin);
txtChatBar = new TextField("do a chat", uiSkin);
txtChatBar.setName("txtChatBar");
table.add(txtChatBar).width(300f);
table.row();
table.add(scroll).expand().fill().colspan(4);
txtChatBar.addListener(new InputListener() {
public boolean keyDown(InputEvent event, int keycode) {
if (keycode == Input.Keys.ENTER) {
sendMessage();
// Close the chat bar
showChat = false;
return true;
}
return false;
}
});
And here is my render() method:
Log.debug("void", "x: " + stage.getCamera().position.x + ", y: " + stage.getCamera().position.y);
stage.act();
for (Actor a : stage.getActors()) {
a.draw(spriteBatch, 1);
}
In another section of code elsewhere, the game's camera object is translated to center on the player:
camera.translate(targetPosition.x, targetPosition.y);
camera.update();
So that all said, the chat window renders properly, but it only does so at 0, 0. I've also changed called stage.draw() rather than iterate through the Actors individually, but that causes the same issue. Here is a screenshot illustrating the issue:
http://i.imgur.com/8uz5lV6.jpg
Finally, I've tried to translate the stage manually by setting the viewport, but that causes an even weirder issue.
float cx = controller.getCamera().getX();
float cy = controller.getCamera().getY();
float width = controller.getCamera().viewportWidth;
float height = controller.getCamera().viewportHeight;
stage.act();
stage.setViewport(width, height, true, cx, cy, width, height);
stage.draw();
Image here:
http://i.imgur.com/JpSLq1s.jpg
Certainly I am doing something wrong, but I have no idea at this point. I would have assumed that the stage follows the Camera translation, but that doesn't appear to be the case. Any suggestions are welcome! Thanks!
I believe the issue is this line of code:
stage.setCamera(controller.getCamera());
If I'm reading correctly, you want the chat window to always render from (0,0), no matter where the camera is on the screen. If that's the case, then the stage shouldn't have any relation with the camera, which moves around and just further complicates getting the stage in the right position to be rendered properly.
Without that line of code, you should be able to just call
stage.act();
stage.draw();
and it should work fine.

libGDX stage draw me mirrored text

I use Stage in libGDX for drawing GUI and adding listeners to controls in my game.
But when I draw text on ImageTextButton I get mirrored text as displayed on image below.
Can some help me and tell me how to draw normal text, not mirrored ?
stage = new Stage(Constants.VIEWPORT_GUI_WIDTH, Constants.VIEWPORT_GUI_HEIGHT);
stage.clear();
....
ImageTextButtonStyle imageTextButtonStyle = new ImageTextButtonStyle();
imageTextButtonStyle.font = Assets.instance.fonts.defaultSmall;
ImageTextButton imageTextButton = new ImageTextButton("ddsds", imageTextButtonStyle);
imageTextButton.setBackground( gameUISkin.getDrawable("fil_coins"));
imageTextButton.setPosition(50, 600);
imageTextButton.setHeight(85);
imageTextButton.setWidth(183);
stage.addActor(imageTextButton);
....
public void render (float deltaTime) {
stage.act(deltaTime);
stage.draw();
}
Thanks
Edit:
Button images are shown correct, only text has mirrored view
As #Springrbua suggest me in comment below, my bitmap font was flipped when creating.
defaultSmall = new BitmapFont(Gdx.files.internal("images/font.fnt"), true);
should be
defaultSmall = new BitmapFont(Gdx.files.internal("images/font.fnt"), false);
Even it's not case here it may be useful for someone - if font size parameter is set to negative value, text will be rendered upside-down (Y-scale).

LibGDX Android Game - displaying fixed text (ie Score) over a scrolling screen

I am beginning to write a game in LibGDX, only just beginning. I have got a basic tile map loaded, a player sprite and can move the character around and the screen (camera) scrolls around - perfect.
I have two overlayed textures in the bottom right of the screen, a left and right arrow, which are used as the joypad to control the character. I position these in relation to the players.x position, which is always fixed to the centre of the screen. Cool so far .... As below:
/////////////////////////////////////////////////////////////////
private void renderJoypad(float deltaTime)
{
batch.draw(Assets.leftJoypad, blockman.position.x-14, 1, 3, 3);
batch.draw(Assets.rightJoypad, blockman.position.x-9, 1, 3, 3);
}
I am now trying to put the player's score in the top left of the screen. The score is made of a Bitmap font, as below.
font = new BitmapFont(Gdx.files.internal("fonts/minecrafter.fnt"),Gdx.files.internal("fonts/minecrafter.png"),false);
font.setScale(0.02f);
In my render() method I cam calling some other methods to update, like the positions of the
leftJoypad etc, as in renderJoypad(). I am also calling my draw font method to update the position of the score, however, when I scroll it is all jerky, and sometimes it shows less characters than there should be.
public void drawScore(float deltaTime)
{
font.draw(batch, "00000", blockman.position.x, 10);
}
I believe that I need to place the score (and any other on screen texts, HUD etc) into a stage, but I cannot understand how to get it working with my existing code.
My show method is as follows:
public void show()
{
//load assets class to get images etc
Assets Assets = new Assets();
//start logging Framerate
Gdx.app.log( GameScreen.LOG, "Creating game" );
fpsLogger = new FPSLogger();
//set the stage - bazinga
Gdx.input.setInputProcessor(stage);
//stage.setCamera(camera);
//stage.setViewport(480, 360, false);
batch = new SpriteBatch();
//load the Joypad buttons
loadJoypad();
//background image
loadBackground();
//sounds
jumpSound = Gdx.audio.newSound(Gdx.files.internal("sounds/slime_jump.mp3"));
//LOAD block man here
// load the map, set the unit scale to 1/16 (1 unit == 16 pixels)
loadMap();
//draw the score
font = new BitmapFont(Gdx.files.internal("fonts/minecrafter.fnt"),Gdx.files.internal("fonts/minecrafter.png"),false);
font.setScale(0.02f);
// create an orthographic camera, shows us 30x20 units of the world
camera = new OrthographicCamera();
camera.setToOrtho(false, 30, 20);
camera.update();
// create the Blockman we want to move around the world
blockman = new Blockman();
blockman.position.set(25, 8);
}
and my render() method is as follows:
public void render(float delta)
{
// get the delta time
float deltaTime = Gdx.graphics.getDeltaTime();
stage.act(deltaTime);
stage.draw();
// clear the screen
Gdx.gl.glClearColor(0.3f, 0.3f, 0.3f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderBackground(deltaTime);
batch = renderer.getSpriteBatch();
//updateBlockman(deltaTime);
blockman.update(deltaTime);
// let the camera follow the blockMan, x-axis only
camera.position.x = blockman.position.x;
camera.update();
// set the tile map rendere view based on what the
// camera sees and render the map
renderer.setView(camera);
renderer.render();
//start the main sprite batch
batch.begin();
// render the blockMan
renderBlockman(deltaTime);
renderJoypad(deltaTime);
drawScore(deltaTime);
batch.end();
fpsLogger.log();
}
I have tried to change the way things work with relation to the Spritebatch etc and just cannot seem to get it working as I require.
Can anyone suggest how I may approach getting a stage and actors to work, or a second camera or something to help me achieve a fixed score display in the corner.
Do I need to use Scene 2D or something - aahhh! My head is exploding....
I look forward and thank you in advance.
Regards
James
I have a couple of suggestions:
Check to see if you have setUseIntegerPositions set to true
(the default) when you draw your font. If you do, and you're scaling
it, then it can cause some odd effects similar to those that you
describe. Set it to false and see if it fixes the problem.
Reset your spritebatch's matrices before drawing the text, that way you won't need to adjust it for the scrolling.
I'd even go as far as to recommend not scaling the font if you can help it, because fonts often look a little odd after being scaled.

Supporting Multiple image resolution for libgdx

How should I follow the directory structure and what to specify so that assetManger will use that folder for different resolution.
I have studied assetManager and ResolutionFileResolver but until now I couldn't exactly figured how to specify the folder to support different resolutions.
Update: Newer versions of Libgdx use a different strategy to resolve filenames (with directories, not files), so this answer does not apply to newer Libgdx versions after (0.9.2, I think? https://github.com/libgdx/libgdx/commit/3afcfe49c40196765033a90b4610159183dde981)
The built-in ResolutionFileResolver does not use a directory hierarchy. It uses file suffixes to match screen resolutions to assets.
Here's the code from the libGDX AssetManagerTest:
Resolution[] resolutions = { new Resolution(320, 480, ".320480"),
new Resolution(480, 800, ".480800"),
new Resolution(480, 856, ".480854") };
ResolutionFileResolver resolver = new ResolutionFileResolver(new InternalFileHandleResolver(), resolutions);
AssetManager manager = new AssetManager();
manager.setLoader(Texture.class, new TextureLoader(resolver));
...
The resolver appends one of those suffixes based on the current screen resolution. So, for example, if you look up "foo.jpg" on a 480x800 device, the file "foo.jpg.480800" will be opened.
If you want to resolve files based on directories (so "foo.jpg" would be resolved to "480x800/foo.jpg" or something like that), you can write a new resolver. Just implement FileHandleResolver. The ResolutionFileResolver.java source is probably a good place to start.
Once me too suffered from this problem but at end i got the working solution, for drawing anything using SpriteBatch or Stage in libgdx. Using orthogrphic camera we can do this.
first choose one constant resolution which is best for game. Here i have taken 1280*720(landscape).
class ScreenTest implements Screen{
final float appWidth = 1280, screenWidth = Gdx.graphics.getWidth();
final float appHeight = 720, screenHeight = Gdx.graphics.getHeight();
OrthographicCamera camera;
SpriteBatch batch;
Stage stage;
Texture img1;
Image img2;
public ScreenTest(){
camera = new OrthographicCamera();
camera.setToOrtho(false, appWidth, appHeight);
batch = new SpriteBatch();
batch.setProjectionMatrix(camera.combined);
img1 = new Texture("your_image1.png");
img2 = new Image(new Texture("your_image2.png"));
img2.setPosition(0, 0); // drawing from (0,0)
stage = new Stage(new StretchViewport(appWidth, appHeight, camera));
stage.addActor(img2);
}
#Override
public void render(float delta) {
batch.begin();
batch.draw(img, 0, 0);
batch.end();
stage.act();
stage.act(delta);
stage.draw();
// Also You can get touch input according to your Screen.
if (Gdx.input.isTouched()) {
System.out.println(" X " + Gdx.input.getX() * (appWidth / screenWidth));
System.out.println(" Y " + Gdx.input.getY() * (appHeight / screenHeight));
}
}
//
:
:
//
}
run this code in Any type of resolution it will going to adjust in that resolution without any disturbance.
If you use an OrthographicCamera you won't need to deal with different image resolutions.
Say that you have a camera with the size 400x300. Then you draw a 400x300 large image at coordinate (0,0). Then, regardless of screen resolution, the image will be scaled to fill the screen. This is really neat on Android where the screen resolution can vary a lot between different devices, and doing it like this you won't have to think about it.