I have an Image with a fadeOut/fadeIn action. Something like this:
public void fadeInAndOut() {
AlphaAction actionFadeOut = new AlphaAction();
actionFadeOut.setAlpha(0f);
actionFadeOut.setDuration(2f);
AlphaAction actionFadeIn = new AlphaAction();
actionFadeIn.setAlpha(1f);
actionFadeIn.setDuration(2f);
this.addAction(Actions.sequence(actionFadeOut, Actions.delay(2f), actionFadeIn));
}
But nothing happens when calling this method.
My draw method is:
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
batch.draw(objectImage, getX(), getY(), getWidth() * getScaleX(),
getHeight() * getScaleY());
}
How can I make the alpha values of the image work?
Thanks in advance!
As the scene2d wiki says, we need to override draw like this:
#Override
public void draw(Batch batch, float parentAlpha) {
Color color = getColor();
batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
batch.draw(objectImage, getX(), getY(), getWidth() * getScaleX(),
getHeight() * getScaleY());
batch.setColor(color.r, color.g, color.b, 1f);
}
And voilĂ ...
----- UPDATE -----
I had to add after drawing next line:
batch.setColor(color.r, color.g, color.b, 1f);
otherwise in some cases the stage color was also affected and not only the actor.
Hope it helps
In order to make the alpha values of your image to work, you need to change the colour of your spriteBatch like so:
Color color = batch.getColor();
batch.setColor(color.r, color.g, color.b, parentAlpha); //Sets the alpha of the batch without changing the color
batch.draw(...);
Related
I am trying to animate an actor which contain a simple message written with bitmapfont using fadeIn action but it doesn't work.
Here is my code.
public class Message extends Actor{
BitmapFont font;
String message;
float x, y;
public Message(BitmapFont font, String message, float x, float y) {
this.font = font;
this.message = message;
this.x = x;
this.y = y;
}
#Override
public void draw(Batch batch, float parentAlpha) {
Color color = getColor();
batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
font.setColor(color.r, color.g, color.b, color.a * parentAlpha);
font.draw(batch, message, x, y);
}
}
Then when clicking a button the message should appear but it is only appear without animation.
button.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
BitmapFont font = new BitmapFont(Gdx.files.internal("myfont.font"));
Message message = new Message(font, "Tap Here", 100, 20);
stage.addActor(message);
message.addAction(Actions.fadeIn(5));
}});
Other actors animations on the same stage work fine as I'm calling:
stage.act(delta);
stage.draw();
You should set message actor's alpha to zero before adding the fadeIn action:
button.addListener(new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
BitmapFont font = new
BitmapFont(Gdx.files.internal("myfont.font"));
Message message = new Message(font, "Tap Here", 100, 20);
message.getColor().a = 0f; // add this line
stage.addActor(message);
message.addAction(Actions.fadeIn(5));
}});
I want to make a text appear in the center of the screen, indicating
the current level. It should appear gradually and after a while disappear gradually. I'm using scene2d with stages, actors.. so i would use Actions.
This is what i have now:
public class TextActor extends Actor {
private BitmapFont font;
private CharSequence charSequence;
public TextActor(CharSequence charSequence) {
font = new BitmapFont(Gdx.files.internal("fonts/white_standard_font.fnt"));
this.charSequence = charSequence;
}
#Override
public void act(float delta) {
super.act(delta);
}
#Override
public void draw(Batch batch, float delta) {
super.draw(batch, delta);
font.draw(batch, charSequence, getX(), getY());
}
}
In the class that creates the TextActor..
textActor.addAction(Actions.sequence(Actions.fadeIn(1f), Actions.delay(1f), Actions.fadeOut(1f), new Action() {
#Override
public boolean act(float delta) {
textActor.remove();
transitionInProgress = false;
gameState = GameState.RUNNING;
Gdx.input.setInputProcessor(stage);
return true;
}
}));
gameTable.addActor(textActor);
fadeIn, fadeOut, alpha.. don't work. I tried with "moveBy" and it works, so it seems a problem concerning the appearance of the Actor. There is something that escapes me.
The fade actions modify the alpha value of the Actor's color (getColor().a). You're drawing the font directly without applying the color associated with the actor.
Take a look at how Label.draw is implemented for a better understanding. In the meantime, just try adding this above your font.draw(...) call:
font.setColor(getColor())
Or, if you don't want to modify the entire color, just the alpha, try this:
font.getColor().a = getColor().a;
UPDATE:
Also note that you should apply the parentAlpha (second parameter of draw - labelled as delta in your example) to the final alpha:
font.getColor().a = getColor().a * parentAlpha
This allows your actor to fade if you change the alpha of the stage or any parents.
I try to implement a custom Actor which displays contents of a FrameBuffer by extending Image. Inside I'd like to draw using a ShapeRenderer.
public class CustomActor extends Image {
private FrameBuffer frameBuffer = null;
private ShapeRenderer shapeRenderer = new ShapeRenderer();
private int width;
private int height;
public CustomActor() {
width = Gdx.graphics.getWidth();
height = Gdx.graphics.getHeight();
shapeRenderer.setAutoShapeType(true);
}
#Override
public void draw(Batch batch, float parentAlpha) {
if (frameBuffer == null) {
frameBuffer = new FrameBuffer(Pixmap.Format.RGB565, width / 2, height / 2, false);
TextureRegion textureRegion = new TextureRegion(frameBuffer.getColorBufferTexture());
textureRegion.flip(false, true);
setDrawable(new TextureRegionDrawable(textureRegion));
}
frameBuffer.begin();
// render content
Gdx.gl.glClearColor(0, 1, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.setColor(Color.WHITE);
shapeRenderer.rect(0, 0, frameBuffer.getWidth() / 2, frameBuffer.getHeight() / 2);
shapeRenderer.end();
if (frameBuffer != null) {
frameBuffer.end();
}
super.draw(batch, parentAlpha);
}
}
When deleting the ShapeRenderer part I can see the green background in the scene. But as soon as I use the ShapeRenderer the content is black. There is no white rectangle visible.
Any ideas what I am doing wrong?
Just found out that using my own SpriteBatch (with begin() and end()) after the FrameBuffer end() it works. So the problem seems to have to do with the calling order of the FrameBuffers methods and the SpriteBatches methods. Ending the given actor batch before beginning the FrameBuffer and "re"-beginning it to draw the actor is also working (see comment above).
I want an actor that draws a drawable, but clips it to the size of the actor. I'm deriving this class from Widget, and using some hard-coded values as a simple test:
public class MyWidget extends Widget {
public MyWidget(Drawable drawable) {
setDrawable(drawable);
setSize(100, 100);
}
public void draw(Batch batch, float parentAlpha) {
clipBegin(getX(), getY(), 20, 20);
drawable.draw(batch, getX(), getY(), 500, 500);
clipEnd();
}
}
No clipping is performed though, the drawable spills out of the bounds of the actor. This actor is part of a Table, if it matters. I believe I am using the clipBegin() / clipEnd() methods incorrectly. What is the right way to do this?
Thanks
This is what I found based on the comments and my own experimentation. It's important to flush the batch before starting the clip and after drawing to ensure the proper drawing gets clipped.
public void draw(Batch batch, float parentAlpha) {
batch.flush();
if (clipBegin(getX(), getY(), 20.0f, 20.0f)) {
//do your drawing here
drawable.draw(batch, getX(), getY(), 500, 500);
batch.flush();
clipEnd();
}
}
I simply want to fade-out (opacity = completely transparent) a button after I've pressed it... the following code has the unexplainable effect of fading the background image (a totally different actor!) to black !
What am I doing wrong ?
Skin skin = new Skin();
TextureAtlas buttonAtlas = new TextureAtlas(Gdx.files.internal("gfx/menu_buttons.pack"));
skin.addRegions(buttonAtlas);
TextButtonStyle textButtonStyle = new TextButtonStyle();
textButtonStyle.font = mButtonSpacefont;
textButtonStyle.up = skin.getDrawable("menu_button_background_top");
textButtonStyle.down = skin.getDrawable("menu_button_background_bottom");
mButtonStartGame = new TextButton("Play", textButtonStyle);
mButtonStartGame.setPosition(game.getIdealWidth()/2 - mButtonStartGame.getWidth()/2,
game.getIdealHeight()/2 - mButtonStartGame.getHeight()/2);
mButtonStartGame.addListener(new ChangeListener()
{
#Override
public void changed (ChangeEvent event, Actor actor)
{
//triggers when button is pressed and let go
mButtonStartGame.addAction(Actions.fadeOut( 1.0f ));
}
});
// add actors to stage
mStage.addActor(backgroundActor);//background
mStage.addActor(titleActor);//ontop of background
mStage.addActor(mButtonStartGame);//ontop of background
UPDATE 1:
I've discovered that the TextButton is faded out - BUT - so is the actor that contains the background image backgroundActor ! Why would the backgroundActor be faded when the code doesn't even call backgroundActor.addAction(Actions.fadeOut( 1.0f )); ??
UPDATE 2:
The render() method seems to play a part... when I call Gdx.gl.glClearColor(0, 0, 0, 0); the whole screen (except for the titleActor!) turns black due to the fadeOut action. When I call Gdx.gl.glClearColor(1, 1, 1, 1); the whole screen (except for the titleActor!) turns white.
#Override
public void render(float delta)
{
Gdx.gl.glClearColor(0, 0, 0, 0);//clear the screen black
//Gdx.gl.glEnable(GL20.GL_BLEND);// no effect, so commented out
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// update the actors
mStage.act(Gdx.graphics.getDeltaTime());
// draw the actors
mStage.draw();
}
The solution was that all of my actor's need to take into consideration the parentAlpha and set the color with batch.setColor().
Since my background was an actor, and I wasn't setting the batch color, the background was screwed up.
for example:
public class ActorBackground extends Actor
{
// Member Variables
private Texture mTexture;
// Constructor
public ActorBackground(GFXLoader gfxloader)
{
mTexture = new Texture(gfxloader.loadGraphic("menu_background"));// returns Gdx.files.internal(file.path())
//setBounds(getX(), getY(), mTexture.getWidth(), mTexture.getHeight());
setWidth(mTexture.getWidth());
setHeight(mTexture.getHeight());
}
#Override
public void draw(Batch batch, float parentAlpha)
{
// needed to make actions work
super.act(Gdx.graphics.getDeltaTime());
// needed to make fade work
Color color = new Color(this.getColor().r, this.getColor().g, this.getColor().b, this.getColor().a * parentAlpha);
batch.setColor(color);
// show it
batch.draw(mTexture, getX(), getY(), getWidth(), getHeight());
}
}