I have a problem with my texture. The table works perfect, but when I try to add a texture Android Studio doesn't agree with me.
private Sprite tiger2;
.
batch.begin();
batch.setColor(tiger2.getColor());
batch.draw(
tiger2,
Gdx.graphics.getWidth() / 2f - tiger2.getRegionWidth() / 2f,
Gdx.graphics.getHeight() / 2f - tiger2.getRegionHeight() / 2f,
tiger2.getRegionWidth(),
tiger2.getRegionHeight()
);
batch.end();
.
tiger2 = new Sprite(new Texture("tiger2.png"));
.
I don't know if this is how I should write it:
table.add(tiger2);
I get this error:
Cannot resolve method 'add(com.badlogic.gdx.graphics.g2d.Sprite)'
table.add(**tiger2**);
You are trying to add a Sprite to the table not a Texture and this is the core reason why you are having problems. It is basically the same as doing int i = "Hello World" which would yield a error like incompatible types. In other words a Integer container cannot hold a String.
If you hover over the line you will see that table.add expects a actor. If you would go to the definition of Sprite you notice that this does not extend Actor in any way. So doing Actor a = new Sprite() results in the same error as above, you cannot put a Sprite object in a Actor container. These are core fundamentals of programming.
So what are compatible Actors? Everything that inherits Actor such as Label, TextButton, Table, ScrollPane, Window, Dialogue, etc. You can extend Action yourself too and create your very own Actor, but since you are struggling with this you should wait with this.
The easiest solution is to use scene2d.ui.Image. If you inspect this class you see it extends from Widget and if you inspect Widget you see it extends from Actor and thus Image is a actor since you are a child of your mother and your mother of your grandmother.
If you inspect what the Image constructor takes then you will notice the easiest thing to do is to create a SpriteDrawable, since Image does not take a Sprite like table.add does not take a Sprite either. SpriteDrawable takes a sprite and is a Drawable and that is compatible with the constructor of Image.
Image image = new Image(new SpriteDrawable(mySprite));
table.add(image);
Image takes a Texture too so if you are not doing fancy Sprite stuff with your sprite you can just create the Image with a Texture as well. You can see this in your IDE by typing new Image( and intellisense will let you know the compatible constructors.
Try to understand these types and use your IDE and the documentation to find out what you can use. With Android Studio you can right click a class and do goto -> declaration and see the class in question. Other IDE's have equivalent methods unless you are using something like Notepad of course.
Assuming the table is a Scene2D Table:
A texture is not an actor and cannot be added to a table. To fix this you can add the texture to an Image (an actor containing a texture). It would look something like this:
Image tiger2Image = new Image(new Texture("tiger2.png"));
table.add(tiger2Image);
Related
I have a general question about how to design dynamic UI elements in Android (with Java).
I would like to have a thermometer in my app that depending on some external information increases or decreases a red bar(shown below).
. How can i design something like this in Android?
I could for example just design the thermometer without the red bar as a jpeg with some drawing program and then somehow implement the red bar in Android as an object that can be changed programmatically whereas the 'rim' of the thermometer does not change.
The problem I see with this approach is that I believe it is extremely difficult to match the rim of the thermometer with the red bar for different screen sizes and resolutions. Do you have another suggestion on how I could do something like this? Is there maybe a library for this?
I'd appreciate every comment as I have no experience whatsoever generally with designing such dynamic UI objects.
Updated Answer:
I have created a demo project on Github here. This project has the Thermometer custom view in which the outer thermometer is drawn from an image file and the inside mercury view of the thermometer is drawn from the code. You can look over the project of user kofigyan I shared in my previous answer for other customizations.
Previous Answer:
I think what are you looking for is creating Custom Views in Android.
You can extend the Android View class and can create your Custom View. The View has a Canvas object on which you can draw the shape of a Thermo-meter and can build functionalities to change the state of your shape in your subclass itself. Moreover, with the Paint object, you can paint your drawn shape.
I found this project on Github by a user kofigyan.
For having a dynamic ui you can take two approaches.
Jetpack Compose(not being discussed since it's still in Beta)
LiveData and observer pattern
In LiveData and observer pattern. Give the temperature as a LiveData variable(in your ViewModel) and implement an Observer in your MainActivity which gets triggered automatically when the value of the temperature live data changes.
For getting the output graphic you can use a canvas and then draw on it and tie it to the temperature variable.
You could for example use the Canvas.drawRect function to create a short or long rectangle depending on the temperature. ( the part from the circle to the top of the thermometer can be the rectangle)
I am currently doing a school project where we are creating an Asteroids game using Codename One. My current functionality works well, except for when it comes to rotating the image of the ship. Using the Transform class has been ineffective; the image does not rotate, no matter how the Transform is applied or the image is drawn.
Here is a sample portion of the code used to turn:
public void turnRight() //Rotates the ship 5 degrees clockwise
{
if (direction==355)
direction = 0;
else
direction+=5;
Transform tmpTransform = Transform.makeIdentity();
theImage.getGraphics().getTransform(tmpTransform);
tmpTransform.rotate((float)Math.toRadians(5), x, y);
theImage.getGraphics().setTransform(tmpTransform);
theImage.getGraphics().drawImage(shipPic, 0, 0);
}
Where:
theImage is a mutable Image (100x100)
shipPic is an Image created via Image.createImage(String path)
In addition, I have tried using the draw(Graphics g, Point p) method and passing theImage.getGraphics(), as well as passing shipPic.getGraphics()
I am at a loss, and Codename One's documentation on the subject is unhelpful.
Could I get some assistance, please?
You need to use one graphics object so something like this:
Graphics g = theImage.getGraphics();
Would be more correct. You also must test for transform support when rendering onto an image as low level graphics isn't always portable to all OS's in all surfaces. A good example is iOS where rendering onto an image uses a completely different low level implementation than the display rendering.
Normally I would render directly to the display as that is hardware accelerated on modern devices and images are often implemented in software.
About the documentation, did you read the graphics section in the developer guide?
It should contain explanations of everything and if something is missing there is search. If you still can't find something and figure it out by yourself notice you can also edit the docs and help us improve them.
I am working on a desktop game with libGDX. I want to reduce the aliasing, that is very strong.
There is documentation about that. The magic is supposed to happen in the DesktopLauncher class with the line config.samples = samplingNumber;
I tried 2, 4, 8 and 16 sampling number. I am unable to see a difference.
Here is my DesktopLauncher class.
public class DesktopLauncher {
public static void main (String[] arg) {
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.title = "AA Test";
config.width = 1280;
config.height = 720;
config.samples = 8;
new LwjglApplication(new MyGdxGame(), config);
}
}
And here is an image showing the difference between no AA and MSAA 16x. The same result is observed for MSAA 2x, 4x and 8x.
Am I missing something to apply MSAA to my libGDX project ?
I found a solution to this problem.
texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
The sampling field, as you experienced, has no effect but setting this filter on the Textures did.
If you are using TextureAtlas then you can do the following to your TextureAtlas object.
atlas.getTextures().forEach(t -> t.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear));
MSAA only affects the edges of polygons, which are not usually visible in a 2D scene because sprites typically do not bleed all the way to their rectangular edges. (Exceptions are opaque rectangular sprites, and shapes drawn with ShapeRenderer.)
Your image quality looks to me like you are not using a mip mapping filter. Load your texture with the useMipMaps parameter true, and use a min filter of MipMapLinearLinear or MipMapLinearNearest (the first looks better, costs more). Note: a MipMap filter does nothing if you didn't load your Texture with useMipMaps true.
There are AA techniques that do process all pixels of the screen, but they are more expensive than simply using mip mapping and trilinear filtering. One example is FXAA, which is done not with a configuration setting, but by drawing your scene to a frame buffer object, and then drawing the FBO's texture to screen with a special shader.
Your GPU chip could not support MSAA although then it should support CSAA.
To make it work you need to replace
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
with
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT | (Gdx.graphics.getBufferFormat().coverageSampling?GL20.GL_COVERAGE_BUFFER_BIT_NV:0));
in your render method. Then set config.samples for Desktop or config.numSamples for Android to the desired value.
Read more about LibGDX AA here
I've created a small piece of code which draws a 3D cube in my SWT application allowing to rotate it.
Now, I want to change each face/side of the cube and draw a different image on it, but I can't find how to do it (or at least, in an easy way, if that's possible).
I was able to change the complete texture of the cube to an image, but it change all the faces and I want to set a different image to each face. Is this possible? Any code example?
Thanks
Ok, based on the previous answer and some other forums I reach the following code that allows to set a different texture to each face of a cube:
Basically the line that allows to do that is the following one:
((Shape3D) textureCube.getChild(POSITION)).setAppearance(APPEARANCE);
Taking into account that:
textureCube:
Box textureCube = new Box(0.4f, 0.4f, 0.4f, Box.GENERATE_TEXTURE_COORDS,
defaultAppearance);
(defaultAppearance is just a basic Appearance object: Appearance defaultAppearance = new Appearance();)
The position is given by, as vembutech pointed out, TextureCubeMap class and their values for each face: POSITIVE_X, POSITIVE_Y, POSITIVE_Z, NEGATIVE_X, NEGATIVE_Y, NEGATIVE_Z.
And the appearance object is just an appearance object. I created mine appearance objects with this method:
private Appearance getAppearance(String f) throws Exception {
Appearance app = new Appearance();
URL texImage = new java.net.URL("file:" + f);
Texture tex = new TextureLoader(texImage, this).getTexture();
app.setTexture(tex);
TextureAttributes texAttr = new TextureAttributes();
texAttr.setTextureMode(TextureAttributes.MODULATE);
app.setTextureAttributes(texAttr);
return app;
}
This method creates an appearance based on an input file (f).
Cheers
Use TextureCubeMap class which is a sub class of Texture. The texture mapping can be used to apply images to faces of the cube.
You can do it by specifying the cube faces using xyz coordinates as positive and negative.
Refer the below link for its complete documentation.
I have an overlay in my game that consists of an image of a screen, and a set of buttons that are "on" the screen.
Screenshot:
My Screen has one Stage. The Stage has a set of Group objects, which I think of as layers. The first group has the backgrounds, the groups in the middle has the game elements, and the frontmost group has the screen overlay.
The overlay layer consists of one Image, the screen itself, and four TextButton (one in each corner).
This would work great, if it weren't for the fact that I can't click on anything in the game layer as long as the image in the overlay layer is in front of it. Even if the image is transparent, it still interecepts all touch events before they reach the game layer.
So my questions is: How can I make the image in the overlay layer ignore all touch events, so that the game layer will get them and one can actually play the game?
I tried one idea myself, but I'm not sure this is the right way to do it:
I tried creating the image as a custom Actor that always had height/width set to 0, but still (by overloading the draw() method) drew the image on the entire screen. This works very well, except for the fact that the image for some reason gets drawn behind elements in lower layers.
Screenshot: https://dl.dropboxusercontent.com/u/1545094/Screen2.png
In this screenshot, I have opened a instruction messagebox, which adds itself to one of the game layers (group 6).
Note that all the buttons in the overlay layer (which is group 7) is in front of the messagebox, but the screen frame (which is a custom Actor) somehow gets drawn behind the messagebox. Why is that?
Note: If I take this exact same case, and change my custom actor into a regular Image, everything is drawn correctly, but then I can't click anything in the lower layers anymore, as described above.
This is my custom actor, if anybody can make any sense of it:
public class ClickThroughImage extends Actor {
BaseDrawable d;
public NonexistingImage(BaseDrawable d){
this.d = d;
setSize(0, 0);
}
#Override
public void draw(SpriteBatch batch, float parentAlpha) {
d.draw(batch, 0, 0, 1024, 768); //Yes, I tried swapping these two lines.
super.draw(batch, parentAlpha); //It had no effect.
}
}
In addition to the other methods note you can also call:
setTouchable(Touchable.disabled);
Which is documented as:
No touch input events will be received by the actor or any children.
Method is n the Actor class.
Use an InputMultiplexer. The InputMultiplexer class allows you to share user input among multiple input processors. Create your own class extending InputProcessor, and put that in InputMultiplexer with your Stage. That way you can respond to user input in a custom way, and still be able to use your stage.
InputMultiplexer multiplexer = new InputMultiplexer();
Array<InputProcessor> processors = new Array<InputProcessor>();
MyInputProcessor myInputProcessor = new MyInputProcessor();
processors.add(myInputProcessor);
processors.add(stage);
this.multiplex.setProcessors(processors);
//...
//and in your show method in your Screen class
Gdx.input.setInputProcessor(this.multiplex);
Also, be sure to return null from Actor.hit. This should cause the actor to not respond to any user interaction.
This is how I solved this problem in my game.
Yes, Pool is right.
Just set touchable to disabled.
It is questionable, whether it is a "good" default of the engine to make all actors touchable in a stage, because in most of my games the majority of actors is _not_ touchable, and there are only few elements the user can/shall interact with. Therefore I always create a base class of "nonTouchableActor" where I derive all my Actors from that shall not react on clicks/taps and this base class sets touchable(disabled) in the constructor. That way you no longer have to think about it.