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\$
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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.