I am trying to draw a frame with two textures within Libgdx. My texture is just a white square that i scale and draw with SpriteBatch to the screen. The color is set with batch.setColor(). Now I want to draw a black rectangle and a smaller opaque rectangle in the middle, so it looks like a frame.
batch.begin();
batch.setColor(new Color(0,0,0,1)); //Black
batch.draw(rectangle, 0,0,100,100);
batch.setColor(new Color(0,0,0,0)); //Transparent
batch.draw(rectangle, 25,25,50,50);
batch.end();
I am using this blend function:
Gdx.gl.glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR);
the problem now is when i draw this it just shows the black rectangle cause the transparent rectangle is drawn on top of it. I want to draw it that I can see through the second rectangle the stuff I drawed before so it acts like a frame.
My question is: How can i accomplish this?
Example Background
How it should look
How it looks
First of all, you should not create new instances of Color in your render() method, since it's called every frame it will lead to a memory leak. Create colors in create() for example. And for black color you could use Color.BLACK instead of creating your own instance.
Back to your question.
You can simply just use TextureRegion class. Here is a sample code:
public class MyGdxGame extends ApplicationAdapter {
SpriteBatch batch;
Texture whiteRectangle;
TextureRegion backgroundRegion;
#Override
public void create() {
//initializing batch, whiteTexture, etc...
//background, the one with a turtle from you example
Texture backgroundTexture = ...;
backgroundRegion = new TextureRegion(backgroundTexture);
//to set a region (part of the texture you want to draw),
//you can use normalized coordinates (from 0 to 1), or absolute values in pixels
backgroundRegion.setRegion(0.25f, 0.25f, 0.75f, 0.75f);
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
//black background
batch.setColor(Color.BLACK);
batch.draw(whiteRectangle, 0, 0, 100, 100);
//on top of that background draw the backgroundRegion
batch.setColor(Color.WHITE);
batch.draw(backgroundRegion, 25,25,50,50);
batch.end();
}
}
Related
I wrote the following code:
int color = Color.argb8888(255, rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
stage.getBatch().setColor(color);
With this code I want to change the color of a sprite randomly. Unfortunately, the color of all sprites on the stage get changed but I want to declare which sprite I want to tint. How can I improve my code?
To change tint of a single sprite, use below code
Sprite mysprite;
Texture mytexture;
mytexture = new Texture("texture.png");
mysprite = new Sprite(mytexture);
mysprite.setColor(Color.WHITE.cpy().lerp(Color.BLACK, .5f));
this code changes white tint of sprite to black tint
Color color = new Color(rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), 1f);
'rand.nextFloat()' is gives you a float between 0 and 1, so you can create random color like this.
I prefer to use in this way :
final Image image=new Image(new Texture("badlogic.jpg"));
final Color colors[]=new Color[]{Color.YELLOW,Color.RED,Color.CYAN};
image.addAction(Actions.forever(Actions.sequence(Actions.delay(.2f),Actions.run(new Runnable() {
#Override
public void run() {
image.setColor(colors[MathUtils.random(colors.length-1)]);
}
}))));
stage.addActor(image);
In my experience, you could just set your color attribute that used as vertex attributes in shader back to normal color masking like this:
stage.getBatch().setColor(your_random_color);
stage.getBatch().draw(your_texture);
stage.getBatch().setColor(1.0f,1.0f,1.0f,1.0f);
Please be noticed that I tried this way for drawing TextureRegion, but I think this would not be different with drawing Sprite.
I have my own Libgdx class that does not implement the Screen
Interface. I control my camera movement. It's an orthographic camera whose viewport width is WorldWidth and viewport height is WorldHeight. I am trying to add a button via the Stage class. I am able to add it and I see that its drawn, but since I don't implement the screen interface I call stage.draw() on my render() method, not on the render(float delta) method that seems to be required by the Screen interface. For comparison purposes, I draw a sprite whose size is (0.25fcamera.viewportWidth,0.25fcamera.viewportHeight). However, this sprite is not drawing when I call stage.draw(). The button draws but it seems very small even though I set its size to (0.25fcamera.viewportWidth,0.25fcamera.viewportHeight). Here's the code on
how I add my button class:
stage1= new Stage();
btn = new Button(new SpriteDrawable(new Sprite(new Texture("texone.png"))),
new SpriteDrawable(new Sprite(new Texture("textwo.png"))));
btn.addListener(new ClickListener(){
public void clicked(InputEvent event, float x, float y){ }
});
btn.setBounds(0f,0f,0.25f*camera.viewportWidth,0.25f*camera.viewportHeight);
btn.setPosition(0f,100f);
stage1.add(btn);
Gdx.input.setInputProcessor(stage1);
//a few lines down to my render() method
#Override
public void render(){
//.... more regular code that goes in method
batch.begin();
//more lines of code that draw my sprites
stage1.draw();
batch.end();
}
What I want to know is why is the button so small and why isn't my other sprite drawing? Perhaps there is a way to add my orthographic camera to my stage1 object. And, if I add my orthographic camera to my stage1 object, how should I update my stage1 viewport on the resize method? Please advise.
thank you
I don't see that you set a projection matrix for batch. Do you call this function?
batch.setProjectionMatrix(camera.combined);
you should do it in render function
I created a transparent black layer using this code:
Pixmap pixmap = new Pixmap((int) stage.getWidth(), (int) stage.getHeight(), Pixmap.Format.LuminanceAlpha);
Pixmap.setBlending(Pixmap.Blending.None); // disable Blending
pixmap.setColor(0, 0, 0, 1f);
pixmap.fill();
pixmap.fillCircle(200, 200, 100);
pixmapTexture = new Texture(pixmap, Pixmap.Format.LuminanceAlpha, false);
#Override
public void render(float delta) {
super.render(delta);
stage.getBatch().begin();
stage.getBatch().draw(pixmapTexture, 0, 0);
stage.getBatch().end();
}
The problem that I can click through it.
For example if I have a button behind it I can click it.
I want to be able to click only specific actors that I will make for them a transparent circle in the black screen (texture) that I created.
Why I'm able to click through the texture? I want to be able to click only through a transparent circle that I will make.
P.S I'm trying to do something like this
In my game I am drawing a scene2d Stage using a custom world coordinate system.
I then want to draw a debug UI with some text like FPS on top of that, but simply using screen coordinates, i.e. where the text is positioned in the upper right corner of the screen. My main render method looks something like this:
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
gameStage.act(delta);
gameStage.draw();
debugInfo.render(delta);
}
The Stage sets a custom viewport:
public GameStage(GameDimensions dimensions, OrthographicCamera camera) {
// mapWith will be smaller than screen width
super(new FitViewport(dimensions.mapWidth, dimensions.mapHeight, camera));
...
}
The DebugInfo render code looks like this:
public DebugInfo() {
Matrix4 mat = new Matrix4();
mat.setToOrtho2D(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.setProjectionMatrix(mat);
}
#Override
public void render(float delta) {
batch.begin();
font.setScale(2f);
drawText("FPS " + Gdx.graphics.getFramesPerSecond());
batch.end();
}
private void drawText(String text) {
final BitmapFont.TextBounds textBounds = font.getBounds(text);
textPos.x = Gdx.graphics.getWidth() - textBounds.width - MARGIN;
textPos.y = Gdx.graphics.getHeight() - MARGIN;
textPos.z = 0;
font.draw(batch, text, textPos.x, textPos.y);
}
The problem is that even though I make no reference whatsoever to the stage's world system or its camera, but strictly use pixel values and an according projection matrix, the text appears in the upper right corner of the stage's viewport, which is smaller than the screen. I want it to appear detached from the stage in the screen's corner instead.
I could pinpoint the problem down to the creation of the Stage instance itself; stopping to draw it is not enough. I actually have to remove the call to super(new FitViewport(...)) to prevent this from happening.
This leads me to believe that I need to somehow reset the viewport of the rendering pipeline before I render the UI overlay? How would I do that?
My first answer was wrong. Now, when I've looked into Viewport source code I can see that it uses OpenGL's glViewPort and indeed it affects all subsequent draw calls. So you have to call glViewport with appropriate dimensions before rendering your stuff:
#Override
public void render(float delta) {
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.begin();
font.setScale(2f);
drawText("FPS " + Gdx.graphics.getFramesPerSecond());
batch.end();
}
I've made a game that uses ShapeRenderer for making colorized lines. This worked fine, but when I start to import images the colored lines suddenly became black. Worst of all: When I'm using a background the lines doesn't show at all, and yes, i'm drawing it in the right order....
Code for importing and rendering the images:
Constructor(){
TextureAtlas atlas = new TextureAtlas(Gdx.files.internal("data/texture.atlas"));
AtlasRegion region = atlas.findRegion("path");
Sprite sprite = new Sprite(region);
}
..........................................
#Override
public void render() {
Gdx.gl.glClearColor(255, 255, 255, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.begin();
background.draw(batch); // drawing the background
drawing.draw(); // drawing the lines
drawObjects(); // drawing some pictures
batch.end();
}
But when I remove the code for rnedering the background and the pictures the lines will show up and in the right color....
Please help!!
EDIT: Drawing with the ShapeRenderer looks something like this (Don't have to put everything in):
public void draw() {
shaperenderer.begin(ShapeType.Line);
shaperenderer.setColor(Color.RED);
shaperenderer.line(1, 1, 100, 100);
shaperenderer.end();
}
You cannot nest objects that depend on OpenGL context. Specifically, you are nesting a ShapeRenderer.begin() within a SpriteBatch.begin(). If you change render to look like this:
batch.begin();
background.draw(batch); // drawing the background
batch.end(); // end spritebatch context to let ShapeRenderer in
drawing.draw(); // drawing the lines (with ShapeRenderer)
batch.begin();
drawObjects(); // drawing some pictures
batch.end();