Libgdx create a TextButton with background with uiskin.json - java

I want to define the background of TextButton with uiskin.json.
Here is what i tried but didn't work:
com.badlogic.gdx.scenes.scene2d.ui.Skin$TintedDrawable: {
img: { file: bg.png }
},
com.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle: {
default: { down: default-round-down, up: img, font: default-font, fontColor: white }
}
So I want to make bg.png as the default background. How can i do it?

Skin cannot read file locations from the json. If you followed tutorials for Skin, you probably instantiated it with a TextureAtlas like this:
skin = new Skin(skinFilePath, textureAtlas);
When you load it like that, all the images in the json must be available by their names in the TextureAtlas.
Normally, you need all your images to be in a single TextureAtlas, for performance reasons. So the best solution would be to add this bg.png image into your TextureAtlas, and then you can refer to it by its TextureAtlas name.
If you must load it as a separate file, then you must manually load it before loading your skin.
Texture bgTexture = new Texture("bg.png");
skin = new Skin(); //empty constructor causes it not to load yet.
skin.add("bg", bgTexture);
skin.addRegions(textureAtlas); // you will be responsible for disposing the atlas separately from the skin now.
skin.load(skinFilePath);

Related

Relative URL not working in javafx

I would like to put an image on a Label, and the codes are:
Label userPic = new label();
ImageView userImage = new ImageView(
new Image("test/123/headPortrait.png",50.0,50.0,false,false));
userPic.setGraphic(userImage);
But it continually throws java.lang.IllegalArgumentException: Invalid URL or resource not found.
And I've tried file://headPortrait.png, file://E:/eclipse/ClassSchedule/headPortrait.png(the absolute URL). This time the compiler did not throw any exception, but the image still won't show up and the application runs very slowly.
Before I tried to add an image to the label, all of my code had worked perfectly.
It's not good pratice to put an ImageView into a label. I would recommend to you that you add the ImageView to your scene directly.
To load an Image in the classpath the best way to do that would be using a ResourceStream,
this.getClass().getResourceAsStream("/assets/headPortrait.png")
as example. In this case your image must be in a folder called assets.
Your whole code could look like this:
ImageView imageView = new ImageView(new Image(this.getClass().getResourceAsStream("/assets/headPortrait.png"), 50, 50, false, true));
I would recommend to you to set the last boolean flag of the Image constructor to true, because it increases the quality of the image.

Error when using JSON to initialize TextButton (Libgdx)

I'm trying to initize a TextButton by giving it a JSON file which contains the style of the button, however I keep getting the following error:
Exception in thread "LWJGL Application"
java.lang.IllegalArgumentException: Missing LabelStyle font.
After researching what the error was about, it seems that this message shows up when you forget to include a font as part of the TextButtonStyle, however i do include that in my JSON file, so i don't know why it keeps showing.
Here's my json file
{
"com.badlogic.gdx.graphics.Color":{
"golden":{"r":255,"g":215,"b":0,"a":1}
},
"com.badlogic.gdx.graphics.g2d.BitmapFont": {
"arcade": {"file": "arcade.fnt"}
},
"com.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle": {
"default": {
"font": arcade,
"fontColor": golden
}
},
"com.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle": {
"buttonstyle1": {
"up": "unpressedtextbutton",
"down": "pressedtextbutton",
"font": arcade
}
}
}
and in the code I initialize the button like this:
Skin skin = new Skin(Gdx.files.internal("buttonstyles.json"),new TextureAtlas(Gdx.files.internal("uistuff.atlas")));
myTextButton = new TextButton("text of the button",skin,"buttonstyle1")
My theory is that somehow it is not reading the font file "arcade.fnt", i'm assuming that the directory it reads the files from is the assets folder, and that's where my "arcade.fnt" file is located.
i'm sorry it seems like i made a stupid mistake. Since i declared the font in the JSON file, i erased the font i was previously using in the code to define the button styles, and there was a usage of that font later for a label style, so, it was found to be null and it gave the error.
Is it working like this? The official uiskin.json does it like this:
com.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle: {
default: { font: default-font, fontColor: white }
}
No quotes are needed at all not even for the font.
com.badlogic.gdx.graphics.g2d.BitmapFont: {
default-font: { file: default.fnt }
},
Might not be proper JSON but libgdx has it's own lightweight JSON style.

