shaperenderer rounded corner triangle - libgdx

I would like to create a triangle shape with rounded corners. I can't use a sprite since the shape will change all the time so shaperenderer seems as a good option. I currently do:
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeType.Filled);
shapeRenderer.setColor(0.2f, 0f, 0f, 1f);
// shapeRenderer.filledTriangle(50f, 50f, 55f, 55f, 60f, 60f);
shapeRenderer.triangle(0, 0, 5f, 5f, 5f, 4f);
shapeRenderer.end();
which produce something like:
but I need something like:
Any ideas?

Either use an image that you draw from Photoshop with Sprite and SpriteBatch, or a Stencil to cut out the edges.

Related

How to crop texture based on the other object it touched?

I have a line actor that might have other object that intersect with it, And I need to crop out that part.
Above is the image actor
this rectangle is also a image actor might appear randomly along the lines.
And this is the sample of the result I wanted to get. I need advice on how to achieve this with libgdx.
[EDIT]
As suggest I am trying to use fbo to draw into a buffer. Below is the code I am currently working on.
#Override
public void draw(Batch batch, float parentAlpha) {
fbo.begin();
getStage().getViewport().apply();
Gdx.gl.glClearColor(0f,0f,0f,0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.draw(trLine,position.x,position.y);
batch.flush();
fbo.end();
getStage().getViewport().apply();
batch.draw(fbo.getColorBufferTexture(),0,0);
}
I am able to buffer the draw into the buffer and draw it later but it happen to be different size. below is the code for creation and dispose of fbo. and it is outside of the draw loop.
fbo = new FrameBuffer(Pixmap.Format.RGBA8888,getStage().getViewport().getWidth(),getStage().getViewport().getHeight(),false,true);
[SOLVED FBO]
Below is the coding that have working fbo but the blending is not working as expected. Will keep trying until it works.
fbo.begin();
Gdx.gl.glClearColor(0f,0f,0f,0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(trLine,position.x,position.y);
batch.end();
int srcFunc = batch.getBlendSrcFunc();
int dstFunc = batch.getBlendDstFunc();
batch.enableBlending();
batch.begin();
batch.setBlendFunction(GL20.GL_ONE, GL20.GL_FUNC_REVERSE_SUBTRACT);
for(int i = 0 ; i < cropRectangles.size() ; i++){ batch.draw(cropTexture.get(i),cropRectangles.get(i).x,cropRectangles.get(i).y);
}
batch.end();
fbo.end();
getStage().getViewport().apply();
//reset blending before drawing the desire result
batch.begin();
batch.setBlendFunction(srcFunc, dstFunc);
batch.draw(fbo.getColorBufferTexture(),0,0);
batch.end();
But the output is not getting any blending effect. it is still a rectangle with filled white color.
[SOLVED FULL CODE]
I finally apply the equation correctly and able to reset it so it doesn't affect other things that I draw after this.
fbo.begin();
Gdx.gl.glClearColor(0f,0f,0f,0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(trLine,position.x,position.y);
batch.end();
int srcFunc = batch.getBlendSrcFunc();
int dstFunc = batch.getBlendDstFunc();
batch.enableBlending();
batch.begin();
batch.setBlendFunction(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA);
Gdx.gl.glBlendEquation(GL20.GL_FUNC_REVERSE_SUBTRACT);
for(int i = 0 ; i < cropRectangles.size() ; i++){
batch.draw(cropTexture.get(i),cropRectangles.get(i).x,cropRectangles.get(i).y);
}
batch.end();
batch.flush();
fbo.end();
Gdx.gl.glBlendEquation(GL20.GL_FUNC_ADD);
getStage().getViewport().apply();
batch.begin();
batch.setBlendFunction(srcFunc, dstFunc);
batch.draw(fbo.getColorBufferTexture(),0,0);
batch.end();
You can use blend mode to achieve this.Your rectangle should have 2 parts.
Outer part and transparent part.
Outer part is your actual part going to be draw as usual.
Transparent part will be another rectangle with a full alpha and you should use blending for this part.
Visual Blending Tool
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
This mode clearing intersection area, it seems like correct mode .
You can easly find example usages of blending in libgdx.
SpriteBatch sb = (SpriteBatch)batch;
// draw our destination image
sb.draw(dst, 0, 0);
sb.end();
// remember SpriteBatch's current functions
int srcFunc = sb.getBlendSrcFunc();
int dstFunc = sb.getBlendDstFunc();
// Let's enable blending
sb.enableBlending();
sb.begin();
// blend them
sb.setBlendFunction(GL20.GL_ONE, GL20.ONE_MINUS_SRC_ALPHA);
sb.draw(src, 0, 0);
// Reset
sb.end();
sb.begin();
sb.setBlendFunction(srcFunc, dstFunc);
Additionally you must change blend equation as well.
And its not unique for sprite batch so we need to change for all game.
//Equation for effect you want
Gdx.gl.glBlendEquation(GL20.GL_FUNC_REVERSE_SUBTRACT);
//After draw you should also reset this
Gdx.gl.glBlendEquation(GL20.GL_FUNC_ADD);
Now we should take this drawn to FrameBufferObject because transparent area will show background color of your spritebatch.
If it's okey for you then it's done but you want to see another texture at this transparent area like background image or something then we have one more step.
You should read this article for whats the purpose of FBO(FrameBufferObject)
Frame Buffer from official wiki
You need to use this for merge your sprites and transparent areas so you can use those as whole image and see through background images from transparent area.
Maybe using second viewport or sprite batch would be easier and much more efficient according to your game.
One solution for this situation, fill that rectangle with solid background color(i mean make one rectangle inside that rectangle ring). It will cropped out that part.

Flipping a shaperenderer object in libGDX

I am flipping one of the object in my libGDX project. At the same time I want to flip its shape rendering circle also. How can I do it?
here is my code for shaperenderer:
shapeRenderer.setProjectionMatrix(camera.projection);
shapeRenderer.setTransformMatrix(camera.view);
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
if (obsObj.isSpider())
circle(shapeRenderer, ob.getCollisionCircle());
shapeRenderer.end();
and circle method is:
private void circle(ShapeRenderer renderer, Circle circle) {
shapeRenderer.circle(circle.x, circle.y, circle.radius, 100);
}
I am flipping sprite object like this..
obsSprite.setFlip(true,false);
Instead of using circle/Rectangle shape rendering,I tried shape rendering with polygons.
It worked well for rotation and flipping.
You can use transform matrix like this :
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.setTransformMatrix(...your transformation matrix...);
camera.combined contains both camera projection and view.
your transformation matrix might be scaling matrix in your case (scaleX = -1 for horizontal flipping and/or scaleY = -1 for vertical flipping)

Libgdx blending contrast issue in render();

In a Libgdx 1.x Stage, my goal is to apply a dark semi transparent mask on my screen except an area that should display the original screen.
My global render method:
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setShader(null);
update();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
batch.begin();
darkener.draw(batch, 0.7f);
spotlight.draw(batch, 1f);
batch.end();
}
Both instances of objects Darkener and Spotlight are Sprites made from a pure white 4x4 texture:
spotlight = new Sprite(new Texture(Gdx.files.internal("data/ui/whitepixel.png")));
darkener = new Sprite(new Texture(Gdx.files.internal("data/ui/whitepixel.png")));
I give my Darkener object the size of the screen, and my Spotlight object the size of the area I want not to be darkened.
Here is the draw method of my object darkener:
public void draw(Batch batch, float alpha) {
darkener.draw(batch, alpha);
}
And the draw method of my Spotlight object:
public void draw(Batch batch, float alpha) {
batch.setBlendFunction(GL20.GL_DST_COLOR, GL20.GL_SRC_ALPHA);
spotlight.draw(batch, alpha);
batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
}
My problem is about blending:
With the parameters:
darkener.draw(batch, 0.7f);
spotlight.draw(batch, 1f);
The preserved (spotlight) area is darker than the original.
With the parameters:
darkener.draw(batch, 0.3f);
spotlight.draw(batch, 1f);
The preserved (spotlight) area is brighter (saturated) than the original.
With the paremeters:
darkener.draw(batch, 0.5f);
spotlight.draw(batch, 1f);
The preserved (spotlight) area is exactly like the original (so, as I want it). The problem is that I want to be able to set different values for my Darkener either < 0.5f or > 0.5f.
What I am doing wrong?
The blend function you're using for the spotlight takes the current pixel brightness and multiplies it by (1+alpha).
So if you darken to 0.7 of brightness (using a darkener alpha of 0.3), you want the spotlight to multiply the brightness by 1/0.7 = 1.429 so you should use a spotlight alpha of 0.429. So:
spotlightAlpha = 1/(1-darkenerAlpha) - 1; //assuming darkener RGB is black
The problem is if you darken to less than 0.5 brightness (darkner alpha > 0.5), because alpha cannot be greater than 1. You would have to run the spotlight with alpha 1 repeatedly until the brightness is above 0.5 and then one more time with the appropriate value.
You will lose color precision the darker you go so this method may not be suitable. Might want to consider drawing 8 dark boxes instead. And if you want the spotlight to be non-rectangular you can make its sprite inverted to fill in the middle rectangle.

LibGDX FrameBuffer

I'm trying to make a game where you build a spaceship from parts, and fly it around and such.
I would like to create the ship from a series of components (from a TextureAtlas for instance). I'd like to draw the ship from it's component textures, and then save the drawn ship as one large Texture. (So i don't have to draw 50 component textures, just one ship texture. What would be the best way to go about this?
I've been trying to do so using a FrameBuffer. I've been able to draw the components to a Texture, and draw the texture to the screen, but no matter what I try the Texture ends up with a solid background the size of the frame buffer. It's like the clear command can't clear with transparency. Here's the drawing code I have at the moment. The ship is just a Sprite which i save the FrameBuffer texture to.
public void render(){
if (ship == null){
int screenwidth = Gdx.graphics.getWidth();
int screenheight = Gdx.graphics.getHeight();
SpriteBatch fb = new SpriteBatch();
FrameBuffer fbo = new FrameBuffer(Format.RGB888, screenwidth, screenheight, false);
fbo.begin();
fb.enableBlending();
Gdx.gl.glBlendFuncSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA);
Gdx.gl.glClearColor(1, 0, 1, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
fb.begin();
atlas.createSprite("0").draw(fb);
fb.end();
fbo.end();
ship = new Sprite(fbo.getColorBufferTexture());
ship.setPosition(0, -screenheight);
}
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.enableBlending();
batch.setBlendFunction(GL20.GL_ONE, GL20.GL_ZERO);
ship.draw(batch);
batch.end();
}
The problem here lies in this line:
FrameBuffer fbo = new FrameBuffer(Format.RGB888, screenwidth, screenheight, false);
specifically with Format.RGB888. This line is saying that your FrameBuffer should be Red (8 bits) followed by Green (8 bits) followed by Blue (8 bits). Notice however, that this format doesn't have any bits for Alpha (transparency). In order to get transparency out of your frame buffer, you probably instead want to use the Format.RGBA8888, which includes an additional 8 bits for Alpha.
Hope this helps.

Textures overlapping

I am new in LibGDX and I would like to know how to make one texture appear in front of the other, because lets say we have 2 textures(t1 and t2) with shape of a square. And when they overlap, I see the color of t1 but I would like to see the color of t2? Is there any way that I can make some kind of priorities or?
Just draw your texture in render() function in needed order. Last drawn texture will be on the first visible layer. Example: (if the texture have the same size, you will see only second one):
#Override
public void render(float delta) {
spriteBatch.begin();
Gdx.gl.glClearColor(0.5f, 0.5f, 0.5f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
spriteBatch.draw(YOUR_TEXTURE_1, 0, 0);
spriteBatch.draw(YOUR_TEXTURE_2, 0, 0);
spriteBatch.end();
}