0
votes

I managed to create a text from .*ttf and now i have a BitmapFont object. I want to use it as an Actor. In Actor`s method draw() i used:

 FontRed.draw(batch, "Some text!", getX(), getY());

A text was displayed, but a Listener did not work. When i tried to take a region from BitmapFont: batch.draw(FontRed.getRegion(), getX(), getY(), getWidth(), getHeight());

i saw a lot of strange symbols instead of my text on the screen, but my listener worked.

I think it is closely connected with that fact, that spritebatch is sent in method draw() of the BitmapFont. This is my full code:

public class Text extends Actor {
private BitmapFont FontRed;
private FreeTypeFontGenerator generator;
FreeTypeFontParameter parameter;
String FONT_CHARS = "";

public Text(GameStateManager gsm){
    generator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/myfont.ttf"));
    for( int i = 32; i < 127; i++ ) FONT_CHARS += (char)i; 
    for( int i = 1024; i < 1104; i++ ) FONT_CHARS += (char)i;
    parameter = new FreeTypeFontParameter();
    parameter.characters = FONT_CHARS;
    parameter.size = 82;
    parameter.color= Color.RED;
    FontRed = generator.generateFont(parameter);
    generator.dispose();
    setPosition(30, 300);
    setSize(182, 182);
    this.addListener(new Listener(gsm));
}

@Override
public void draw(Batch batch, float parentAlpha) {
    FontRed.draw(batch, "Some text!", getX(), getY());
   // batch.draw(FontRed.getRegion(), getX(), getY(), getWidth(), getHeight());

}

@Override
public void act(float delta) {
}

class Listener extends InputListener {
    GameStateManager gsm;
    Listener(GameStateManager gsm){
        this.gsm = gsm;
    }

    @Override
    public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
        event.getListenerActor().setColor(Color.GREEN);
        System.out.println("it works");
        return true;
    }

    @Override
    public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
        gsm.push(new PlayState(gsm));
    }
}

}

So please explain me why the listner in Actor doesn't work when spritebatch is sent in BitmapFont's method draw() and how can i make a texture from BitmapFont for using it in batch.draw()?

1
The way in which the actor is drawn is wholly independent from any listeners so there must be something else going on. How are you determining if the listener is working? Right now you have it setting the actor's color, but you aren't using the actor's color when drawing it, so that won't be visible. Are you saying the "it works" log only happens when you draw the font region? They have no relation.Tenfour04
@Tenfour04, setting actor's color doesn't matter, i forgot to delete it. I mean System.out.println("it works"); doesn't work when i draw FontRed.draw(batch, "Some text!", getX(), getY()); But when i draw batch.draw(FontRed.getRegion(), getX(), getY(), getWidth(), getHeight()); i see stupid symbols instead of my text but listener works. You say they have no relation. But what to do? Please, help me.Daniil Andashev
Check it again. You'll see if you look at the source code of Stage and Actor that what you're describing is impossible. There must be some other change you made.Tenfour04

1 Answers

0
votes

As the commenters mention, the way the Actor is drawn has nothing to do with whether the Listener should work if you click within the 182 x 182 box that defines the Actor's bounds. When you draw using this line:

batch.draw(FontRed.getRegion(), getX(), getY(), getWidth(), getHeight());

you are drawing the texture that defines the font (which is a texture with every character in the font squished together) in exactly the Actor's region, so when you click on the visible texture, the Listener fires. When you draw using this line:

FontRed.draw(batch, "Some text!", getX(), getY());

you are drawing text in a way that has nothing to do with the Actor's bounds. The coordinates arguments to the BitmapFont .draw() method define the top left corner of the text, whereas the x and y coordinates of an Actor define the bottom left corner. When you draw using that line of code, the text is drawn below the Actor's bounds. If you click above the text, your Listener should fire.

If you want to make an Actor with a Listener which fires only when you click on the text itself, you can use a GlyphLayout to determine the bounds of the text as drawn with your font, and use that to set the Actor's bounds:

GlyphLayout layout = new GlyphLayout(FontRed, "Some text!");
setSize(layout.width, layout.height);

Then, when you draw the text, draw with respect to the Actor's top left corner:

FontRed.draw("Some text!", getX(), getY(Align.topLeft));

However, I do not recommend using this approach. If you want to make a text object that responds to clicks, I suggest you use a class from scene2d.ui such as Label or Button. These classes give you a lot of control and make it easy to do things like give your text a background, put padding between the text and the bounds of the Actor, and align the text within the Actor.