OSMdroid - Replace empty grid background when no tile available (offline)

I'm using OSMdroid library in my project to display map tiles (it's a shape with lines and blank background) from my company local sever in my app. The thing is when I use the app in offline mode and I browse the map shows an empty grey grid background for the tiles that aren't in the cache, and I want to change that empty grey grid for an blank background image/tile.
The only workaround that I've found to achieve this is the following:
Add a tile overlay and set setLoadingBackgroundColor and setLoadingLineColor to Color.WHITE, and then set the TileSource from the local server from OnlineTileSourceBase. I know this is not quite performant, so is there a better way to do this? Thanks in advance!
final ITileSource tileSource = new OnlineTileSourceBase(...)
{
#Override
public String getTileURLString(MapTile aTile) {
return getBaseUrl() + aTile.getX() + "+" + aTile.getY() + "+" + aTile.getZoomLevel();
}
};
tileProvider = new MapTileProviderBasic(context, tileSource);
tilesOverlay = new TilesOverlay(tileProvider , context);
tilesOverlay.setLoadingBackgroundColor(Color.WHITE);
tilesOverlay.setLoadingLineColor(Color.WHITE);
this.map.getOverlays().add(tilesOverlay);
this.map.setTileSource(tileProvider.getTileSource());
map.invalidate();
Your code is an example on adding a secondary tile overlay. That's useful for when you need another raster graphics overlay on top of the map imagery.
You can also change the loading lines and background for the existing and default tiles overlay. This should get you going
mMapView.getOverlayManager().getTilesOverlay().setLoadingBackgroundColor(Color.TRANSPARENT);
mMapView.getOverlayManager().getTilesOverlay().setLoadingLineColor(Color.TRANSPARENT);

Store sprites from spritesheet in array Libgdx

