I'm trying to make a progress bar in LibGdx. I'm using scene 2D to put elements into the screen (is a loading screen). I'm using a table, where I put an image, a label ("loading...") and a progress bar.
The progress bar is composed by two images. My problem is that I cannot overlay the two images. I'm using this code
stage.addActor(root);
root.add(image).width(200).height(200);
root.row();
root.add(new Label("Loading...", skin));
root.row();
root.add(progressBarBG).width(600);
root.add(progressBarFG).height(30).width(30);
root.pack();
Gdx.input.setInputProcessor(stage);
But the progressBarBG and progressBarFG are draw one followed by the other. It is a way to put one over the other one?
ProgressBarBG and ProgressBarFG are loaded from a texture atlas. Root is a Table.
Thanks.
As Springrbua mentioned, it's best to use ProgressBar for this.
Though, to answer your question, you can use a Group to overlap images with scene2d. Simply add all of the images to one group, then add that group to the desired parent. If you need to offset any of the images in the group, you can use image.setPosition(offsetX, offsetY). Here's an example for your case:
stage.addActor(root);
root.add(image).width(200).height(200);
root.row();
root.add(new Label("Loading...", skin));
root.row();
//Use groups to overlay multiple images
Group group = new Group();
progressBarBG.setWidth(600);
progressBarFG.setSize(30, 30);
group.addActor(progressBarBG);
group.addActor(progressBarFG);
root.add(group);
root.pack();
Gdx.input.setInputProcessor(stage);
I used this code to place a diamond image over a box image:
Image boxImage = new Image(Assets.instance.gifts.box);
Image diamondImage = new Image(Assets.instance.gifts.diamond);
Stack diamondBox = new Stack();
diamondBox.addActor(boxImage);
diamondBox.addActor(diamondImage);
tbl.add(diamondBox).width(20).height(20);
tbl.row();
Related
I'm looking for a way of rendering a scene hidden from view and then creating a second shrunken copy for initial display. Plainly I could render the contents a second time to create this copy only smaller. The original code written in another language though produced a better result using a smooth (spatially filtered) shrinking function to create the small copy. Is there such a bitmap copy/shrink/smooth function in JavaFX and is it any good?
You can create a snapshot of a scene as a WritableImage as follows:
Scene scene = ... ;
Image image = scene.snapshot(null);
and then display a scaled version of it in an image view with:
ImageView sceneImage = new ImageView();
sceneImage.setFitWidth(desiredWidth);
sceneImage.setFitHeight(desiredHeight);
// force aspect ratio to be preserved if fitWidth and fitHeight would distort it:
sceneImage.setPreserveRatio(true);
// this provides a tiny bit of control over the scaling used:
sceneImage.setSmooth(true);
sceneImage.setImage(image);
I am trying to do a project with javafx but I can't create the figures to a puzzle game with tiles, in order to push them with the click of a button. How can an Image be cropped and saved as an individual tile ?
The ImageView class is used to display an image. It has a viewport property that represents the portion of the image it is viewing. So you can create multiple image views from the same image, each with a different viewport: then you can add the image views to a pane of some kind, register mouse handlers on them, etc.
If you actually need to store each piece as an individual image, you can snapshot the image view to create a new Image from it. You'll probably find you don't need this, however.
You might want to try PixelReader and WritableImage APIs from JavaFX platform.
I've been using an ImageView object to try and modify an Image and then draw it. However I could only make the two following outcomes happen:
1) After ImageView has been modified, I tried to grab the image out of it for display with getImage() but that only displayed the original Image I had in the first place.
example code:
sheet = new Image("file:sprite_sheet.png");
ImageView iv = new ImageView();
iv.setImage(sheet);
iv.setViewport(new Rectangle2D(0, 0, 32, 32));
g.drawImage(iv.getImage(), 100, 100);//'g' is GraphicsContext2D
2) I managed to get the modified image to show by adding it to the Group obj like so:
root.getChildren().add(iv);
But then it only displayed the image in the top left corner of the screen and I couldn't move it or do anything with it.
I prefer (if possible) to approach this issue with a method more like the first outcome has presented. And just saying this in advance, I'm aware of that that there's another post similar to this atm, but I couldn't get anything useful out of it.
ImageView, as the name implies, is just a view of the data (image in this case). All modifications to the view only affect the view and not the data. There are two general methods for what you want to achieve.
Use scene graph and ImageView object. Perform all visual operations on the view. This is the preferred way as the data stays the same, meaning you can easily create a new ImageView with the original image and modify it in a different way should you wish to. If the parent is Pane, then you can easily move the object by calling setTranslateX/Y.
If you absolutely need to use Canvas, then you will need to modify the data itself or create a copy of the data and modify it instead. You can do this by using a combination of the following: PixelWriter and PixelReader
Example for 1.:
ImageView view = new ImageView(image);
// create root with dimension 800x600
Pane root = new Pane();
root.setPrefSize(800, 600);
// attach view to root so it can be displayed
root.getChildren().add(view);
// translate view to 100, 100
// on the screen this means the image will move 100 in X and 100 in Y
view.setTranslateX(100);
view.setTranslateY(100);
I've read about libgdx's scene2d features, including the UI elements, but I can't get them to work. They all seem to use a skin object, how do I create one?
I've gone through the nice tutorial that creates a simple libgdx game catching raindrops in a bucket, and I've created a simple board game app by loading images with a texture atlas. However, scene2d sounds like a better way to control the moving pieces in a board game app, as well as any buttons and menus.
To load a skin, you can start with the sample skin files used in the libgdx test project.
Atlaspack File
Json File
Atlaspack Image
Font File
There's a bit more detail in this question, and I found that I had to move the files into a subdirectory of assets to avoid a bug in the HTML version. (If I leave files in the assets folder, I see an error message like, "GwtApplication: exception: Error reading file data/uiskin.json.")
I posted a complete example that displays a single button, and the interesting code is all in the game class. The example is so simple that you only need two member variables to hold the scene and the button.
private Stage stage;
private TextButton button;
To create the skin, you just load the data file.
Skin skin = new Skin(Gdx.files.internal("data/uiskin.json"));
Wire the button into the stage.
stage = new Stage();
button = new TextButton("Click Me!", skin);
stage.addActor(button);
Wire a listener into the button, and register the stage to receive events.
button.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
button.setText("Clicked!");
}
});
Gdx.input.setInputProcessor(stage);
The render() method is basically a call to stage.draw().
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));
stage.draw();
Then you just need to layout the screen when it resizes.
button.setPosition(
(width-button.getWidth())/2,
(height-button.getHeight())/2);
If your screen is more complicated, consider using a Table.
If you want to use a different font, you can generate the font file and image file using Hiero. After you've done that, you'll have to take the new font image and use the TexturePacker to repack it with the other skin assets.
Now Libgdx provide Git repository to get skin, you can download it from: https://github.com/libgdx/libgdx-skins, copy assets:https://github.com/libgdx/libgdx-skins/tree/master/skins/visui/assets to your project
I have been able to successfully swap in my own image for the expandable listview arrows. I have two issues at the moment.
One is that the icons i substitue in with the code below are each strechted to the height of the row and too wide as well. The second is, that this code is only changing the initial state of the Group Indicator. How do I change it from one image to another when a particular row is open?
Drawable plus = (Drawable) getResources().getDrawable(R.drawable.plus);
getExpandableListView().setGroupIndicator(plus);
Android's default behavior is to stretch the groupIndicator icon. It's a ninepatch, so if you don't want it to stretch the image, you have to make the stretchable area of your ninepatch the transparent regions on both sides of the icon.
To make it change appropriately when the ExpandableListView opens, you have to use a StateListDrawable. Add the appropriate Drawables for the following states:
int[][] states = new int[][] {
new int[] { android.R.attr.state_expanded },
new int[] { },
};
You do that like so:
StateListDrawable sld = new StateListDrawable();
sld.addState(states[0], YOUR_EXPANDED_DRAWABLE);
sld.addState(states[1], YOUR_UNEXPANDED_DRAWABLE);
And set that to the groupIndicator.
Hope that helps.
What you could do, is onCollapse and onExpand change the group indicator drawable. Source