3
\$\begingroup\$

I'm experimenting with Scene2D to see if it fits fot the game I want to develop. Say I have an Actor with the origin in the center of its TextureRegion.

My setup method contains this code:

float width = WorldUtils.pixelsToMeters(Assets.bullet.getRegionWidth());
float height = WorldUtils.pixelsToMeters(Assets.bullet.getRegionHeight());

setPosition(x, y);
setOrigin(width / 2, height / 2);
setSize(width, height);
setRotation(angle);

Where WorldUtils.pixelsToMeters(float) is just a method to convert pixels to world units (basically 64px = 1 meter).

My draw() method is like this:

@Override
public void draw(SpriteBatch batch, float parentAlpha) {
    batch.setColor(getColor().r, getColor().g, getColor().b, getColor().a);
    batch.draw(Assets.bullet, getX()-getOriginX(), getY()-getOriginY(), getOriginX(), getOriginY(),
               getWidth(), getHeight(), 1, 1, getRotation());
}

This way the actor's position is equal to its center position. This simplifies a lot of stuff like moving the actor to a specific (x, y) in the game world. Otherwise everytime I have to use this actor's position I have to take in account for its screen representation's size... and it doesn't make much sense.

But the way I setup things come at the cost of messing up with event handling. From what I understand Scene2D event handling assumes I'm using (0, 0) as origin of the actor's bounding box. So when I touch/click on my actor during execution it can handle only the ones slightly up-right it real position (obviously).

Is there a way to fix this without touching the library code? I would like to handle certain objects with origin in the center and others with origin in the bottom-left corner.

Maybe I misunderstood how to setup my actor?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Answering my own question:

Looking at Actor's code, it seems to be as simple as overriding the default hit() method.

The original code is:

public Actor hit (float x, float y, boolean touchable) {
    if (touchable && this.touchable != Touchable.enabled) return null;
    return x >= 0 && x < width && y >= 0 && y < height ? this : null;
}

While my new code is:

public class NewActor extends Actor {
    @Override
    public Actor hit(float x, float y, boolean touchable) {
        if (touchable && getTouchable() != Touchable.enabled) return null;
        return x >= -getOriginX() && x < (getWidth() - getOriginX())
                && y >= -getOriginY() && y < (getHeight() - getOriginY()) ? this : null;
    }
}

It's worth mentioning that hit()'s x and y are relative to the Actor position, so I just translate the original bounds check by (-getOriginX(), -getOriginY()).

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .