Libgdx slider - drawables are drawn the wrong size - java

I am drawing a slider with Libgdx using the following code:
Pixmap pix = new Pixmap(200, 50, Pixmap.Format.RGBA8888);
pix.setColor(Color.BLACK);
pix.fill();
skin.add("sliderBackS", new Texture(pix));
Pixmap pix1 = new Pixmap(10, 70, Pixmap.Format.RGBA8888);
pix1.setColor(Color.RED);
pix1.fill();
skin.add("knobS", new Texture(pix1));
Slider.SliderStyle sliderStyle = new Slider.SliderStyle();
sliderStyle.disabledBackground = skin.newDrawable("sliderBackS");
sliderStyle.disabledKnob = skin.newDrawable("knobS");
sliderStyle.background = skin.newDrawable("sliderBackS");
sliderStyle.knob = skin.newDrawable("knobS");
skin.add("sunSlider", sliderStyle);
sunlightSlider = new Slider(0, 100, 1, false, sliderStyle);
stage.addActor(sunlightSlider);
sunlightSlider.setBounds(300, 300, 100, 10);
sunlightSlider.setDisabled(true);
sunlightSlider.setDebug(true);
And then else where:
stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));
stage.draw();
But for some reason the pixmaps in the slider seem to be drawn at their actual size. This can be seen in the following picture (the green line is what it should be, from the debug):
For some reason the width seems to be constrained by sunlightSlider.setBounds(300, 300, 100, 10); but the height does not.
I know that I could choose the pixmap size to what ever I need, but I want to use an image from file. If I use a big image, then it overflows the bounds similarly.
I want it to look like it is above, but constrained to the green rectangle.
What am I doing wrong?

A TextureRegionDrawable, which is what you've created with your newDrawable calls, by default has a minimum size that matches its original pixel dimensions. The minimum size of the Drawable prevents the Slider widget from drawing it as small as it would like to fit it into its own bounds. So you can reduce the minimum size:
sliderStyle.disabledBackground = skin.newDrawable("sliderBackS");
sliderStyle.disabledBackground.setMinWidth(0);
sliderStyle.disabledBackground.setMinHeight(0);
// and so on for other new drawables.
I'm not sure what your long term plans are, but typically you want all your skin's images to be part of a single Texture object so the SpriteBatch doesn't have to flush itself many times to draw your whole scene.
If for some reason you're not doing that, you can at least make all these solid color drawables use the same texture. It can simply be a one-pixel white texture that is shared by everything. Also, make sure you are disposing of the pixmap you use to create a texture, or you are leaking memory!
Pixmap pix = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
pix.setColor(Color.WHITE);
pix.fill();
Texture tex = new Texture(pix);
pix.dispose();
skin.add(tex, "white");
Drawable blackDrawable = skin.newDrawable("white", Color.BLACK);
Drawable redDrawable = skin.newDrawable("white", Color.RED);
Slider.SliderStyle sliderStyle = new Slider.SliderStyle();
sliderStyle.disabledBackground = blackDrawable;
sliderStyle.disabledKnob = redDrawable;
sliderStyle.background = blackDrawable;
sliderStyle.knob = redDrawable;
Since you passed your Texture object to the Skin, the Skin will dispose of it when the Skin is disposed. Don't forget to dispose of the Skin in the dipose() method.

Related

I want to display text using Android and OpenGL

I want to display a text within a OpenGL Android Application. I have tried the code below, but, nothing is displayed. Some other attempts have been tried but none was displayed either. Could anyone help me with some advice?
String aText = "Prueba";
float aFontSize = 100;
int[] textureId = new int[1];
Paint textPaint = new Paint();
textPaint.setTextSize(aFontSize);
textPaint.setFakeBoldText(false);
textPaint.setAntiAlias(true);
textPaint.setARGB(255, 255, 255, 255);
// If a hinting is available on the platform you are developing, you should enable it (uncomment the line below).
//textPaint.setHinting(Paint.HINTING_ON);
textPaint.setSubpixelText(true);
textPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));
float realTextWidth = textPaint.measureText(aText);
// Creates a new mutable bitmap, with 128px of width and height
int bitmapWidth = (int)(realTextWidth + 2.0f);
int bitmapHeight = (int)aFontSize + 2;
Bitmap textBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
textBitmap.eraseColor(Color.argb(0, 255, 255, 255));
// Creates a new canvas that will draw into a bitmap instead of rendering into the screen
Canvas bitmapCanvas = new Canvas(textBitmap);
// Set start drawing position to [1, base_line_position]
// The base_line_position may vary from one font to another but it usually is equal to 75% of font size (height).
bitmapCanvas.drawText(aText, 1, 1.0f + aFontSize * 0.75f, textPaint);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId[0]);
// Assigns the OpenGL texture with the Bitmap
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, textBitmap, 0);
// Free memory resources associated with this texture
textBitmap.recycle();
// After the image has been subloaded to texture, regenerate mipmaps
GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);

libGDX Draw viewport only partly while cutting off the rest

This problem seemed very obvious for me to solve, but whatever I try, it doesn't work. What I'm trying to do is to incorporate a mini-version of my PlayScreen in a ScrollPane as a tutorial where you can read text and try it out immediately.
Because I didn't find any better solution to add this to the Table inside the ScrollPane, I edited the draw() method of the PlayScreen to take the ScrollPane.getScrollPercentY() and offset the camera of the PlayScreen accordingly.
What I want to do now is to only render only part of the viewport that would be normally visible in the real game. Subsequently, I want to be able to control the size and position of this "window".
I also want to be able to resize and move the content, while cutting off the edges that are not visible to the camera. This is what I tried inside the PlayScreenDraw:
public void draw(final float yOffset,
final int xTiles,
final int yTiles) {
view.getCamera().position.y = yTiles / 2f - yOffset * yTiles / HEIGHT; // HEIGHT = 800
view.getCamera().position.x = xTiles / 2f;
view.setWorldSize(xTiles, yTiles); //Do i even need to change the world size?
b.setProjectionMatrix(view.getCamera().combined);
b.begin();
...
b.end();
view.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}
What this gives me, in terms of the picture above, is this
How do I need to change the viewport and/or the camera? Btw., this is how i set the two up:
cam = new OrthographicCamera();
cam.setToOrtho(false, WIDTH, HEIGHT); // WIDTH = 8, HEIGHT = 16
batch.setProjectionMatrix(cam.combined);
view = new FitViewport(WIDTH, HEIGHT, cam);
The Pixmap class can help you achieve what you want since you stated that you wanted to "cut off" the parts outside of the green selection box.
You need to render what the camera sees to an FBO and then get the pixmap from the FBO itself.
Framebuffer Objects are OpenGL Objects, which allow for the creation of user-defined Framebuffers. With them, one can render to non-Default Framebuffer locations, and thus render without disturbing the main screen.
-- OpenGL wiki
// Construct an FBO and keep a reference to it. Remember to dispose of it.
FrameBuffer fbo = new FrameBuffer(Format.RGBA8888, width, height, false);
public void render() {
//Start rendering to the fbo.
fbo.begin();
//From the camera's perspective.
batch.setProjectionMatrix(camera.combined);
batch.begin();
//Draw whatever you want to draw with the camera.
batch.end();
// Finished drawing, get pixmap.
Pixmap pixmap = ScreenUtils.getFrameBufferPixmap(0, 0, width, height);
//Stop drawing to your fbo.
fbo.end();
}
After getting the pixmap you can iterate through the pixels and set the alpha of the pixels outside your green selection window to 0 making them invisible or "cutting them off"

How to extend the background in LibGdx for top down game?

What is the proper way to extend the background in top down game? I used LibGdx framework. Any idea or tutorial for top down game.My background is in PNG format and screen of 720x1280 portrait.I had a problem in extending the background.I want the camera follow the character and the background will extend. How could I do that? Here is the Screen shot of
https://i.stack.imgur.com/jl03R.png
Here is my code
To display background I used this
//background
Background = new Texture(Gdx.files.internal("floor.png")); //File from assets folder
Background.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);
bgsprite = new Sprite(Background);
In render
spriteBatch.draw(Background,0,100,0, srcy, Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
srcy +=3;
The background is scrolling but the camera don't follow the player(cat)
Source code for GameScreen
http://pastebin.com/Dxfx9f65
Thank's and Advance any help or suggestion are much appreciated. :)
Use two identical texture background. Each the size of the screen It can be the same file. It is important that are docked vertically. Move of at the same time. Alternately changing with each other.
Sample code:
declaration:
Texture background1, background2;
SpriteBatch batch;
float yMax, yCoordBg1, yCoordBg2;
final int BACKGROUND_MOVE_SPEED = 100; // pixels per second. Put your value here.
creation:
Background1 = new Texture(Gdx.files.internal("floor.png"));
Background2 = new Texture(Gdx.files.internal("floor.png")); // identical
yMax = 1280;
yCoordBg1 = yMax*(-1); yCoordBg2 = 0;
in method render:
yCoordBg1 += BACKGROUND_MOVE_SPEED * Gdx.graphics.getDeltaTime();
yCoordBg2 = yCoordbg1 + yMax; // We move the background, not the camera
if (yCoordBg1 >= 0) {
yCoordBg1 = yMax*(-1); yCoordBg2 = 0;
}
batch.begin();
batch.draw(background1, 0, yCoordBg1);
batch.draw(background2, 0, yCoordBg2);
batch.end();
The background can be made in the format jpg - will spend less memory.

How to set size, position, and color, of one RadialGradient, or set XferMode on GradientDrawable

This is my first question here on Stackoverflow, so go easy on me. I'm trying to draw a radial bloom effect around a point, and found RadialGradient, as well as GradientDrawable. However neither fully gives a solution.
Here is how I'm doing the drawing right now:
//global
PorterDuffXfermode xferMode = new PorterDuffXfermode(PorterDuff.Mode.ADD);
Paint mainP = new Paint();
Paint whiteP = new Paint();
whiteP.setColor(Color.WHITE);
RadialGradient gradient;
// in a drawing method with a canvas
gradient = new RadialGradient((int) x, (int) y, tempRadius, mainP.getColor(),
0x00000000, Shader.TileMode.CL
mainP.setShader(gradient);
mainP.setXfermode(xferMode);
canvas.drawCircle((int) x, (int) y, tempRadius, mainP);
gradient = new RadialGradient((int) x, (int) y, tempRadius/2, whiteP.getColor(),
0x00000000, Shader.TileMode.CLAMP);
whiteP.setXfermode(xferMode);
whiteP.setShader(gradient);
canvas.drawCircle((int) x, (int) y, tempRadius/2, whiteP);
This will give the expected result:
Screenshot
However the new RadialGradient builds up in memory every frame per dot. Which becomes a problem later obviously. The only public thing in that class is a constructor, so all you can do with RadialGradient is create a new one every time you need a new size, position or color. The reason I want to do it this way is because you assign the gradient to the Paint object your going to draw it with, which allows you to use it's setXferMode().
The other way, using the GradientDrawable, does allow you to just create one instance of itself, so you can change the size, position, and color, but the Paint object it uses to paint itself is private, so you can't set the XferMode on it. Which is necessary so that if you have more than one dot, they don't just paint over one another. It has a colorfilter, but it doesn't look like colorfilter worries about the destination, only a specified color and the source.
Since I am new, i can only post two links, and instead of posting just two pictures, I'll link back to the same question I wrote on reddit which has all the pictures for context. (and no answers yet, which is why I came here, ha ha)
https://www.reddit.com/r/learnandroid/comments/590uce/having_a_shader_issue_using_radialgradient_and/
So, how should this be done, I know I need one class or the other. From what I can tell, RadialGradient would be perfect if I didn't have to create a new one every time I needed a different size, position, or color. GradientDrawable would be equally great since you can just have one instance, but I need to be able to set the XferMode on the paint it uses. Is there another class, or am I missing something between the two of these?
Thanks!!
So, while I did find a solution, it still lead to more issues. The solution I found was partly here. The only thing it was missing was being able to change the color of the preallocated RadialGradient bitmap. So I came up with this:
// Global
int tempRadius;
Paint p = new Paint();
RadialGradient gradient;
Bitmap circleBitmap = Bitmap.createBitmap((int) (tempRadius * 2.0f), (int) (tempRadius * 2.0f),
Bitmap.Config.ARGB_8888);
Canvas tempCanvas = new Canvas(circleBitmap);
Rect gradBMPRect = new Rect(0,0,200,200);
Rect destRect = new Rect();
int[] hsv = {0,1,1};
PorterDuffColorFilter[] myColors = new PorterDuffColorFilter[360];
PorterDuffXfermode xferMode = new PorterDuffXfermode(PorterDuff.Mode.ADD);
// Initialize
gradient = new RadialGradient(tempRadius, tempRadius, tempRadius, Color.WHITE, 0x00000000, Shader.TileMode.CLAMP);
circleBitmap = Bitmap.createBitmap((int) (100 * 2.0f), (int) (100 * 2.0f),
Bitmap.Config.ARGB_8888);
tempCanvas = new Canvas(circleBitmap);
for(int i = 0; i < 360; i++){
hsv[0] = i;
myColors[i] = new PorterDuffColorFilter(Color.HSVtoColor(hsv), PorterDuff.Mode.MULTIPLY)
}
// update/draw
p.setDither(true);
p.setShader(gradient);
tempCanvas.drawCircle(100, 100, 100, p);
p.setXfermode(xferMode);
if(p.getColor() != mainP.getColor()) {
p.setColorFilter(myColors[hue]);
p.setColor(mainP.getColor());
destRect.set((int)x-tempRadius,(int)y-tempRadius,(int)x+tempRadius,(int)y+tempRadius);
canvas.drawBitmap(circleBitmap,gradBMPRect,destRect,p);
p.setColorFilter(null);
destRect.set((int)x-(tempRadius/2),(int)y-(tempRadius/2),(int)x+(tempRadius/2),(int)y+(tempRadius/2));
canvas.drawBitmap(circleBitmap,gradBMPRect,destRect,p);
With this the RadialGradient is used to create a greyscaled bitmap, then a pallette of 360 PorterDuffColorFilters is made using HSVtoColor. All 360 have their modes set to multiply. When drawing these the paint used to draw the bitmap is set use the ColorFilter specified by its hue. The colorfilter shades the greyscaled bitmap to whatever color the filter is. And no more memory leaks :)
This took longer to render the bitmap of a RadialGradient vs rendering a circle with a RadialGradient though. With 30 circles it took my Galaxy S5 15-20ms per frame draw, while the bitmaps took around 30-35ms. It could probably get worked out though with a little more work and adjustment.

drawBitmap() draws the false part

I'm trying to show part of an image in an ImageView. I tried it with canvas.drawBitmap() but it seems like the false part of the image is displayed. My code:
MainActivity:
this.drawCharacter = new DrawCharacter(1);
this.bm = Bitmap.createBitmap(16, 32, Bitmap.Config.ARGB_8888);
this.c = new Canvas(this.bm);
this.c = this.drawCharacter.drawCharacter(this.c, this.characterBitmap);
this.bm = Bitmap.createScaledBitmap(this.bm, this.imgWidth, this.imgHeight, isChild());
this.imgv.setImageBitmap(this.bm);
DrawCharacter:
[...]
Paint localPaint = new Paint();
paramCanvas.drawBitmap(paramBitmap, new Rect(8, 8, 16, 16), new Rect(4, 0, 12, 8), localPaint);
return paramCanvas;
[...]
And at the end some strange part of the image is shown.
In your drawBitmap() call, you set the first Rect parameter to 8,8,16,16, this is the source rectangle from your bitmap to be drawn, set it to null to draw the entire bitmap.
see the documentation
if you want to apply this bounds according to the initial bitmap scale, you may need to apply the same scale on your src Rectangle.
(try to remove the scale part, createScaledBitmap() to see if your src rectangle is good without the scale ;) )

Categories

Resources