Some Actions do not work - libgdx

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.

Related

Change the color of one word in a phrase using label, libgdx?

Is it possible to change the colour of one word in a
phrase using Label in libgdx, my idea is on my dialog box some importante words like important places, or names have a different color than the rest of the text to make them stand out.
I think you don't need to use any third party artifact, LibGDX has built in API for your requirement. You can use color markup language, that Label supports as well.
Enable markupEnabled on the BitmapFont
font.getData().markupEnabled = true;
I've some code
public class MyGdxGame extends ApplicationAdapter {
private Stage stage;
private BitmapFont bitmapFont;
#Override
public void create () {
stage=new Stage();
bitmapFont=new BitmapFont(Gdx.files.internal("Roboto-Medium_24.fnt"));
bitmapFont.getData().markupEnabled=true;
bitmapFont.getRegion().getTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
Label label=new Label("Welcome to [BLUE]LibGDX, []Game development framework \n" +
"\nPublish your games on [GREEN]Windows,[] [#00FFFF]Mac, []Linux, [#FFFF00]Android,[] [BLACK]iOS,[] BlackBerry and HTML5, all with the same code base. ",new Label.LabelStyle(bitmapFont, Color.WHITE));
label.setPosition(20,340);
label.setWrap(true);
label.setWidth(500);
stage.addActor(label);
}
#Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
}
#Override
public void dispose () {
stage.dispose();
bitmapFont.dispose();
}
}
Output :

Check collision of 2 objects in libgdx

I am making a game in libgdx, where you shoot aliens with bullets. I have 2 ArrayLists of objects and would like to check if any of objects in bulletArrayList is colliding with any object from alienArrayList. What is the best way to do that? I was thinking of contactListener.
In the screen class I am generating objects like this:
public class PlayScreen implements Screen, InputProcessor,ContactListener {
public ArrayList<Alien> alienArrayList = new ArrayList<Alien>();
public ArrayList<Bullet> bulletArrayList = new ArrayList<Bullet>();
public void generateAlien() {
alien = new Alien();
alienArrayList.add(alien);
}
public void shootBullet(float x, float y) {
//send x,y moving coordiantes
bullet = new Bullet(x,y);
bulletArrayList.add(bullet);
}
}
In object class I have Rectangle box which i am moving like this:
public class Alien {
public Alien() {
bound = new Rectangle( x, y, alienRegion.getRegionWidth(), alienRegion.getRegionHeight());
}
public void update(float delta) {
bound.y -= speed * delta;
}
public void render(SpriteBatch batch, float delta) {
update(delta);
elapsedTime += Gdx.graphics.getDeltaTime();
alienRegion = (TextureRegion) alien.getKeyFrame(elapsedTime, true);
batch.draw(alienRegion, getBound().x, getBound().y);
}
}
Because you are using Rectangles in your Alien class, we can use a class called Intersector which has static methods to check for collision detection.
for(Alien alien1: alienArrayList) {
for(Alien alien2 : bulletArrayList) {
if(Intersector.overlaps(alien1.rect, alien2.rect)) {
// Collision code
}
}
}
First, we iterate through the two lists using a nested special for loop. Then we pass two Rectangles to the Intersector.overlaps(rect1, rect2). This is a static method defined in the Intersector class which will return true if the rectangles are overlapping.
Also, this code can go straight into your render method.
This code is not the most optimized because it will check 2 rects twice however, I will leave the optimization to you.
I hope that this answer was helpful and if you have any further questions please feel free to post a comment below.

How to create an ImageButton with multiple Sprite/Texture layers in LibGDX?

I'm designing a game that requires generating a vast array of buttons, with different combinations of background colors and outlines. I already have a Sprite for the background and a Sprite for the outline and apply tints to each.
I've already tried to join both on a SpriteBatch but have had no luck converting it to a structure that ImageButton supports.
Thanks in advance.
You could make your own version of an ImageButton by extending the Actor class and implementing your own methods for drawing. The example below isn't tested but should give you and idea on how to make your own Custom button:
private class LayeredButton extends Actor{
private int width = 100;
private int height = 75;
private Texture backGround;
private Texture foreGround;
private Texture outline;
public LayeredButton(Texture bg, Texture fg, Texture ol){
setBounds(this.getX(),this.getY(),this.width,this.height);
backGround = bg;
foreGround = fg;
outline = ol;
addListener(new InputListener(){
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
// do something on click here
return true;
}
});
}
#Override
public void draw(Batch batch, float alpha){
// draw from back to front
batch.draw(backGround,this.getX(),this.getY());
batch.draw(foreGround,this.getX(),this.getY());
batch.draw(outline,this.getX(),this.getY());
}
#Override
public void act(float delta){
// do stuff to button
}
}

Actor in Stage Does Not Update the MoveTo XY Location