I have 960x960 spritesheet stored as a png inside of my Libgdx android assets. In a class I have specified towards initializing sprites for use in my game, I am trying to make it so there is a 120x120 sprite cut from the spritesheet (so there should be 64 items in the array). How am I able to do this? This is what I have tried in a similar situation:
public static Texture spritesheet;
public static Sprite[] textures = new Sprite[64];
...
//inside method that gets called once to initialize variables
spritesheet = new Texture(
Gdx.app.getType() == Application.ApplicationType.Android ?
"...Spritesheet.png" :
"android/assets/...Spritesheet.png"
);
spritesheet.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
for (int x = 0; x < 64; x ++) {
textures[x] = new Sprite(spritesheet, x, (x%8), 64, 64);
textures[x].flip(false, true);
}
I then render the sprite in other classes with this:
batch.draw(Assets.textures[0 /*this can be any number*/], (float) x, (float) y, 108, 108);
When I do this, it acts really weird. It says there are elements filled in the array, but there's still Array Index Out of Bounds Exceptions or the sprites just render crazily. Overall, it's not working out. What I'm trying to do is make it so I don't have to initialize 64 different sprites separately, and make it so I can easily change the sprite by changing the index inputted when rendering the sprite so I can do some other things later on, like an animation. How can I go about doing this?
You should use a TextureAtlas for this purpose. A atlas is a file generated automatically from separate images by the LibGDX TexturePacker. It stores everything from image bounds within your sheet to NinePatch information. All you need to do is put your separate images in a folder and run the TexturePacker on that folder. This will create a sheet and a .atlas/.pack file for you that can easily loaded.
There exists a TexturePackerGui if you have difficulty with the commandline but I do recommend the command line or even using it within your app.
What I usually do is create these sheets on the fly when I'm developing. I can easily overwrite separate images and they have a immediate effect after I run my app again. I start with creating a new folder images at the root of my project. Then for each pack I need I create another folder. For this example I create the folder tileset in images. In the DesktopLauncher I will setup this folder to produce a atlas from the images.
TexturePacker.Settings settings = new TexturePacker.Settings();
settings.maxWidth = 1024;
settings.maxHeight = 1024;
The settings file specifies everything about your atlas. The maximum size of a single sheet, if it should strip transparency from images, padding, rotation, etc. They are all very straightforward and you can look these all up in the documentation. Using these settings you can create your atlas.
TexturePacker.process(settings,
"../../images/tileset", //where to find the images to be packed.
"../../android/assets/tileset/", //where to store the atlas and sheet
"tileset"); //what filename to use
Now you can open your .atlas file and you see it uses the filenames as a alias. This alias is used to look them up but let's load the atlas first.
TextureAtlas atlas = new TextureAtlas("tileset/tileset.atlas");
By passing just a string to the constructor it looks by default in your local path which in turn is by default in android/assets/. Now we can ask the atlas to hand over our assets in the sheet.
atlas.findRegion("alias"); //hands over the image on the sheet named "alias"
Looking up textures like this is somewhat expensive. You don't want to look up many textures like this each update so you still need to store them somewhere.
If you name your image sequence like image_01.png, image_02.png, image_03.png it stores them all under the same name and within the atlas it sorts them bu it's index. So if you want a separate array of certain textures you can name them with _xx and get them all in one go:
atlas.findRegions("alias");
This is especially handy for Animation. Just copy your image sequence to a folder and specify it to be packed. Name your sequence correctly and give the regions to the animation. Everything will work right off the bat.
Loading a TextureAtlas with the AssetManager is pretty much the same as a normal Texture except you would specify it's from a TextureAtlas.class. You always load the .atlas which in turn handles your image.
I always use AssetDescriptor to load my assets. If I where you I would get rid of the static Assets.textures[] since that will get you into trouble sooner or later.
//None static AssetManager with getter
private AssetManager manager = new AssetManager();
public AssetManager getManager() { return manager; }
//Specify a descriptor for the atlas, this is static so I can acces it anywhere.
//It's just a descriptor of the asset so this is safe.
public static final AssetDescriptor<TextureAtlas> TileSet = new AssetDescriptor<TextureAtlas>("tileset/tileset.atlas", TextureAtlas.class);
//then just load everything
public void load()
{
manager.load(tileSet);
//... load other stuff
}
Now just pass the AssetManager object anywhere you need access to your assets and you can load any asset just like so:
TextureAtlas tileset = assetManager.get(Assets.TileSet);
I think your for loop should look like this
for(int x = 0; x < 64; x ++){
textures[x] = new Sprite(
spritesheet,
(x%8)*64, //where x=3, (3%8)*64 = 3*64 = 192px sourceX
(x/8)*64, //where x=3, (int)(3/8)*64 = 0*64 = 0px sourceY
64, //source width
64 //source height
);
Another test case where x=20;
(20%8)*64 = 4*64 = 256px SourceX
(20/8)*64 = 2*64 = 128px SourceY

Libgdx reload scene2d skin after application hidden

I'm having an issue with libgdx skin.
When the app is paused or goes into the background and then reopens all my scene2d textures are just showing up black. I assume that the underlying textures need to be reloaded.
I'm creating my skin using the following code
FileHandle jsonFile = Gdx.files.internal( "ui/uiskin.json" );
FileHandle atlasFile = Gdx.files.internal( "ui/uiskin.atlas" );
TextureAtlas atlas = new TextureAtlas(atlasFile);
skin = new Skin(jsonFile, atlas);
My question is if there any way that I can detect when the texture needs to be reloaded and how to best do this?
I have found that it is best to rebuild the skin when you reopen your app.

Categories

Resources