I am creating a game wherein an apple is being shot with an arrow. The apple's location is the XY location of the user input and the arrow actor has to move to that location using the code actor.moveto. The problem is the arrow only moves only once to the user input's direction. I know that the moveTo action of the actor is updated many times per second when I called stageArrow.act in the update method so I am wondering why the arrow only moves once. Here's my code:
appleclass.java
public class AppleClass implements Screen {
Arrow arrow;
private final MainApp app;
public Image ShotImage;
public AppleClass(final MainApp app){
this.app = app;
this.stageApple = new Stage(new StretchViewport(app.screenWidth,app.screenHeight , app.camera));
this.stageArrow =new Stage(new StretchViewport(app.screenWidth,app.screenHeight , app.camera));
arrow = new ArrowClass(app);
}
#Override
public void show() {
InputMultiplexer inputMultiplexer = new InputMultiplexer();
inputMultiplexer.addProcessor(stageApple);
inputMultiplexer.addProcessor(stageArrow);
Gdx.input.setInputProcessor(inputMultiplexer);
arrow();
}
public void arrow(){
arrow.isTouchable();
stageArrow.addActor(arrow);
arrow.addAction((moveTo(Gdx.input.getX(),Gdx.input.getY(),0.3f))); //===> only executes once.
arrow.addListener(new InputListener(){
public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor){
if (Gdx.input.isTouched()){
ShotImage.setVisible(true);
}
}
});}
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
update(delta);
}
public void update(float deltaTime){
stageApple.draw();
stageArrow.draw();
stageApple.act(deltaTime);
stageArrow.act(deltaTime);
}
ArrowClass.java
public class ArrowClass extends Actor {
MainApp app;
AppleClass appleClass;
public Texture arrowTexture;
public ArrowClass(final MainApp app){
this.app = app;
arrowTexture = new Texture("medievalarrow.png");
this.setSize(arrowWidth, arrowHeight);
this.setTouchable(Touchable.enabled);
this.setBounds(app.screenWidth*0.45f,0,arrowWidth,arrowHeight);
this.setOrigin(0,0);
}
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
final float delta = Gdx.graphics.getDeltaTime();
this.act(delta);
app.batch.begin();
app.batch.draw(arrowTexture, getX(),getY(),getWidth(),getHeight());
app.batch.end();
}
}
Any help will be highly appreciated. Thanks.
I think the problem is because you are calling this.act(delta) in your ArrowClass' draw method. When you call Stage#act(), it will call the act method on all of its actors for you. Since you're calling it once when you draw and again when you update the stage, it's moving at twice the normal speed and that could be causing it to reach its destination prematurely.
A few other comments about your code, if I may:
First, you probably don't want two separate stages- unless you're using Scene2D.UI, you would normally have a single stage with Arrow and Apple added to it as actors.
Second, when you override Actor#draw(), you should use the batch it passes you to do the rendering instead of using the one from app. You also don't want to call begin() and end() inside your draw method- these are 'expensive' and you only want to call them once per frame. However, if you just use the batch that is passed to draw(), the Stage class will handle beginning and ending for you and you won't need to call them explicitly.
Third, you actually don't need to call super.draw(batch, parentAlpha) because it's an empty method in the Actor class.
Thus, your class could be simplified to the following:
public class ArrowClass extends Actor {
AppleClass appleClass; // You never set this; you may not need it
Texture arrowTexture;
public ArrowClass(MainApp app, arrowWidth, arrowHeight) {
arrowTexture = new Texture("medievalarrow.png");
this.setSize(arrowWidth, arrowHeight);
this.setTouchable(Touchable.enabled);
this.setBounds(app.screenWidth*0.45f,0,arrowWidth,arrowHeight);
this.setOrigin(0,0);
}
#Override
public void draw(Batch batch, float parentAlpha) {
batch.draw(arrowTexture, getX(),getY(),getWidth(),getHeight());
}
}

LibGDX Scene2d Action affects multiple Actors

I am working on my second app and it went quite well so far. But now I got stuch on a problem I just can´t manage to find a solution for.
I´ve been using scene2d stage to display everything. Now I´ve added a black image which fades out whenever a new Screen is called(as a transition).
My problem is, that when I add the fade out action to my black Image it also fades out the background. Interestingly only the background is affected, no other Actor what so ever.
I´ve tried changing the order of the Actors, putting them into groups, clearing all actions from the background, setting his alpha to 1 but nothing worked.
Thanks for helping me !
For the background:
public class BackgroundColor extends Actor {
public BackgroundColor(int x) {
this.setBounds(x, 0, 270, 960);
}
public void act(float delta) {
}
public void draw(Batch batch, float alpha) {
batch.draw(image, this.getX(), this.getY(), this.getWidth(), this.getHeight());
}
}
For the screen:
public class GameScreen implements Screen {
public Stage stage;
public BackgroundColor backgroundColor;
public Image black;
public GameScreen() {
stage = new Stage(new ExtendViewport(540, 900, 540, 960));
Gdx.input.setInputProcessor(stage);
setupStage();
}
private void setupStage() {
backgroundColor = new BackgroundColor(0);
stage.addActor(backgroundColor);
//this is the black layer
black = new Image(AssetLoader.black);
black.setBounds(0, 0, stage.getWidth(), stage.getHeight());
stage.addActor(black);
black.addAction(Actions.sequence(Actions.fadeOut((float)0.5), Actions.touchable(null)));
}
#Override
public void show() {
}
#Override
public void render(float deltaTime) {
Gdx.gl.glClear(0);
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
So, I kinda figured it out...
apparently having a different Image as the first layer of the stage solves the issue.
I added in a random Image before the backgroundColor = new BackgroundColor(0); and that fixed it.
I still have no Idea what causes this, maybe I missed something...
Would be great if you could tell me what is going on here!
Cheers